Skip to content

Commit d9f114a

Browse files
committed
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.
1 parent a17c167 commit d9f114a

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

fuzz/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,9 @@ name = "dhcp_header"
3434
path = "fuzz_targets/dhcp_header.rs"
3535
test = false
3636
doc = false
37+
38+
[[bin]]
39+
name = "ieee802154_header"
40+
path = "fuzz_targets/ieee802154_header.rs"
41+
test = false
42+
doc = false
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
use smoltcp::wire::{Ieee802154Frame, Ieee802154Repr};
4+
5+
fuzz_target!(|data: &[u8]| {
6+
if let Ok(ref frame) = Ieee802154Frame::new_checked(data) {
7+
if let Ok(repr) = Ieee802154Repr::parse(frame) {
8+
// The buffer len returns only the lenght required for emitting the header
9+
// and does not take into account the length of the payload.
10+
let mut buffer = vec![0; repr.buffer_len()];
11+
12+
// NOTE: unchecked because the checked version checks if the addressing mode field
13+
// is valid or not. The addressing mode field is required for calculating the length of
14+
// the header, which is used in `check_len`.
15+
let mut frame = Ieee802154Frame::new_unchecked(&mut buffer[..]);
16+
repr.emit(&mut frame);
17+
}
18+
};
19+
});

src/wire/ieee802154.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,24 @@ impl<T: AsRef<[u8]>> Frame<T> {
251251
pub fn check_len(&self) -> Result<()> {
252252
// We need at least 3 bytes
253253
if self.buffer.as_ref().len() < 3 {
254-
Err(Error::Truncated)
255-
} else {
256-
Ok(())
254+
return Err(Error::Truncated);
257255
}
256+
257+
let mut offset = field::ADDRESSING.start + 2;
258+
259+
// Calculate the size of the addressing field.
260+
offset += self.dst_addressing_mode().size();
261+
offset += self.src_addressing_mode().size();
262+
263+
if !self.pan_id_compression() {
264+
offset += 2;
265+
}
266+
267+
if offset > self.buffer.as_ref().len() {
268+
return Err(Error::Truncated);
269+
}
270+
271+
Ok(())
258272
}
259273

260274
/// Consumes the frame, returning the underlying buffer.

0 commit comments

Comments
 (0)