|  | @@ -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<AddressFuzzer> 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<AddressFuzzer>,
 | 
	
		
			
				|  |  | +    ll_dst_addr: Option<AddressFuzzer>,
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +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(_) => (),
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +});
 |