From 76f1b81182cde176ff49c43f7b20090cf61c608d Mon Sep 17 00:00:00 2001 From: Thibaut Vandervelden Date: Thu, 4 Nov 2021 11:33:26 +0100 Subject: [PATCH] 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. --- fuzz/Cargo.toml | 6 ++++++ fuzz/fuzz_targets/ieee802154_header.rs | 19 +++++++++++++++++++ src/wire/ieee802154.rs | 20 +++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 fuzz/fuzz_targets/ieee802154_header.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 0db822f..8cbb5db 100644 --- a/fuzz/Cargo.toml +++ b/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 diff --git a/fuzz/fuzz_targets/ieee802154_header.rs b/fuzz/fuzz_targets/ieee802154_header.rs new file mode 100644 index 0000000..af54f88 --- /dev/null +++ b/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); + } + }; +}); diff --git a/src/wire/ieee802154.rs b/src/wire/ieee802154.rs index aca402e..41df5e1 100644 --- a/src/wire/ieee802154.rs +++ b/src/wire/ieee802154.rs @@ -251,10 +251,24 @@ impl> Frame { 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.