浏览代码

Add fuzzing for IEEE802.15.4

Because IEEE802.15.4 uses a lot of compression in its frame, fuzzing it
is maybe a good idea. Adding this fuzz target showed that some frame
methods were panicking. `check_len` now checks if accessors will panic
or not.

I ran the fuzzer for about 15 minutes and nothing showed up.
Thibaut Vandervelden 3 年之前
父节点
当前提交
d9f114a2ab
共有 3 个文件被更改,包括 42 次插入3 次删除
  1. 6 0
      fuzz/Cargo.toml
  2. 19 0
      fuzz/fuzz_targets/ieee802154_header.rs
  3. 17 3
      src/wire/ieee802154.rs

+ 6 - 0
fuzz/Cargo.toml

@@ -34,3 +34,9 @@ name = "dhcp_header"
 path = "fuzz_targets/dhcp_header.rs"
 test = false
 doc = false
+
+[[bin]]
+name = "ieee802154_header"
+path = "fuzz_targets/ieee802154_header.rs"
+test = false
+doc = false

+ 19 - 0
fuzz/fuzz_targets/ieee802154_header.rs

@@ -0,0 +1,19 @@
+#![no_main]
+use libfuzzer_sys::fuzz_target;
+use smoltcp::wire::{Ieee802154Frame, Ieee802154Repr};
+
+fuzz_target!(|data: &[u8]| {
+    if let Ok(ref frame) = Ieee802154Frame::new_checked(data) {
+        if let Ok(repr) = Ieee802154Repr::parse(frame) {
+            // The buffer len returns only the lenght required for emitting the header
+            // and does not take into account the length of the payload.
+            let mut buffer = vec![0; repr.buffer_len()];
+
+            // NOTE: unchecked because the checked version checks if the addressing mode field
+            // is valid or not. The addressing mode field is required for calculating the length of
+            // the header, which is used in `check_len`.
+            let mut frame = Ieee802154Frame::new_unchecked(&mut buffer[..]);
+            repr.emit(&mut frame);
+        }
+    };
+});

+ 17 - 3
src/wire/ieee802154.rs

@@ -251,10 +251,24 @@ impl<T: AsRef<[u8]>> Frame<T> {
     pub fn check_len(&self) -> Result<()> {
         // We need at least 3 bytes
         if self.buffer.as_ref().len() < 3 {
-            Err(Error::Truncated)
-        } else {
-            Ok(())
+            return Err(Error::Truncated);
         }
+
+        let mut offset = field::ADDRESSING.start + 2;
+
+        // Calculate the size of the addressing field.
+        offset += self.dst_addressing_mode().size();
+        offset += self.src_addressing_mode().size();
+
+        if !self.pan_id_compression() {
+            offset += 2;
+        }
+
+        if offset > self.buffer.as_ref().len() {
+            return Err(Error::Truncated);
+        }
+
+        Ok(())
     }
 
     /// Consumes the frame, returning the underlying buffer.