diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 98bd4d0f..b3357eba 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -43,13 +43,7 @@ test = false doc = false [[bin]] -name = "sixlowpan_udp_header" -path = "fuzz_targets/sixlowpan_udp_header.rs" -test = false -doc = false - -[[bin]] -name = "sixlowpan_iphc_header" -path = "fuzz_targets/sixlowpan_iphc_header.rs" +name = "sixlowpan_packet" +path = "fuzz_targets/sixlowpan_packet.rs" test = false doc = false diff --git a/fuzz/fuzz_targets/sixlowpan_iphc_header.rs b/fuzz/fuzz_targets/sixlowpan_iphc_header.rs deleted file mode 100644 index 3ed012b0..00000000 --- a/fuzz/fuzz_targets/sixlowpan_iphc_header.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![no_main] -use libfuzzer_sys::fuzz_target; -use smoltcp::wire::{Ieee802154Address, SixlowpanIphcPacket, SixlowpanIphcRepr}; - -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, arbitrary::Arbitrary)] -pub enum AddressFuzzer { - Absent, - Short([u8; 2]), - Extended([u8; 8]), -} - -impl From for Ieee802154Address { - fn from(val: AddressFuzzer) -> Self { - match val { - AddressFuzzer::Absent => Ieee802154Address::Absent, - AddressFuzzer::Short(b) => Ieee802154Address::Short(b), - AddressFuzzer::Extended(b) => Ieee802154Address::Extended(b), - } - } -} - -#[derive(Debug, arbitrary::Arbitrary)] -struct SixlowpanIphcPacketFuzzer<'a> { - data: &'a [u8], - ll_src_addr: Option, - ll_dst_addr: Option, -} - -fuzz_target!(|fuzz: SixlowpanIphcPacketFuzzer| { - if let Ok(ref frame) = SixlowpanIphcPacket::new_checked(fuzz.data) { - if let Ok(repr) = SixlowpanIphcRepr::parse( - frame, - fuzz.ll_src_addr.map(Into::into), - fuzz.ll_dst_addr.map(Into::into), - ) { - let mut buffer = vec![0; repr.buffer_len()]; - - let mut frame = SixlowpanIphcPacket::new_unchecked(&mut buffer[..]); - repr.emit(&mut frame); - } - }; -}); diff --git a/fuzz/fuzz_targets/sixlowpan_packet.rs b/fuzz/fuzz_targets/sixlowpan_packet.rs new file mode 100644 index 00000000..d9ba99bb --- /dev/null +++ b/fuzz/fuzz_targets/sixlowpan_packet.rs @@ -0,0 +1,240 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; +use smoltcp::{phy::ChecksumCapabilities, wire::*}; + +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, arbitrary::Arbitrary)] +pub enum AddressFuzzer { + Absent, + Short([u8; 2]), + Extended([u8; 8]), +} + +impl From for Ieee802154Address { + fn from(val: AddressFuzzer) -> Self { + match val { + AddressFuzzer::Absent => Ieee802154Address::Absent, + AddressFuzzer::Short(b) => Ieee802154Address::Short(b), + AddressFuzzer::Extended(b) => Ieee802154Address::Extended(b), + } + } +} + +#[derive(Debug, arbitrary::Arbitrary)] +struct SixlowpanPacketFuzzer<'a> { + data: &'a [u8], + ll_src_addr: Option, + ll_dst_addr: Option, +} + +fuzz_target!(|fuzz: SixlowpanPacketFuzzer| { + match SixlowpanPacket::dispatch(fuzz.data) { + Ok(SixlowpanPacket::FragmentHeader) => { + if let Ok(frame) = SixlowpanFragPacket::new_checked(fuzz.data) { + if let Ok(repr) = SixlowpanFragRepr::parse(&frame) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut frame = SixlowpanFragPacket::new_unchecked(&mut buffer[..]); + repr.emit(&mut frame); + } + } + } + Ok(SixlowpanPacket::IphcHeader) => { + if let Ok(frame) = SixlowpanIphcPacket::new_checked(fuzz.data) { + if let Ok(iphc_repr) = SixlowpanIphcRepr::parse( + &frame, + fuzz.ll_src_addr.map(Into::into), + fuzz.ll_dst_addr.map(Into::into), + ) { + let mut buffer = vec![0; iphc_repr.buffer_len()]; + let mut iphc_frame = SixlowpanIphcPacket::new_unchecked(&mut buffer[..]); + iphc_repr.emit(&mut iphc_frame); + + let payload = frame.payload(); + match iphc_repr.next_header { + SixlowpanNextHeader::Compressed => { + if let Ok(p) = SixlowpanNhcPacket::dispatch(payload) { + match p { + SixlowpanNhcPacket::ExtHeader => { + if let Ok(frame) = + SixlowpanExtHeaderPacket::new_checked(payload) + { + if let Ok(repr) = SixlowpanExtHeaderRepr::parse(&frame) + { + let mut buffer = vec![0; repr.buffer_len()]; + let mut ext_header_frame = + SixlowpanExtHeaderPacket::new_unchecked( + &mut buffer[..], + ); + repr.emit(&mut ext_header_frame); + } + } + } + SixlowpanNhcPacket::UdpHeader => { + if let Ok(frame) = + SixlowpanUdpNhcPacket::new_checked(payload) + { + if let Ok(repr) = SixlowpanUdpNhcRepr::parse( + &frame, + &iphc_repr.src_addr, + &iphc_repr.dst_addr, + ) { + let mut buffer = vec![ + 0; + repr.header_len() + + frame.payload().len() + ]; + let mut udp_packet = + SixlowpanUdpNhcPacket::new_unchecked( + &mut buffer[..], + ); + repr.emit( + &mut udp_packet, + &iphc_repr.src_addr, + &iphc_repr.dst_addr, + frame.payload().len(), + |b| b.copy_from_slice(frame.payload()), + ); + } + } + } + } + } + } + SixlowpanNextHeader::Uncompressed(proto) => match proto { + IpProtocol::HopByHop => { + if let Ok(frame) = Ipv6HopByHopHeader::new_checked(payload) { + if let Ok(repr) = Ipv6HopByHopRepr::parse(&frame) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut hop_by_hop_frame = + Ipv6HopByHopHeader::new_unchecked(&mut buffer[..]); + repr.emit(&mut hop_by_hop_frame); + } + } + } + IpProtocol::Icmp => { + if let Ok(frame) = Icmpv4Packet::new_checked(payload) { + if let Ok(repr) = + Icmpv4Repr::parse(&frame, &ChecksumCapabilities::default()) + { + let mut buffer = vec![0; repr.buffer_len()]; + let mut icmpv4_packet = + Icmpv4Packet::new_unchecked(&mut buffer[..]); + repr.emit( + &mut icmpv4_packet, + &ChecksumCapabilities::default(), + ); + } + } + } + IpProtocol::Igmp => { + if let Ok(frame) = IgmpPacket::new_checked(payload) { + if let Ok(repr) = IgmpRepr::parse(&frame) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut frame = IgmpPacket::new_unchecked(&mut buffer[..]); + repr.emit(&mut frame); + } + } + } + IpProtocol::Tcp => { + if let Ok(frame) = TcpPacket::new_checked(payload) { + if let Ok(repr) = TcpRepr::parse( + &frame, + &iphc_repr.src_addr.into_address(), + &iphc_repr.dst_addr.into_address(), + &ChecksumCapabilities::default(), + ) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut frame = TcpPacket::new_unchecked(&mut buffer[..]); + repr.emit( + &mut frame, + &iphc_repr.src_addr.into_address(), + &iphc_repr.dst_addr.into_address(), + &ChecksumCapabilities::default(), + ); + } + } + } + IpProtocol::Udp => { + if let Ok(frame) = UdpPacket::new_checked(payload) { + if let Ok(repr) = UdpRepr::parse( + &frame, + &iphc_repr.src_addr.into_address(), + &iphc_repr.dst_addr.into_address(), + &ChecksumCapabilities::default(), + ) { + let mut buffer = + vec![0; repr.header_len() + frame.payload().len()]; + let mut packet = UdpPacket::new_unchecked(&mut buffer[..]); + repr.emit( + &mut packet, + &iphc_repr.src_addr.into_address(), + &iphc_repr.dst_addr.into_address(), + frame.payload().len(), + |b| b.copy_from_slice(frame.payload()), + &ChecksumCapabilities::default(), + ); + } + } + } + IpProtocol::Ipv6Route => { + if let Ok(frame) = Ipv6RoutingHeader::new_checked(payload) { + if let Ok(repr) = Ipv6RoutingRepr::parse(&frame) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut packet = Ipv6RoutingHeader::new(&mut buffer[..]); + repr.emit(&mut packet); + } + } + } + IpProtocol::Ipv6Frag => { + if let Ok(frame) = Ipv6FragmentHeader::new_checked(payload) { + if let Ok(repr) = Ipv6FragmentRepr::parse(&frame) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut frame = + Ipv6FragmentHeader::new_unchecked(&mut buffer[..]); + repr.emit(&mut frame); + } + } + } + IpProtocol::Icmpv6 => { + if let Ok(packet) = Icmpv6Packet::new_checked(payload) { + if let Ok(repr) = Icmpv6Repr::parse( + &iphc_repr.src_addr.into_address(), + &iphc_repr.dst_addr.into_address(), + &packet, + &ChecksumCapabilities::default(), + ) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut packet = + Icmpv6Packet::new_unchecked(&mut buffer[..]); + repr.emit( + &iphc_repr.src_addr.into_address(), + &iphc_repr.dst_addr.into_address(), + &mut packet, + &ChecksumCapabilities::default(), + ); + } + } + } + IpProtocol::Ipv6NoNxt => (), + IpProtocol::Ipv6Opts => { + if let Ok(packet) = Ipv6Option::new_checked(payload) { + if let Ok(repr) = Ipv6OptionRepr::parse(&packet) { + let mut buffer = vec![0; repr.buffer_len()]; + let mut packet = Ipv6Option::new_unchecked(&mut buffer[..]); + repr.emit(&mut packet); + } + } + } + IpProtocol::Unknown(_) => (), + }, + }; + + let mut buffer = vec![0; iphc_repr.buffer_len()]; + + let mut frame = SixlowpanIphcPacket::new_unchecked(&mut buffer[..]); + iphc_repr.emit(&mut frame); + } + }; + } + Err(_) => (), + } +}); diff --git a/fuzz/fuzz_targets/sixlowpan_udp_header.rs b/fuzz/fuzz_targets/sixlowpan_udp_header.rs deleted file mode 100644 index de876a5e..00000000 --- a/fuzz/fuzz_targets/sixlowpan_udp_header.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![no_main] -use libfuzzer_sys::fuzz_target; -use smoltcp::wire::{Ipv6Address, SixlowpanUdpNhcPacket, SixlowpanUdpNhcRepr}; - -#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, arbitrary::Arbitrary)] -pub struct AddressFuzzer(pub [u8; 16]); - -impl From for Ipv6Address { - fn from(val: AddressFuzzer) -> Self { - Ipv6Address(val.0) - } -} - -#[derive(Debug, arbitrary::Arbitrary)] -struct SixlowpanUdpPacketFuzzer<'a> { - data: &'a [u8], - src_addr: AddressFuzzer, - dst_addr: AddressFuzzer, -} - -fuzz_target!(|fuzz: SixlowpanUdpPacketFuzzer| { - if let Ok(ref frame) = SixlowpanUdpNhcPacket::new_checked(fuzz.data) { - if let Ok(repr) = SixlowpanUdpNhcRepr::parse( - frame, - &fuzz.src_addr.into(), - &fuzz.dst_addr.into(), - ) { - let payload = frame.payload(); - let mut buffer = vec![0; repr.header_len() + payload.len()]; - - let mut frame = SixlowpanUdpNhcPacket::new_unchecked(&mut buffer[..]); - repr.emit( - &mut frame, - &fuzz.src_addr.into(), - &fuzz.dst_addr.into(), - payload.len(), - |b| b.copy_from_slice(payload), - ); - } - }; -});