Skip to content

Commit 747bcfd

Browse files
committed
Don't panic when working with invalid PkgLengths (round 2)
The fuzzer still manages to crash the parser with an invalid PkgLength. We were already checking that it's valid when we construct it, so we're adding another check when we try and use it. We should look at this more closely in the future, as I don't think we should necessarily have to do both.
1 parent 034cecb commit 747bcfd

File tree

3 files changed

+27
-11
lines changed

3 files changed

+27
-11
lines changed

aml/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ pub enum AmlError {
613613
UnexpectedEndOfStream,
614614
UnexpectedByte(u8),
615615
InvalidNameSeg,
616+
InvalidPkgLength,
616617
InvalidFieldFlags,
617618
IncompatibleValueConversion,
618619
UnterminatedStringConstant,

aml/src/parser.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,14 @@ where
178178
'c: 'a,
179179
{
180180
move |input: &'a [u8], context| {
181-
let bytes_to_take = (input.len() as u32) - length.end_offset;
181+
/*
182+
* TODO: fuzzing manages to find PkgLengths that correctly parse during construction, but later crash here.
183+
* I would've thought we would pick up all invalid lengths there, so have a look at why this is needed.
184+
*/
185+
let bytes_to_take = match (input.len() as u32).checked_sub(length.end_offset) {
186+
Some(bytes_to_take) => bytes_to_take,
187+
None => return Err((input, context, AmlError::InvalidPkgLength)),
188+
};
182189
take_n(bytes_to_take).parse(input, context)
183190
}
184191
}

aml/src/pkg_length.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ use bit_field::BitField;
88
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
99
pub struct PkgLength {
1010
pub raw_length: u32,
11-
/// The distance from the end of the structure this `PkgLength` refers to, and the end of the
12-
/// stream.
11+
/// The offset in the structure's stream to stop parsing at - the "end" of the PkgLength. We need to track this
12+
/// instead of the actual length encoded in the PkgLength as we often need to parse some stuff between the
13+
/// PkgLength and the explicit-length structure.
1314
pub end_offset: u32,
1415
}
1516

1617
impl PkgLength {
1718
pub fn from_raw_length(stream: &[u8], raw_length: u32) -> Result<PkgLength, AmlError> {
18-
// TODO: might want a more descriptive error
1919
Ok(PkgLength {
2020
raw_length,
21-
end_offset: (stream.len() as u32).checked_sub(raw_length).ok_or(AmlError::UnexpectedEndOfStream)?,
21+
end_offset: (stream.len() as u32).checked_sub(raw_length).ok_or(AmlError::InvalidPkgLength)?,
2222
})
2323
}
2424

@@ -44,7 +44,6 @@ where
4444
Ok(pkg_length) => Ok((new_input, context, pkg_length)),
4545
Err(err) => Err((input, context, err)),
4646
}
47-
// Ok((new_input, context, try_with_context!(context, PkgLength::from_raw_length(input, raw_length))))
4847
}
4948
}
5049

@@ -124,6 +123,19 @@ mod tests {
124123
check_err!(pkg_length().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
125124
test_correct_pkglength(&[0x00], 0, &[]);
126125
test_correct_pkglength(&[0x05, 0xf5, 0x7f, 0x3e, 0x54, 0x03], 5, &[0xf5, 0x7f, 0x3e, 0x54, 0x03]);
126+
127+
check_ok!(
128+
pkg_length()
129+
.feed(|length| crate::parser::take_to_end_of_pkglength(length))
130+
.parse(&[0x05, 0x01, 0x02, 0x03, 0x04, 0xff, 0xff, 0xff], &mut context),
131+
&[0x01, 0x02, 0x03, 0x04],
132+
&[0xff, 0xff, 0xff]
133+
);
134+
}
135+
136+
#[test]
137+
fn not_enough_pkglength() {
138+
let mut context = make_test_context();
127139
check_err!(
128140
pkg_length().parse(&[0b11000000, 0xff, 0x4f], &mut context),
129141
AmlError::UnexpectedEndOfStream,
@@ -134,10 +146,6 @@ mod tests {
134146
#[test]
135147
fn not_enough_stream() {
136148
let mut context = make_test_context();
137-
check_err!(
138-
pkg_length().parse(&[0x05, 0xf5], &mut context),
139-
AmlError::UnexpectedEndOfStream,
140-
&[0x05, 0xf5]
141-
);
149+
check_err!(pkg_length().parse(&[0x05, 0xf5], &mut context), AmlError::InvalidPkgLength, &[0x05, 0xf5]);
142150
}
143151
}

0 commit comments

Comments
 (0)