Kaynağa Gözat

Return error if PkgLength is longer than remaining stream

Isaac Woods 4 yıl önce
ebeveyn
işleme
5ab486d1a8
3 değiştirilmiş dosya ile 33 ekleme ve 22 silme
  1. 12 11
      aml/src/lib.rs
  2. 19 10
      aml/src/pkg_length.rs
  3. 2 1
      aml/src/type1.rs

+ 12 - 11
aml/src/lib.rs

@@ -183,7 +183,7 @@ impl AmlContext {
             return Err(AmlError::UnexpectedEndOfStream);
         }
 
-        let table_length = PkgLength::from_raw_length(stream, stream.len() as u32) as PkgLength;
+        let table_length = PkgLength::from_raw_length(stream, stream.len() as u32).unwrap();
         match term_object::term_list(table_length).parse(stream, self) {
             Ok(_) => Ok(()),
             Err((_, _, err)) => {
@@ -209,16 +209,17 @@ impl AmlContext {
                  */
                 self.namespace.add_level(path.clone(), LevelType::MethodLocals)?;
 
-                let return_value =
-                    match term_list(PkgLength::from_raw_length(&code, code.len() as u32)).parse(&code, self) {
-                        // If the method doesn't return a value, we implicitly return `0`
-                        Ok(_) => Ok(AmlValue::Integer(0)),
-                        Err((_, _, AmlError::Return(result))) => Ok(result),
-                        Err((_, _, err)) => {
-                            error!("Failed to execute control method: {:?}", err);
-                            Err(err)
-                        }
-                    };
+                let return_value = match term_list(PkgLength::from_raw_length(&code, code.len() as u32).unwrap())
+                    .parse(&code, self)
+                {
+                    // If the method doesn't return a value, we implicitly return `0`
+                    Ok(_) => Ok(AmlValue::Integer(0)),
+                    Err((_, _, AmlError::Return(result))) => Ok(result),
+                    Err((_, _, err)) => {
+                        error!("Failed to execute control method: {:?}", err);
+                        Err(err)
+                    }
+                };
 
                 /*
                  * Locally-created objects should be destroyed on method exit (see §5.5.2.3 of the ACPI spec). We do

+ 19 - 10
aml/src/pkg_length.rs

@@ -14,8 +14,12 @@ pub struct PkgLength {
 }
 
 impl PkgLength {
-    pub fn from_raw_length(stream: &[u8], raw_length: u32) -> PkgLength {
-        PkgLength { raw_length, end_offset: stream.len() as u32 - raw_length }
+    pub fn from_raw_length(stream: &[u8], raw_length: u32) -> Result<PkgLength, AmlError> {
+        // TODO: might want a more descriptive error
+        Ok(PkgLength {
+            raw_length,
+            end_offset: (stream.len() as u32).checked_sub(raw_length).ok_or(AmlError::UnexpectedEndOfStream)?,
+        })
     }
 
     /// Returns `true` if the given stream is still within the structure this `PkgLength` refers
@@ -29,14 +33,18 @@ pub fn pkg_length<'a, 'c>() -> impl Parser<'a, 'c, PkgLength>
 where
     'c: 'a,
 {
-    move |input: &'a [u8], context: &'c mut AmlContext| {
+    move |input: &'a [u8], context: &'c mut AmlContext| -> crate::parser::ParseResult<'a, 'c, PkgLength> {
         let (new_input, context, raw_length) = raw_pkg_length().parse(input, context)?;
 
         /*
          * NOTE: we use the original input here, because `raw_length` includes the length of the
          * `PkgLength`.
          */
-        Ok((new_input, context, PkgLength::from_raw_length(input, raw_length)))
+        match PkgLength::from_raw_length(input, raw_length) {
+            Ok(pkg_length) => Ok((new_input, context, pkg_length)),
+            Err(err) => Err((input, context, err)),
+        }
+        // Ok((new_input, context, try_with_context!(context, PkgLength::from_raw_length(input, raw_length))))
     }
 }
 
@@ -97,7 +105,7 @@ mod tests {
         let mut context = make_test_context();
         check_ok!(
             pkg_length().parse(stream, &mut context),
-            PkgLength::from_raw_length(stream, expected_raw_length),
+            PkgLength::from_raw_length(stream, expected_raw_length).unwrap(),
             &expected_leftover
         );
     }
@@ -124,11 +132,12 @@ mod tests {
     }
 
     #[test]
-    #[should_panic]
     fn not_enough_stream() {
-        /*
-         * TODO: Ideally, this shouldn't panic the parser, but return a `UnexpectedEndOfStream`.
-         */
-        test_correct_pkglength(&[0x05, 0xf5], 5, &[0xf5]);
+        let mut context = make_test_context();
+        check_err!(
+            pkg_length().parse(&[0x05, 0xf5], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[0x05, 0xf5]
+        );
     }
 }

+ 2 - 1
aml/src/type1.rs

@@ -59,7 +59,8 @@ where
                 .map_with_context(|((predicate, then_branch), else_branch), context| {
                     let branch = if predicate { then_branch } else { else_branch };
 
-                    match term_list(PkgLength::from_raw_length(branch, branch.len() as u32)).parse(branch, context)
+                    match term_list(PkgLength::from_raw_length(branch, branch.len() as u32).unwrap())
+                        .parse(branch, context)
                     {
                         Ok((_, context, result)) => (Ok(result), context),
                         Err((_, context, err)) => (Err(err), context),