From fe60eae2dbccde7315fe789eeefcaf7940e3d548 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 9 Jan 2025 17:26:40 +0300 Subject: [PATCH 1/8] test(simple-dns): fuzz --- Cargo.lock | 35 ++++++++++++++++++++ Cargo.toml | 2 +- simple-dns/fuzz/.gitignore | 4 +++ simple-dns/fuzz/Cargo.toml | 21 ++++++++++++ simple-dns/fuzz/fuzz_targets/packet_parse.rs | 24 ++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 simple-dns/fuzz/.gitignore create mode 100644 simple-dns/fuzz/Cargo.toml create mode 100644 simple-dns/fuzz/fuzz_targets/packet_parse.rs diff --git a/Cargo.lock b/Cargo.lock index 8d91c9d..99e4ca4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,12 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + [[package]] name = "autocfg" version = "1.3.0" @@ -104,6 +110,8 @@ version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -341,6 +349,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.70" @@ -356,6 +373,16 @@ version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "libfuzzer-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" +dependencies = [ + "arbitrary", + "cc", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -663,6 +690,14 @@ dependencies = [ "criterion", ] +[[package]] +name = "simple-dns-fuzz" +version = "0.0.0" +dependencies = [ + "libfuzzer-sys", + "simple-dns", +] + [[package]] name = "simple-mdns" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index dec1328..9698a89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] resolver = "2" -members = ["simple-dns", "simple-mdns"] +members = ["simple-dns", "simple-mdns", "simple-dns/fuzz"] diff --git a/simple-dns/fuzz/.gitignore b/simple-dns/fuzz/.gitignore new file mode 100644 index 0000000..1a45eee --- /dev/null +++ b/simple-dns/fuzz/.gitignore @@ -0,0 +1,4 @@ +target +corpus +artifacts +coverage diff --git a/simple-dns/fuzz/Cargo.toml b/simple-dns/fuzz/Cargo.toml new file mode 100644 index 0000000..cb91752 --- /dev/null +++ b/simple-dns/fuzz/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "simple-dns-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" + +[dependencies.simple-dns] +path = ".." + +[[bin]] +name = "packet_parse" +path = "fuzz_targets/packet_parse.rs" +test = false +doc = false +bench = false diff --git a/simple-dns/fuzz/fuzz_targets/packet_parse.rs b/simple-dns/fuzz/fuzz_targets/packet_parse.rs new file mode 100644 index 0000000..bca6194 --- /dev/null +++ b/simple-dns/fuzz/fuzz_targets/packet_parse.rs @@ -0,0 +1,24 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; + +use simple_dns::Packet; + +fuzz_target!(|data: &[u8]| { + // fuzzed code goes here + if let Ok(original) = Packet::parse(data) { + let compressed = original.build_bytes_vec_compressed().unwrap(); + + match Packet::parse(&compressed) { + Ok(decompressed) => { + let encoded = decompressed.build_bytes_vec().unwrap(); + + assert_eq!(encoded, original.build_bytes_vec().unwrap()); + } + Err(e) => { + eprintln!("{:?}", original); + panic!("Packet failed to parse: {:?}", e); + } + } + } +}); From 1b360314c72610a473db089290d564dfd69697c1 Mon Sep 17 00:00:00 2001 From: nazeh Date: Thu, 9 Jan 2025 20:55:21 +0300 Subject: [PATCH 2/8] fix(simple-dns): pass packet_parse fuzz test --- simple-dns/fuzz/fuzz_targets/packet_parse.rs | 12 ++--- simple-dns/src/dns/character_string.rs | 10 +++- simple-dns/src/dns/name.rs | 10 ++-- simple-dns/src/dns/question.rs | 14 ++++-- simple-dns/src/dns/rdata/a.rs | 8 ++- simple-dns/src/dns/rdata/aaaa.rs | 8 ++- simple-dns/src/dns/rdata/afsdb.rs | 6 ++- simple-dns/src/dns/rdata/caa.rs | 6 ++- simple-dns/src/dns/rdata/cert.rs | 15 +++--- simple-dns/src/dns/rdata/dhcid.rs | 9 ++-- simple-dns/src/dns/rdata/dnskey.rs | 13 +++-- simple-dns/src/dns/rdata/ds.rs | 19 ++++--- simple-dns/src/dns/rdata/eui.rs | 21 +++----- simple-dns/src/dns/rdata/hinfo.rs | 2 +- simple-dns/src/dns/rdata/ipseckey.rs | 36 ++++++++----- simple-dns/src/dns/rdata/isdn.rs | 2 +- simple-dns/src/dns/rdata/kx.rs | 20 ++++---- simple-dns/src/dns/rdata/loc.rs | 12 ++--- simple-dns/src/dns/rdata/macros.rs | 14 +++--- simple-dns/src/dns/rdata/minfo.rs | 2 +- simple-dns/src/dns/rdata/mod.rs | 3 +- simple-dns/src/dns/rdata/mx.rs | 6 ++- simple-dns/src/dns/rdata/naptr.rs | 10 +++- simple-dns/src/dns/rdata/nsap.rs | 14 ++---- simple-dns/src/dns/rdata/nsec.rs | 53 ++++++++++++++------ simple-dns/src/dns/rdata/null.rs | 2 +- simple-dns/src/dns/rdata/opt.rs | 8 ++- simple-dns/src/dns/rdata/route_through.rs | 5 +- simple-dns/src/dns/rdata/rp.rs | 2 +- simple-dns/src/dns/rdata/rrsig.rs | 20 ++++---- simple-dns/src/dns/rdata/soa.rs | 8 ++- simple-dns/src/dns/rdata/srv.rs | 6 ++- simple-dns/src/dns/rdata/svcb.rs | 26 +++++++--- simple-dns/src/dns/rdata/txt.rs | 6 ++- simple-dns/src/dns/rdata/wks.rs | 6 ++- simple-dns/src/dns/rdata/zonemd.rs | 13 +++-- simple-dns/src/dns/resource_record.rs | 11 +++- simple-dns/src/dns/wire_format.rs | 23 ++++++++- 38 files changed, 273 insertions(+), 188 deletions(-) diff --git a/simple-dns/fuzz/fuzz_targets/packet_parse.rs b/simple-dns/fuzz/fuzz_targets/packet_parse.rs index bca6194..0b5979f 100644 --- a/simple-dns/fuzz/fuzz_targets/packet_parse.rs +++ b/simple-dns/fuzz/fuzz_targets/packet_parse.rs @@ -9,16 +9,10 @@ fuzz_target!(|data: &[u8]| { if let Ok(original) = Packet::parse(data) { let compressed = original.build_bytes_vec_compressed().unwrap(); - match Packet::parse(&compressed) { - Ok(decompressed) => { - let encoded = decompressed.build_bytes_vec().unwrap(); + if let Ok(decompressed) = Packet::parse(&compressed) { + let encoded = decompressed.build_bytes_vec().unwrap(); - assert_eq!(encoded, original.build_bytes_vec().unwrap()); - } - Err(e) => { - eprintln!("{:?}", original); - panic!("Packet failed to parse: {:?}", e); - } + assert_eq!(encoded, original.build_bytes_vec().unwrap()); } } }); diff --git a/simple-dns/src/dns/character_string.rs b/simple-dns/src/dns/character_string.rs index 74f318d..3be72b7 100644 --- a/simple-dns/src/dns/character_string.rs +++ b/simple-dns/src/dns/character_string.rs @@ -48,7 +48,9 @@ impl<'a> TryFrom> for String { } impl<'a> WireFormat<'a> for CharacterString<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 1; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -57,6 +59,10 @@ impl<'a> WireFormat<'a> for CharacterString<'a> { return Err(SimpleDnsError::InvalidCharacterString); } + if *position + 1 + length > data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + let data = &data[*position + 1..*position + 1 + length]; *position += length + 1; @@ -72,7 +78,7 @@ impl<'a> WireFormat<'a> for CharacterString<'a> { } fn len(&self) -> usize { - self.data.len() + 1 + self.data.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/name.rs b/simple-dns/src/dns/name.rs index 9858d0e..9e6e4aa 100644 --- a/simple-dns/src/dns/name.rs +++ b/simple-dns/src/dns/name.rs @@ -73,7 +73,7 @@ impl<'a> Name<'a> { } /// Returns an Iter of this Name Labels - pub fn iter(&'a self) -> std::slice::Iter> { + pub fn iter(&'a self) -> std::slice::Iter<'a, Label<'a>> { self.labels.iter() } @@ -160,7 +160,9 @@ impl<'a> Name<'a> { } impl<'a> WireFormat<'a> for Name<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 1; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -173,7 +175,7 @@ impl<'a> WireFormat<'a> for Name<'a> { let mut name_size = 0usize; loop { - if *position >= data.len() { + if pointer_position >= data.len() { return Err(crate::SimpleDnsError::InsufficientData); } @@ -250,7 +252,7 @@ impl<'a> WireFormat<'a> for Name<'a> { .iter() .map(|label| label.len() + 1) .sum::() - + 1 + + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/question.rs b/simple-dns/src/dns/question.rs index dd72d21..6d3c5c1 100644 --- a/simple-dns/src/dns/question.rs +++ b/simple-dns/src/dns/question.rs @@ -53,11 +53,17 @@ impl<'a> Question<'a> { } impl<'a> WireFormat<'a> for Question<'a> { + const MINIMUM_LEN: usize = 4; + + // Disable redundant length check. fn parse(data: &'a [u8], position: &mut usize) -> crate::Result { + Self::parse_after_check(data, position) + } + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result { let qname = Name::parse(data, position)?; - if *position + 4 > data.len() { - return Err(crate::SimpleDnsError::InsufficientData); - } + + Self::check_len(data, position)?; let qtype = u16::from_be_bytes(data[*position..*position + 2].try_into()?); let qclass = u16::from_be_bytes(data[*position + 2..*position + 4].try_into()?); @@ -73,7 +79,7 @@ impl<'a> WireFormat<'a> for Question<'a> { } fn len(&self) -> usize { - self.qname.len() + 4 + self.qname.len() + Self::MINIMUM_LEN } fn write_to(&self, out: &mut T) -> crate::Result<()> { diff --git a/simple-dns/src/dns/rdata/a.rs b/simple-dns/src/dns/rdata/a.rs index e61ac1d..5910a34 100644 --- a/simple-dns/src/dns/rdata/a.rs +++ b/simple-dns/src/dns/rdata/a.rs @@ -15,7 +15,9 @@ impl RR for A { } impl<'a> WireFormat<'a> for A { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 4; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -28,10 +30,6 @@ impl<'a> WireFormat<'a> for A { out.write_all(&self.address.to_be_bytes()) .map_err(crate::SimpleDnsError::from) } - - fn len(&self) -> usize { - 4 - } } impl A { diff --git a/simple-dns/src/dns/rdata/aaaa.rs b/simple-dns/src/dns/rdata/aaaa.rs index de1989b..2b44d31 100644 --- a/simple-dns/src/dns/rdata/aaaa.rs +++ b/simple-dns/src/dns/rdata/aaaa.rs @@ -15,7 +15,9 @@ impl RR for AAAA { } impl<'a> WireFormat<'a> for AAAA { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 16; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -24,10 +26,6 @@ impl<'a> WireFormat<'a> for AAAA { Ok(Self { address }) } - fn len(&self) -> usize { - 16 - } - fn write_to(&self, out: &mut T) -> crate::Result<()> { out.write_all(&self.address.to_be_bytes()) .map_err(crate::SimpleDnsError::from) diff --git a/simple-dns/src/dns/rdata/afsdb.rs b/simple-dns/src/dns/rdata/afsdb.rs index 720307d..8731201 100644 --- a/simple-dns/src/dns/rdata/afsdb.rs +++ b/simple-dns/src/dns/rdata/afsdb.rs @@ -28,7 +28,9 @@ impl<'a> AFSDB<'a> { } impl<'a> WireFormat<'a> for AFSDB<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 2; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -54,7 +56,7 @@ impl<'a> WireFormat<'a> for AFSDB<'a> { } fn len(&self) -> usize { - self.hostname.len() + 2 + self.hostname.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/caa.rs b/simple-dns/src/dns/rdata/caa.rs index e92a7ea..5a96e80 100644 --- a/simple-dns/src/dns/rdata/caa.rs +++ b/simple-dns/src/dns/rdata/caa.rs @@ -33,7 +33,9 @@ impl<'a> CAA<'a> { } impl<'a> WireFormat<'a> for CAA<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 1; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -54,7 +56,7 @@ impl<'a> WireFormat<'a> for CAA<'a> { } fn len(&self) -> usize { - self.tag.len() + self.value.len() + 1 + self.tag.len() + self.value.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/cert.rs b/simple-dns/src/dns/rdata/cert.rs index 1418360..d520f92 100644 --- a/simple-dns/src/dns/rdata/cert.rs +++ b/simple-dns/src/dns/rdata/cert.rs @@ -16,13 +16,14 @@ pub struct CERT<'a> { pub certificate: Cow<'a, [u8]>, } - impl<'a> RR for CERT<'a> { const TYPE_CODE: u16 = 37; } impl<'a> WireFormat<'a> for CERT<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 5; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -53,7 +54,7 @@ impl<'a> WireFormat<'a> for CERT<'a> { } fn len(&self) -> usize { - 5 + self.certificate.len() + self.certificate.len() + Self::MINIMUM_LEN } } @@ -108,12 +109,8 @@ mod tests { assert_eq!(sample_rdata.type_code, 3); assert_eq!(sample_rdata.key_tag, 0); assert_eq!(sample_rdata.algorithm, 0); - assert_eq!( - *sample_rdata.certificate, - *b"\x00\x00\x00\x00\x00" - ); - + assert_eq!(*sample_rdata.certificate, *b"\x00\x00\x00\x00\x00"); + Ok(()) } - } diff --git a/simple-dns/src/dns/rdata/dhcid.rs b/simple-dns/src/dns/rdata/dhcid.rs index efd5934..f4db8e0 100644 --- a/simple-dns/src/dns/rdata/dhcid.rs +++ b/simple-dns/src/dns/rdata/dhcid.rs @@ -11,7 +11,7 @@ pub struct DHCID<'a> { /// Digest type code pub digest_type: u8, /// Digest (length depends on digest type) - pub digest: Cow<'a, [u8]> + pub digest: Cow<'a, [u8]>, } impl<'a> RR for DHCID<'a> { @@ -19,7 +19,9 @@ impl<'a> RR for DHCID<'a> { } impl<'a> WireFormat<'a> for DHCID<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 3; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -48,7 +50,7 @@ impl<'a> WireFormat<'a> for DHCID<'a> { } fn len(&self) -> usize { - 2 + 1 + self.digest.len() + self.digest.len() + Self::MINIMUM_LEN } } @@ -101,5 +103,4 @@ mod tests { Ok(()) } - } diff --git a/simple-dns/src/dns/rdata/dnskey.rs b/simple-dns/src/dns/rdata/dnskey.rs index 0bd7cdf..9dae9e1 100644 --- a/simple-dns/src/dns/rdata/dnskey.rs +++ b/simple-dns/src/dns/rdata/dnskey.rs @@ -16,13 +16,14 @@ pub struct DNSKEY<'a> { pub public_key: Cow<'a, [u8]>, } - impl<'a> RR for DNSKEY<'a> { const TYPE_CODE: u16 = 48; } impl<'a> WireFormat<'a> for DNSKEY<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 4; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -56,7 +57,7 @@ impl<'a> WireFormat<'a> for DNSKEY<'a> { } fn len(&self) -> usize { - 2 + 1 + 1 + self.public_key.len() + self.public_key.len() + Self::MINIMUM_LEN } } @@ -94,7 +95,7 @@ mod tests { rdata.write_to(&mut writer).unwrap(); let rdata = DNSKEY::parse(&writer, &mut 0).unwrap(); assert_eq!(rdata.flags, flags); - assert_eq!(rdata.protocol, protocol); + assert_eq!(rdata.protocol, protocol); assert_eq!(rdata.algorithm, algorithm); assert_eq!(&*rdata.public_key, &[1, 2, 3, 4, 5]); } @@ -115,9 +116,7 @@ mod tests { *sample_rdata.public_key, *b"\x01\x03\xd2\x2a\x6c\xa7\x7f\x35\xb8\x93\x20\x6f\xd3\x5e\x4c\x50\x6d\x83\x78\x84\x37\x09\xb9\x7e\x04\x16\x47\xe1\xbf\xf4\x3d\x8d\x64\xc6\x49\xaf\x1e\x37\x19\x73\xc9\xe8\x91\xfc\xe3\xdf\x51\x9a\x8c\x84\x0a\x63\xee\x42\xa6\xd2\xeb\xdd\xbb\x97\x03\x5d\x21\x5a\xa4\xe4\x17\xb1\xfa\x45\xfa\x11\xa9\x74\x1e\xa2\x09\x8c\x1d\xfa\x5f\xb5\xfe\xb3\x32\xfd\x4b\xc8\x15\x20\x89\xae\xf3\x6b\xa6\x44\xcc\xe2\x41\x3b\x3b\x72\xbe\x18\xcb\xef\x8d\xa2\x53\xf4\xe9\x3d\x21\x03\x86\x6d\x92\x34\xa2\xe2\x8d\xf5\x29\xa6\x7d\x54\x68\xdb\xef\xe3" ); - + Ok(()) } - } - diff --git a/simple-dns/src/dns/rdata/ds.rs b/simple-dns/src/dns/rdata/ds.rs index 00b02c4..1fce395 100644 --- a/simple-dns/src/dns/rdata/ds.rs +++ b/simple-dns/src/dns/rdata/ds.rs @@ -13,16 +13,17 @@ pub struct DS<'a> { /// The digest type number identifying the cryptographic hash algorithm used to create the digest pub digest_type: u8, /// The digest value calculated over the referenced DNSKEY record - pub digest: Cow<'a, [u8]> + pub digest: Cow<'a, [u8]>, } - impl<'a> RR for DS<'a> { const TYPE_CODE: u16 = 43; } impl<'a> WireFormat<'a> for DS<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 4; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -55,7 +56,7 @@ impl<'a> WireFormat<'a> for DS<'a> { } fn len(&self) -> usize { - 4 + self.digest.len() + self.digest.len() + Self::MINIMUM_LEN } } @@ -66,7 +67,7 @@ impl<'a> DS<'a> { key_tag: self.key_tag, algorithm: self.algorithm, digest_type: self.digest_type, - digest: Cow::Owned(self.digest.into_owned()) + digest: Cow::Owned(self.digest.into_owned()), } } } @@ -85,7 +86,7 @@ mod tests { let digest = vec![1, 2, 3, 4, 5]; let rdata = DS { key_tag, - algorithm, + algorithm, digest_type, digest: Cow::Owned(digest), }; @@ -110,9 +111,11 @@ mod tests { assert_eq!(sample_rdata.algorithm, 5); assert_eq!(sample_rdata.digest_type, 1); assert_eq!(sample_rdata.key_tag, 60485); - assert_eq!(*sample_rdata.digest, *b"\x2B\xB1\x83\xAF\x5F\x22\x58\x81\x79\xA5\x3B\x0A\x98\x63\x1F\xAD\x1A\x29\x21\x18"); + assert_eq!( + *sample_rdata.digest, + *b"\x2B\xB1\x83\xAF\x5F\x22\x58\x81\x79\xA5\x3B\x0A\x98\x63\x1F\xAD\x1A\x29\x21\x18" + ); Ok(()) } - } diff --git a/simple-dns/src/dns/rdata/eui.rs b/simple-dns/src/dns/rdata/eui.rs index 892a770..65dd021 100644 --- a/simple-dns/src/dns/rdata/eui.rs +++ b/simple-dns/src/dns/rdata/eui.rs @@ -26,11 +26,13 @@ impl RR for EUI64 { } impl<'a> WireFormat<'a> for EUI48 { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 6; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { - let address =data[*position..*position + 6].try_into()?; + let address = data[*position..*position + 6].try_into()?; *position += 6; Ok(Self { address }) } @@ -39,18 +41,16 @@ impl<'a> WireFormat<'a> for EUI48 { out.write_all(&self.address) .map_err(crate::SimpleDnsError::from) } - - fn len(&self) -> usize { - 6 - } } impl<'a> WireFormat<'a> for EUI64 { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 8; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { - let address =data[*position..*position + 8].try_into()?; + let address = data[*position..*position + 8].try_into()?; *position += 8; Ok(Self { address }) } @@ -59,10 +59,6 @@ impl<'a> WireFormat<'a> for EUI64 { out.write_all(&self.address) .map_err(crate::SimpleDnsError::from) } - - fn len(&self) -> usize { - 8 - } } impl EUI48 { @@ -148,4 +144,3 @@ mod tests { Ok(()) } } - diff --git a/simple-dns/src/dns/rdata/hinfo.rs b/simple-dns/src/dns/rdata/hinfo.rs index 43492e8..a70ff5a 100644 --- a/simple-dns/src/dns/rdata/hinfo.rs +++ b/simple-dns/src/dns/rdata/hinfo.rs @@ -30,7 +30,7 @@ impl<'a> HINFO<'a> { } impl<'a> WireFormat<'a> for HINFO<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { diff --git a/simple-dns/src/dns/rdata/ipseckey.rs b/simple-dns/src/dns/rdata/ipseckey.rs index 2d73f94..01579ff 100644 --- a/simple-dns/src/dns/rdata/ipseckey.rs +++ b/simple-dns/src/dns/rdata/ipseckey.rs @@ -1,5 +1,8 @@ use crate::{dns::WireFormat, Name}; -use std::{borrow::Cow, net::{Ipv4Addr, Ipv6Addr}}; +use std::{ + borrow::Cow, + net::{Ipv4Addr, Ipv6Addr}, +}; use super::RR; @@ -46,7 +49,9 @@ impl<'a> RR for IPSECKEY<'a> { } impl<'a> WireFormat<'a> for IPSECKEY<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 5; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -70,7 +75,7 @@ impl<'a> WireFormat<'a> for IPSECKEY<'a> { )); *position += 4; x - }, + } 2 => { let mut octets = [0u8; 16]; if data.len() < *position + 16 { @@ -100,31 +105,32 @@ impl<'a> WireFormat<'a> for IPSECKEY<'a> { match &self.gateway { Gateway::None => { out.write_all(&[self.precedence, 0, self.algorithm])?; - }, + } Gateway::IPv4(ipv4_addr) => { out.write_all(&[self.precedence, 1, self.algorithm])?; out.write_all(&ipv4_addr.octets())? - }, + } Gateway::IPv6(ipv6_addr) => { out.write_all(&[self.precedence, 2, self.algorithm])?; out.write_all(&ipv6_addr.octets())? - }, + } Gateway::Domain(name) => { out.write_all(&[self.precedence, 3, self.algorithm])?; name.write_to(out)? - }, + } }; out.write_all(&self.public_key)?; Ok(()) } fn len(&self) -> usize { - 5 + match &self.gateway { + (match &self.gateway { Gateway::None => 0, Gateway::IPv4(_) => 4, Gateway::IPv6(_) => 16, Gateway::Domain(name) => name.len(), - } + self.public_key.len() + }) + self.public_key.len() + + Self::MINIMUM_LEN } } @@ -161,7 +167,10 @@ mod tests { let ipseckey = IPSECKEY::parse(&data, &mut 0).unwrap(); assert_eq!(ipseckey.precedence, 10); assert_eq!(ipseckey.algorithm, 2); - assert_eq!(ipseckey.gateway, Gateway::IPv4(Ipv4Addr::new(192,0,2,38))); + assert_eq!( + ipseckey.gateway, + Gateway::IPv4(Ipv4Addr::new(192, 0, 2, 38)) + ); assert_eq!(*ipseckey.public_key, *b"\x01\x03\x51\x53\x79\x86\xed\x35\x53\x3b\x60\x64\x47\x8e\xee\xb2\x7b\x5b\xd7\x4d\xae\x14\x9b\x6e\x81\xba\x3a\x05\x21\xaf\x82\xab\x78\x01"); } @@ -176,11 +185,12 @@ mod tests { assert_eq!(sample_rdata.precedence, 10); assert_eq!(sample_rdata.algorithm, 2); - assert_eq!(sample_rdata.gateway, Gateway::IPv4(Ipv4Addr::new(192,0,2,38))); + assert_eq!( + sample_rdata.gateway, + Gateway::IPv4(Ipv4Addr::new(192, 0, 2, 38)) + ); assert_eq!(*sample_rdata.public_key, *b"\x01\x03\x51\x53\x79\x86\xed\x35\x53\x3b\x60\x64\x47\x8e\xee\xb2\x7b\x5b\xd7\x4d\xae\x14\x9b\x6e\x81\xba\x3a\x05\x21\xaf\x82\xab\x78\x01"); - Ok(()) } } - diff --git a/simple-dns/src/dns/rdata/isdn.rs b/simple-dns/src/dns/rdata/isdn.rs index 04fd563..e3f1b0c 100644 --- a/simple-dns/src/dns/rdata/isdn.rs +++ b/simple-dns/src/dns/rdata/isdn.rs @@ -28,7 +28,7 @@ impl<'a> ISDN<'a> { } impl<'a> WireFormat<'a> for ISDN<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { diff --git a/simple-dns/src/dns/rdata/kx.rs b/simple-dns/src/dns/rdata/kx.rs index c8b6991..8815792 100644 --- a/simple-dns/src/dns/rdata/kx.rs +++ b/simple-dns/src/dns/rdata/kx.rs @@ -9,16 +9,17 @@ pub struct KX<'a> { /// The preference (or priority) lowest values are prioritized. pub preference: u16, /// The DNS domain name of the key exchanger. This host must have an associated KEY RR. - pub exchanger: Name<'a> + pub exchanger: Name<'a>, } - impl<'a> RR for KX<'a> { const TYPE_CODE: u16 = 36; } impl<'a> WireFormat<'a> for KX<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 2; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -27,7 +28,7 @@ impl<'a> WireFormat<'a> for KX<'a> { let exchanger = Name::parse(data, position)?; Ok(Self { preference, - exchanger + exchanger, }) } @@ -38,7 +39,7 @@ impl<'a> WireFormat<'a> for KX<'a> { } fn len(&self) -> usize { - 2 + self.exchanger.len() + self.exchanger.len() + Self::MINIMUM_LEN } } @@ -47,7 +48,7 @@ impl<'a> KX<'a> { pub fn into_owned<'b>(self) -> KX<'b> { KX { preference: self.preference, - exchanger: self.exchanger.into_owned() + exchanger: self.exchanger.into_owned(), } } } @@ -62,15 +63,15 @@ mod tests { fn parse_and_write_kx() { let kx = KX { preference: 5, - exchanger: Name::new("example.com.").unwrap() + exchanger: Name::new("example.com.").unwrap(), }; - + let mut data = Vec::new(); kx.write_to(&mut data).unwrap(); let kx = KX::parse(&data, &mut 0).unwrap(); assert_eq!(kx.preference, 5); - assert_eq!(kx.exchanger,Name::new("example.com.").unwrap()); + assert_eq!(kx.exchanger, Name::new("example.com.").unwrap()); } #[test] @@ -88,4 +89,3 @@ mod tests { Ok(()) } } - diff --git a/simple-dns/src/dns/rdata/loc.rs b/simple-dns/src/dns/rdata/loc.rs index 0fab528..64f676a 100644 --- a/simple-dns/src/dns/rdata/loc.rs +++ b/simple-dns/src/dns/rdata/loc.rs @@ -33,14 +33,12 @@ impl LOC { } impl<'a> WireFormat<'a> for LOC { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 16; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { - if data.len() < *position + 16 { - return Err(SimpleDnsError::InsufficientData); - } - let data = &data[*position..*position + 16]; *position += 16; @@ -84,10 +82,6 @@ impl<'a> WireFormat<'a> for LOC { Ok(()) } - - fn len(&self) -> usize { - 16 - } } #[cfg(test)] diff --git a/simple-dns/src/dns/rdata/macros.rs b/simple-dns/src/dns/rdata/macros.rs index 8b259e9..bc5d7b6 100644 --- a/simple-dns/src/dns/rdata/macros.rs +++ b/simple-dns/src/dns/rdata/macros.rs @@ -22,7 +22,7 @@ macro_rules! rr_wrapper { } impl<'a> WireFormat<'a> for $t<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -77,20 +77,22 @@ macro_rules! rdata_enum { } impl<'a> WireFormat<'a> for RData<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 10; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { - if *position + 10 > data.len() { - return Err(crate::SimpleDnsError::InsufficientData); - } - let rdatatype = u16::from_be_bytes(data[*position..*position + 2].try_into()?).into(); let rdatalen = u16::from_be_bytes(data[*position + 8..*position + 10].try_into()?) as usize; // OPT needs to look the ttl and class values, hence position will be advanced by OPT // parsing code if rdatatype == TYPE::OPT { + if *position + rdatalen + 10 > data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + return Ok(RData::OPT(OPT::parse(&data[..*position + rdatalen + 10], position)?)) } *position += 10; diff --git a/simple-dns/src/dns/rdata/minfo.rs b/simple-dns/src/dns/rdata/minfo.rs index 86aacc8..a1ebd8a 100644 --- a/simple-dns/src/dns/rdata/minfo.rs +++ b/simple-dns/src/dns/rdata/minfo.rs @@ -29,7 +29,7 @@ impl<'a> MINFO<'a> { } impl<'a> WireFormat<'a> for MINFO<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { diff --git a/simple-dns/src/dns/rdata/mod.rs b/simple-dns/src/dns/rdata/mod.rs index 2a8c73a..40c64d1 100644 --- a/simple-dns/src/dns/rdata/mod.rs +++ b/simple-dns/src/dns/rdata/mod.rs @@ -160,7 +160,6 @@ macros::rr_wrapper! { HTTPS: SVCB = 65 } - macros::rdata_enum! { A, AAAA, @@ -239,4 +238,4 @@ SMIMEA - RFC 8162 HIP - RFC 8005 TSIG - RFC 8945 -*/ \ No newline at end of file +*/ diff --git a/simple-dns/src/dns/rdata/mx.rs b/simple-dns/src/dns/rdata/mx.rs index 3e44839..8fae4ba 100644 --- a/simple-dns/src/dns/rdata/mx.rs +++ b/simple-dns/src/dns/rdata/mx.rs @@ -30,7 +30,9 @@ impl<'a> MX<'a> { } impl<'a> WireFormat<'a> for MX<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 2; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -59,7 +61,7 @@ impl<'a> WireFormat<'a> for MX<'a> { } fn len(&self) -> usize { - self.exchange.len() + 2 + self.exchange.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/naptr.rs b/simple-dns/src/dns/rdata/naptr.rs index 1739cad..0d41efa 100644 --- a/simple-dns/src/dns/rdata/naptr.rs +++ b/simple-dns/src/dns/rdata/naptr.rs @@ -41,7 +41,9 @@ impl<'a> NAPTR<'a> { } impl<'a> WireFormat<'a> for NAPTR<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 4; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -74,7 +76,11 @@ impl<'a> WireFormat<'a> for NAPTR<'a> { } fn len(&self) -> usize { - self.flags.len() + self.services.len() + self.regexp.len() + self.replacement.len() + 4 + self.flags.len() + + self.services.len() + + self.regexp.len() + + self.replacement.len() + + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/nsap.rs b/simple-dns/src/dns/rdata/nsap.rs index 84c0322..6779582 100644 --- a/simple-dns/src/dns/rdata/nsap.rs +++ b/simple-dns/src/dns/rdata/nsap.rs @@ -1,4 +1,4 @@ -use crate::{dns::WireFormat, SimpleDnsError}; +use crate::dns::WireFormat; use super::RR; @@ -38,14 +38,12 @@ impl NSAP { } impl<'a> WireFormat<'a> for NSAP { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 20; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { - if data.len() < *position + 20 { - return Err(SimpleDnsError::InsufficientData); - } - let data = &data[*position..*position + 20]; *position += 20; @@ -88,10 +86,6 @@ impl<'a> WireFormat<'a> for NSAP { Ok(()) } - - fn len(&self) -> usize { - 20 - } } #[cfg(test)] diff --git a/simple-dns/src/dns/rdata/nsec.rs b/simple-dns/src/dns/rdata/nsec.rs index b5edbfc..8b2da12 100644 --- a/simple-dns/src/dns/rdata/nsec.rs +++ b/simple-dns/src/dns/rdata/nsec.rs @@ -22,13 +22,12 @@ pub struct TypeBitMap<'a> { pub bitmap: Cow<'a, [u8]>, } - impl<'a> RR for NSEC<'a> { const TYPE_CODE: u16 = 47; } impl<'a> WireFormat<'a> for NSEC<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -38,22 +37,35 @@ impl<'a> WireFormat<'a> for NSEC<'a> { while data.len() > *position { let window_block = data[*position]; *position += 1; - if type_bit_maps.last().is_some_and(|f: &TypeBitMap<'_>| f.window_block - 1 != window_block) { + + if type_bit_maps.last().is_some_and(|f: &TypeBitMap<'_>| { + f.window_block > 0 && f.window_block - 1 != window_block + }) { return Err(crate::SimpleDnsError::AttemptedInvalidOperation); } + if *position >= data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + let bitmap_length = data[*position]; *position += 1; - let bitmap = &data[*position..*position + bitmap_length as usize]; - *position += bitmap_length as usize; - + let bitmap_end = *position + bitmap_length as usize; + + if bitmap_end > data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + + let bitmap = &data[*position..bitmap_end]; + *position = bitmap_end; + type_bit_maps.push(TypeBitMap { window_block, bitmap: Cow::Borrowed(bitmap), }); } - + Ok(Self { next_name, type_bit_maps, @@ -65,12 +77,12 @@ impl<'a> WireFormat<'a> for NSEC<'a> { let mut sorted = self.type_bit_maps.clone(); sorted.sort_by(|a, b| a.window_block.cmp(&b.window_block)); - + for record in sorted.iter() { out.write_all(&[record.window_block])?; out.write_all(&[record.bitmap.len() as u8])?; out.write_all(&record.bitmap)?; - }; + } Ok(()) } @@ -83,10 +95,14 @@ impl<'a> WireFormat<'a> for NSEC<'a> { impl<'a> NSEC<'a> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> NSEC<'b> { - let type_bit_maps = self.type_bit_maps.into_iter().map(|x| TypeBitMap { - window_block: x.window_block, - bitmap: x.bitmap.into_owned().into(), - }).collect(); + let type_bit_maps = self + .type_bit_maps + .into_iter() + .map(|x| TypeBitMap { + window_block: x.window_block, + bitmap: x.bitmap.into_owned().into(), + }) + .collect(); NSEC { next_name: self.next_name.into_owned(), type_bit_maps, @@ -128,12 +144,17 @@ mod tests { _ => unreachable!(), }; - assert_eq!(sample_rdata.next_name, Name::new("host.example.com.").unwrap()); + assert_eq!( + sample_rdata.next_name, + Name::new("host.example.com.").unwrap() + ); assert_eq!(sample_rdata.type_bit_maps.len(), 1); assert_eq!(sample_rdata.type_bit_maps[0].window_block, 0); - assert_eq!(sample_rdata.type_bit_maps[0].bitmap, vec![64, 1, 0, 0, 0, 1]); + assert_eq!( + sample_rdata.type_bit_maps[0].bitmap, + vec![64, 1, 0, 0, 0, 1] + ); Ok(()) } - } diff --git a/simple-dns/src/dns/rdata/null.rs b/simple-dns/src/dns/rdata/null.rs index d9d1aa6..88ce530 100644 --- a/simple-dns/src/dns/rdata/null.rs +++ b/simple-dns/src/dns/rdata/null.rs @@ -43,7 +43,7 @@ impl<'a> NULL<'a> { } impl<'a> WireFormat<'a> for NULL<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { diff --git a/simple-dns/src/dns/rdata/opt.rs b/simple-dns/src/dns/rdata/opt.rs index 162ce6f..52a18c0 100644 --- a/simple-dns/src/dns/rdata/opt.rs +++ b/simple-dns/src/dns/rdata/opt.rs @@ -33,14 +33,12 @@ impl<'a> RR for OPT<'a> { } impl<'a> WireFormat<'a> for OPT<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 10; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { - if *position + 10 > data.len() { - return Err(crate::SimpleDnsError::InsufficientData); - } - // udp packet size comes from CLASS let udp_packet_size = u16::from_be_bytes(data[*position + 2..*position + 4].try_into()?); // version comes from ttl diff --git a/simple-dns/src/dns/rdata/route_through.rs b/simple-dns/src/dns/rdata/route_through.rs index aef06cf..3c21667 100644 --- a/simple-dns/src/dns/rdata/route_through.rs +++ b/simple-dns/src/dns/rdata/route_through.rs @@ -30,7 +30,8 @@ impl<'a> RouteThrough<'a> { } impl<'a> WireFormat<'a> for RouteThrough<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 2; + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -59,7 +60,7 @@ impl<'a> WireFormat<'a> for RouteThrough<'a> { } fn len(&self) -> usize { - self.intermediate_host.len() + 2 + self.intermediate_host.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/rp.rs b/simple-dns/src/dns/rdata/rp.rs index 57d551a..49a2d4c 100644 --- a/simple-dns/src/dns/rdata/rp.rs +++ b/simple-dns/src/dns/rdata/rp.rs @@ -28,7 +28,7 @@ impl<'a> RP<'a> { } impl<'a> WireFormat<'a> for RP<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { diff --git a/simple-dns/src/dns/rdata/rrsig.rs b/simple-dns/src/dns/rdata/rrsig.rs index ef0b5d4..e8416c0 100644 --- a/simple-dns/src/dns/rdata/rrsig.rs +++ b/simple-dns/src/dns/rdata/rrsig.rs @@ -1,4 +1,4 @@ -use crate::dns::{WireFormat, Name}; +use crate::dns::{Name, WireFormat}; use std::{borrow::Cow, convert::TryInto}; use super::RR; @@ -23,16 +23,17 @@ pub struct RRSIG<'a> { /// The domain name of the zone that contains the signed RRset pub signer_name: Name<'a>, /// The cryptographic signature that covers the RRSIG RDATA - pub signature: Cow<'a, [u8]> + pub signature: Cow<'a, [u8]>, } - impl<'a> RR for RRSIG<'a> { const TYPE_CODE: u16 = 46; } impl<'a> WireFormat<'a> for RRSIG<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 18; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -89,7 +90,7 @@ impl<'a> WireFormat<'a> for RRSIG<'a> { } fn len(&self) -> usize { - 18 + self.signer_name.len() + self.signature.len() + self.signer_name.len() + self.signature.len() + Self::MINIMUM_LEN } } @@ -110,11 +111,13 @@ impl<'a> RRSIG<'a> { } } - #[cfg(test)] mod tests { - use crate::{rdata::{RData, A}, ResourceRecord}; use super::*; + use crate::{ + rdata::{RData, A}, + ResourceRecord, + }; #[test] fn parse_and_write_rrsig() { @@ -154,8 +157,7 @@ mod tests { assert_eq!(sample_rdata.key_tag, 2642); assert_eq!(sample_rdata.signer_name, Name::new("example.com.")?); assert_eq!(*sample_rdata.signature, *b"\xa0\x90\x75\x5b\xa5\x8d\x1a\xff\xa5\x76\xf4\x37\x58\x31\xb4\x31\x09\x20\xe4\x81\x21\x8d\x18\xa9\xf1\x64\xeb\x3d\x81\xaf\xd3\xb8\x75\xd3\xc7\x54\x28\x63\x1e\x0c\xf2\xa2\x8d\x50\x87\x5f\x70\xc3\x29\xd7\xdb\xfa\xfe\xa8\x07\xdc\x1f\xba\x1d\xc3\x4c\x95\xd4\x01\xf2\x3f\x33\x4c\xe6\x3b\xfc\xf3\xf1\xb5\xb4\x47\x39\xe5\xf0\xed\xed\x18\xd6\xb3\x3f\x04\x0a\x91\x13\x76\xd1\x73\xd7\x57\xa9\xf0\xc1\xfa\x17\x98\x94\x1b\xb0\xb3\x6b\x2d\xf9\x06\x27\x90\xfa\x7f\x01\x66\xf2\x73\x7e\xea\x90\x73\x78\x34\x1f\xb1\x2d\xc0\xa7\x7a"); - + Ok(()) } } - diff --git a/simple-dns/src/dns/rdata/soa.rs b/simple-dns/src/dns/rdata/soa.rs index dcc159d..1d71abf 100644 --- a/simple-dns/src/dns/rdata/soa.rs +++ b/simple-dns/src/dns/rdata/soa.rs @@ -54,13 +54,17 @@ impl<'a> SOA<'a> { } impl<'a> WireFormat<'a> for SOA<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 20; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { let mname = Name::parse(data, position)?; let rname = Name::parse(data, position)?; + Self::check_len(data, position)?; + let serial = u32::from_be_bytes(data[*position..*position + 4].try_into()?); let refresh = i32::from_be_bytes(data[*position + 4..*position + 8].try_into()?); let retry = i32::from_be_bytes(data[*position + 8..*position + 12].try_into()?); @@ -97,7 +101,7 @@ impl<'a> WireFormat<'a> for SOA<'a> { } fn len(&self) -> usize { - self.mname.len() + self.rname.len() + 20 + self.mname.len() + self.rname.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/srv.rs b/simple-dns/src/dns/rdata/srv.rs index 91657f5..0ba9595 100644 --- a/simple-dns/src/dns/rdata/srv.rs +++ b/simple-dns/src/dns/rdata/srv.rs @@ -39,7 +39,9 @@ impl<'a> SRV<'a> { } impl<'a> WireFormat<'a> for SRV<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 6; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -66,7 +68,7 @@ impl<'a> WireFormat<'a> for SRV<'a> { } fn len(&self) -> usize { - self.target.len() + 6 + self.target.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/svcb.rs b/simple-dns/src/dns/rdata/svcb.rs index a23fb5b..56587c1 100644 --- a/simple-dns/src/dns/rdata/svcb.rs +++ b/simple-dns/src/dns/rdata/svcb.rs @@ -148,7 +148,9 @@ impl<'a> SVCB<'a> { } impl<'a> WireFormat<'a> for SVCB<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 2; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -158,7 +160,12 @@ impl<'a> WireFormat<'a> for SVCB<'a> { let target = Name::parse(data, position)?; let mut params = BTreeMap::new(); let mut previous_key = -1; + while *position < data.len() { + if *position + 4 >= data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + let key = u16::from_be_bytes(data[*position..*position + 2].try_into()?); let value_length = usize::from(u16::from_be_bytes( data[*position + 2..*position + 4].try_into()?, @@ -167,11 +174,15 @@ impl<'a> WireFormat<'a> for SVCB<'a> { return Err(crate::SimpleDnsError::InvalidDnsPacket); } previous_key = i32::from(key); - params.insert( - key, - Cow::Borrowed(&data[*position + 4..*position + 4 + value_length]), - ); - *position += 4 + value_length; + + let param_end = *position + 4 + value_length; + + if param_end > data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + + params.insert(key, Cow::Borrowed(&data[*position + 4..param_end])); + *position = param_end; } Ok(Self { priority, @@ -196,12 +207,13 @@ impl<'a> WireFormat<'a> for SVCB<'a> { // RFC9460 ยง2.2 specifically mentioned the TargetName is *uncompressed*. fn len(&self) -> usize { - 2 + self.target.len() + self.target.len() + self .params .values() .map(|value| value.len() + 4) .sum::() + + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/txt.rs b/simple-dns/src/dns/rdata/txt.rs index e4d4c30..3e84c16 100644 --- a/simple-dns/src/dns/rdata/txt.rs +++ b/simple-dns/src/dns/rdata/txt.rs @@ -175,7 +175,9 @@ impl<'a> TryFrom> for String { } impl<'a> WireFormat<'a> for TXT<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 1; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -195,7 +197,7 @@ impl<'a> WireFormat<'a> for TXT<'a> { fn len(&self) -> usize { if self.strings.is_empty() { - 1 + Self::MINIMUM_LEN } else { self.size } diff --git a/simple-dns/src/dns/rdata/wks.rs b/simple-dns/src/dns/rdata/wks.rs index 50e82ed..5eda86d 100644 --- a/simple-dns/src/dns/rdata/wks.rs +++ b/simple-dns/src/dns/rdata/wks.rs @@ -31,7 +31,9 @@ impl<'a> WKS<'a> { } impl<'a> WireFormat<'a> for WKS<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 5; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -57,7 +59,7 @@ impl<'a> WireFormat<'a> for WKS<'a> { } fn len(&self) -> usize { - self.bit_map.len() + 5 + self.bit_map.len() + Self::MINIMUM_LEN } } diff --git a/simple-dns/src/dns/rdata/zonemd.rs b/simple-dns/src/dns/rdata/zonemd.rs index 8afb88c..2679e0f 100644 --- a/simple-dns/src/dns/rdata/zonemd.rs +++ b/simple-dns/src/dns/rdata/zonemd.rs @@ -16,13 +16,14 @@ pub struct ZONEMD<'a> { pub digest: Cow<'a, [u8]>, } - impl<'a> RR for ZONEMD<'a> { const TYPE_CODE: u16 = 63; } impl<'a> WireFormat<'a> for ZONEMD<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 6; + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -53,7 +54,7 @@ impl<'a> WireFormat<'a> for ZONEMD<'a> { } fn len(&self) -> usize { - 4 + 1 + 1 + self.digest.len() + self.digest.len() + Self::MINIMUM_LEN } } @@ -71,7 +72,10 @@ impl<'a> ZONEMD<'a> { #[cfg(test)] mod tests { - use crate::{rdata::{RData, ZONEMD}, ResourceRecord}; + use crate::{ + rdata::{RData, ZONEMD}, + ResourceRecord, + }; use super::*; @@ -114,4 +118,3 @@ mod tests { Ok(()) } } - diff --git a/simple-dns/src/dns/resource_record.rs b/simple-dns/src/dns/resource_record.rs index c4c4224..958076e 100644 --- a/simple-dns/src/dns/resource_record.rs +++ b/simple-dns/src/dns/resource_record.rs @@ -100,7 +100,14 @@ impl<'a> ResourceRecord<'a> { } impl<'a> WireFormat<'a> for ResourceRecord<'a> { - fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + const MINIMUM_LEN: usize = 10; + + // Disable redundant length check. + fn parse(data: &'a [u8], position: &mut usize) -> crate::Result { + Self::parse_after_check(data, position) + } + + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, { @@ -136,7 +143,7 @@ impl<'a> WireFormat<'a> for ResourceRecord<'a> { } fn len(&self) -> usize { - self.name.len() + self.rdata.len() + 10 + self.name.len() + self.rdata.len() + Self::MINIMUM_LEN } fn write_to(&self, out: &mut T) -> crate::Result<()> { diff --git a/simple-dns/src/dns/wire_format.rs b/simple-dns/src/dns/wire_format.rs index 5be2505..604ef22 100644 --- a/simple-dns/src/dns/wire_format.rs +++ b/simple-dns/src/dns/wire_format.rs @@ -7,10 +7,29 @@ use super::name::Label; /// Represents anything that can be part of a dns packet (Question, Resource Record, RData) pub(crate) trait WireFormat<'a> { + const MINIMUM_LEN: usize = 0; + /// Parse the contents of the data buffer starting at the given `position` /// It is necessary to pass the full buffer to this function, to be able to correctly implement name compression /// The implementor must `position` to ensure that is at the end of the data just parsed fn parse(data: &'a [u8], position: &mut usize) -> crate::Result + where + Self: Sized, + { + Self::check_len(data, position)?; + Self::parse_after_check(data, position) + } + + fn check_len(data: &'a [u8], position: &mut usize) -> crate::Result<()> { + if *position + Self::MINIMUM_LEN > data.len() { + return Err(crate::SimpleDnsError::InsufficientData); + } + + Ok(()) + } + + /// Parse the contenst after checking that `data[*position..]` is at least [Self::MINIMUM_LEN]. + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized; @@ -26,5 +45,7 @@ pub(crate) trait WireFormat<'a> { } /// Returns the length in bytes of this content - fn len(&self) -> usize; + fn len(&self) -> usize { + Self::MINIMUM_LEN + } } From 56a943c70d1d1aa3a7442786fad6408c5de48a36 Mon Sep 17 00:00:00 2001 From: Ilson Roberto Balliego Junior Date: Fri, 10 Jan 2025 21:47:38 +0100 Subject: [PATCH 3/8] remove constant default value --- simple-dns/src/dns/rdata/hinfo.rs | 2 ++ simple-dns/src/dns/rdata/isdn.rs | 1 + simple-dns/src/dns/rdata/macros.rs | 1 + simple-dns/src/dns/rdata/minfo.rs | 1 + simple-dns/src/dns/rdata/nsec.rs | 1 + simple-dns/src/dns/rdata/null.rs | 1 + simple-dns/src/dns/rdata/rp.rs | 1 + simple-dns/src/dns/wire_format.rs | 2 +- 8 files changed, 9 insertions(+), 1 deletion(-) diff --git a/simple-dns/src/dns/rdata/hinfo.rs b/simple-dns/src/dns/rdata/hinfo.rs index a70ff5a..d080cc3 100644 --- a/simple-dns/src/dns/rdata/hinfo.rs +++ b/simple-dns/src/dns/rdata/hinfo.rs @@ -30,6 +30,8 @@ impl<'a> HINFO<'a> { } impl<'a> WireFormat<'a> for HINFO<'a> { + const MINIMUM_LEN: usize = 0; + fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/rdata/isdn.rs b/simple-dns/src/dns/rdata/isdn.rs index e3f1b0c..fbef704 100644 --- a/simple-dns/src/dns/rdata/isdn.rs +++ b/simple-dns/src/dns/rdata/isdn.rs @@ -28,6 +28,7 @@ impl<'a> ISDN<'a> { } impl<'a> WireFormat<'a> for ISDN<'a> { + const MINIMUM_LEN: usize = 0; fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/rdata/macros.rs b/simple-dns/src/dns/rdata/macros.rs index bc5d7b6..f43070b 100644 --- a/simple-dns/src/dns/rdata/macros.rs +++ b/simple-dns/src/dns/rdata/macros.rs @@ -22,6 +22,7 @@ macro_rules! rr_wrapper { } impl<'a> WireFormat<'a> for $t<'a> { + const MINIMUM_LEN: usize = 0; fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/rdata/minfo.rs b/simple-dns/src/dns/rdata/minfo.rs index a1ebd8a..c16695f 100644 --- a/simple-dns/src/dns/rdata/minfo.rs +++ b/simple-dns/src/dns/rdata/minfo.rs @@ -29,6 +29,7 @@ impl<'a> MINFO<'a> { } impl<'a> WireFormat<'a> for MINFO<'a> { + const MINIMUM_LEN: usize = 0; fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/rdata/nsec.rs b/simple-dns/src/dns/rdata/nsec.rs index 8b2da12..62fc5f6 100644 --- a/simple-dns/src/dns/rdata/nsec.rs +++ b/simple-dns/src/dns/rdata/nsec.rs @@ -27,6 +27,7 @@ impl<'a> RR for NSEC<'a> { } impl<'a> WireFormat<'a> for NSEC<'a> { + const MINIMUM_LEN: usize = 0; fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/rdata/null.rs b/simple-dns/src/dns/rdata/null.rs index 88ce530..d4ae41d 100644 --- a/simple-dns/src/dns/rdata/null.rs +++ b/simple-dns/src/dns/rdata/null.rs @@ -43,6 +43,7 @@ impl<'a> NULL<'a> { } impl<'a> WireFormat<'a> for NULL<'a> { + const MINIMUM_LEN: usize = 0; fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/rdata/rp.rs b/simple-dns/src/dns/rdata/rp.rs index 49a2d4c..c99511d 100644 --- a/simple-dns/src/dns/rdata/rp.rs +++ b/simple-dns/src/dns/rdata/rp.rs @@ -28,6 +28,7 @@ impl<'a> RP<'a> { } impl<'a> WireFormat<'a> for RP<'a> { + const MINIMUM_LEN: usize = 0; fn parse_after_check(data: &'a [u8], position: &mut usize) -> crate::Result where Self: Sized, diff --git a/simple-dns/src/dns/wire_format.rs b/simple-dns/src/dns/wire_format.rs index 604ef22..cd3dc25 100644 --- a/simple-dns/src/dns/wire_format.rs +++ b/simple-dns/src/dns/wire_format.rs @@ -7,7 +7,7 @@ use super::name::Label; /// Represents anything that can be part of a dns packet (Question, Resource Record, RData) pub(crate) trait WireFormat<'a> { - const MINIMUM_LEN: usize = 0; + const MINIMUM_LEN: usize; /// Parse the contents of the data buffer starting at the given `position` /// It is necessary to pass the full buffer to this function, to be able to correctly implement name compression From f281ae3692a7a51f00479d198294097d66c13901 Mon Sep 17 00:00:00 2001 From: Ilson Roberto Balliego Junior Date: Fri, 10 Jan 2025 21:49:39 +0100 Subject: [PATCH 4/8] clippy warnings --- simple-dns/src/dns/character_string.rs | 6 +++--- simple-dns/src/dns/name.rs | 12 ++++++------ simple-dns/src/dns/rdata/afsdb.rs | 4 ++-- simple-dns/src/dns/rdata/caa.rs | 4 ++-- simple-dns/src/dns/rdata/cert.rs | 4 ++-- simple-dns/src/dns/rdata/dhcid.rs | 4 ++-- simple-dns/src/dns/rdata/dnskey.rs | 4 ++-- simple-dns/src/dns/rdata/ds.rs | 4 ++-- simple-dns/src/dns/rdata/hinfo.rs | 4 ++-- simple-dns/src/dns/rdata/ipseckey.rs | 6 +++--- simple-dns/src/dns/rdata/isdn.rs | 4 ++-- simple-dns/src/dns/rdata/kx.rs | 4 ++-- simple-dns/src/dns/rdata/minfo.rs | 4 ++-- simple-dns/src/dns/rdata/mx.rs | 4 ++-- simple-dns/src/dns/rdata/naptr.rs | 4 ++-- simple-dns/src/dns/rdata/nsec.rs | 4 ++-- simple-dns/src/dns/rdata/null.rs | 2 +- simple-dns/src/dns/rdata/opt.rs | 6 +++--- simple-dns/src/dns/rdata/route_through.rs | 4 ++-- simple-dns/src/dns/rdata/rp.rs | 4 ++-- simple-dns/src/dns/rdata/rrsig.rs | 4 ++-- simple-dns/src/dns/rdata/soa.rs | 4 ++-- simple-dns/src/dns/rdata/srv.rs | 4 ++-- simple-dns/src/dns/rdata/svcb.rs | 2 +- simple-dns/src/dns/rdata/txt.rs | 6 +++--- simple-dns/src/dns/rdata/wks.rs | 4 ++-- simple-dns/src/dns/rdata/zonemd.rs | 4 ++-- simple-dns/src/dns/resource_record.rs | 4 ++-- simple-mdns/src/resource_record_manager.rs | 2 +- 29 files changed, 63 insertions(+), 63 deletions(-) diff --git a/simple-dns/src/dns/character_string.rs b/simple-dns/src/dns/character_string.rs index 3be72b7..e058443 100644 --- a/simple-dns/src/dns/character_string.rs +++ b/simple-dns/src/dns/character_string.rs @@ -90,7 +90,7 @@ impl<'a> TryFrom<&'a str> for CharacterString<'a> { } } -impl<'a> TryFrom for CharacterString<'a> { +impl TryFrom for CharacterString<'_> { type Error = crate::SimpleDnsError; fn try_from(value: String) -> Result { @@ -98,14 +98,14 @@ impl<'a> TryFrom for CharacterString<'a> { } } -impl<'a> Display for CharacterString<'a> { +impl Display for CharacterString<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = std::str::from_utf8(&self.data).unwrap(); f.write_str(s) } } -impl<'a> std::fmt::Debug for CharacterString<'a> { +impl std::fmt::Debug for CharacterString<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CharacterString") .field("data", &self.to_string()) diff --git a/simple-dns/src/dns/name.rs b/simple-dns/src/dns/name.rs index 9e6e4aa..ea97a34 100644 --- a/simple-dns/src/dns/name.rs +++ b/simple-dns/src/dns/name.rs @@ -276,7 +276,7 @@ impl<'a, const N: usize> From<[Label<'a>; N]> for Name<'a> { } } -impl<'a> Display for Name<'a> { +impl Display for Name<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for (i, label) in self.iter().enumerate() { if i != 0 { @@ -290,7 +290,7 @@ impl<'a> Display for Name<'a> { } } -impl<'a> std::fmt::Debug for Name<'a> { +impl std::fmt::Debug for Name<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Name") .field(&format!("{}", self)) @@ -299,13 +299,13 @@ impl<'a> std::fmt::Debug for Name<'a> { } } -impl<'a> PartialEq for Name<'a> { +impl PartialEq for Name<'_> { fn eq(&self, other: &Self) -> bool { self.labels == other.labels } } -impl<'a> Hash for Name<'a> { +impl Hash for Name<'_> { fn hash(&self, state: &mut H) { self.labels.hash(state); } @@ -419,7 +419,7 @@ impl<'a> Label<'a> { } } -impl<'a> Display for Label<'a> { +impl Display for Label<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match std::str::from_utf8(&self.data) { Ok(s) => f.write_str(s), @@ -428,7 +428,7 @@ impl<'a> Display for Label<'a> { } } -impl<'a> std::fmt::Debug for Label<'a> { +impl std::fmt::Debug for Label<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Label") .field("data", &self.to_string()) diff --git a/simple-dns/src/dns/rdata/afsdb.rs b/simple-dns/src/dns/rdata/afsdb.rs index 8731201..df41be7 100644 --- a/simple-dns/src/dns/rdata/afsdb.rs +++ b/simple-dns/src/dns/rdata/afsdb.rs @@ -13,11 +13,11 @@ pub struct AFSDB<'a> { pub hostname: Name<'a>, } -impl<'a> RR for AFSDB<'a> { +impl RR for AFSDB<'_> { const TYPE_CODE: u16 = 18; } -impl<'a> AFSDB<'a> { +impl AFSDB<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> AFSDB<'b> { AFSDB { diff --git a/simple-dns/src/dns/rdata/caa.rs b/simple-dns/src/dns/rdata/caa.rs index 5a96e80..fa66367 100644 --- a/simple-dns/src/dns/rdata/caa.rs +++ b/simple-dns/src/dns/rdata/caa.rs @@ -17,11 +17,11 @@ pub struct CAA<'a> { pub value: Cow<'a, [u8]>, } -impl<'a> RR for CAA<'a> { +impl RR for CAA<'_> { const TYPE_CODE: u16 = 257; } -impl<'a> CAA<'a> { +impl CAA<'_> { /// Transforms the inner data into it owned type pub fn into_owned<'b>(self) -> CAA<'b> { CAA { diff --git a/simple-dns/src/dns/rdata/cert.rs b/simple-dns/src/dns/rdata/cert.rs index d520f92..0ef831a 100644 --- a/simple-dns/src/dns/rdata/cert.rs +++ b/simple-dns/src/dns/rdata/cert.rs @@ -16,7 +16,7 @@ pub struct CERT<'a> { pub certificate: Cow<'a, [u8]>, } -impl<'a> RR for CERT<'a> { +impl RR for CERT<'_> { const TYPE_CODE: u16 = 37; } @@ -58,7 +58,7 @@ impl<'a> WireFormat<'a> for CERT<'a> { } } -impl<'a> CERT<'a> { +impl CERT<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> CERT<'b> { CERT { diff --git a/simple-dns/src/dns/rdata/dhcid.rs b/simple-dns/src/dns/rdata/dhcid.rs index f4db8e0..e53eba9 100644 --- a/simple-dns/src/dns/rdata/dhcid.rs +++ b/simple-dns/src/dns/rdata/dhcid.rs @@ -14,7 +14,7 @@ pub struct DHCID<'a> { pub digest: Cow<'a, [u8]>, } -impl<'a> RR for DHCID<'a> { +impl RR for DHCID<'_> { const TYPE_CODE: u16 = 49; } @@ -54,7 +54,7 @@ impl<'a> WireFormat<'a> for DHCID<'a> { } } -impl<'a> DHCID<'a> { +impl DHCID<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> DHCID<'b> { DHCID { diff --git a/simple-dns/src/dns/rdata/dnskey.rs b/simple-dns/src/dns/rdata/dnskey.rs index 9dae9e1..ea2ea9b 100644 --- a/simple-dns/src/dns/rdata/dnskey.rs +++ b/simple-dns/src/dns/rdata/dnskey.rs @@ -16,7 +16,7 @@ pub struct DNSKEY<'a> { pub public_key: Cow<'a, [u8]>, } -impl<'a> RR for DNSKEY<'a> { +impl RR for DNSKEY<'_> { const TYPE_CODE: u16 = 48; } @@ -61,7 +61,7 @@ impl<'a> WireFormat<'a> for DNSKEY<'a> { } } -impl<'a> DNSKEY<'a> { +impl DNSKEY<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> DNSKEY<'b> { DNSKEY { diff --git a/simple-dns/src/dns/rdata/ds.rs b/simple-dns/src/dns/rdata/ds.rs index 1fce395..d3c1c29 100644 --- a/simple-dns/src/dns/rdata/ds.rs +++ b/simple-dns/src/dns/rdata/ds.rs @@ -16,7 +16,7 @@ pub struct DS<'a> { pub digest: Cow<'a, [u8]>, } -impl<'a> RR for DS<'a> { +impl RR for DS<'_> { const TYPE_CODE: u16 = 43; } @@ -60,7 +60,7 @@ impl<'a> WireFormat<'a> for DS<'a> { } } -impl<'a> DS<'a> { +impl DS<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> DS<'b> { DS { diff --git a/simple-dns/src/dns/rdata/hinfo.rs b/simple-dns/src/dns/rdata/hinfo.rs index d080cc3..ffdf098 100644 --- a/simple-dns/src/dns/rdata/hinfo.rs +++ b/simple-dns/src/dns/rdata/hinfo.rs @@ -15,11 +15,11 @@ pub struct HINFO<'a> { pub os: CharacterString<'a>, } -impl<'a> RR for HINFO<'a> { +impl RR for HINFO<'_> { const TYPE_CODE: u16 = 13; } -impl<'a> HINFO<'a> { +impl HINFO<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> HINFO<'b> { HINFO { diff --git a/simple-dns/src/dns/rdata/ipseckey.rs b/simple-dns/src/dns/rdata/ipseckey.rs index 01579ff..880ebc7 100644 --- a/simple-dns/src/dns/rdata/ipseckey.rs +++ b/simple-dns/src/dns/rdata/ipseckey.rs @@ -32,7 +32,7 @@ pub enum Gateway<'a> { Domain(Name<'a>), } -impl<'a> Gateway<'a> { +impl Gateway<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> Gateway<'b> { match self { @@ -44,7 +44,7 @@ impl<'a> Gateway<'a> { } } -impl<'a> RR for IPSECKEY<'a> { +impl RR for IPSECKEY<'_> { const TYPE_CODE: u16 = 45; } @@ -134,7 +134,7 @@ impl<'a> WireFormat<'a> for IPSECKEY<'a> { } } -impl<'a> IPSECKEY<'a> { +impl IPSECKEY<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> IPSECKEY<'b> { IPSECKEY { diff --git a/simple-dns/src/dns/rdata/isdn.rs b/simple-dns/src/dns/rdata/isdn.rs index fbef704..01da888 100644 --- a/simple-dns/src/dns/rdata/isdn.rs +++ b/simple-dns/src/dns/rdata/isdn.rs @@ -13,11 +13,11 @@ pub struct ISDN<'a> { pub sa: CharacterString<'a>, } -impl<'a> RR for ISDN<'a> { +impl RR for ISDN<'_> { const TYPE_CODE: u16 = 20; } -impl<'a> ISDN<'a> { +impl ISDN<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> ISDN<'b> { ISDN { diff --git a/simple-dns/src/dns/rdata/kx.rs b/simple-dns/src/dns/rdata/kx.rs index 8815792..c34de2a 100644 --- a/simple-dns/src/dns/rdata/kx.rs +++ b/simple-dns/src/dns/rdata/kx.rs @@ -12,7 +12,7 @@ pub struct KX<'a> { pub exchanger: Name<'a>, } -impl<'a> RR for KX<'a> { +impl RR for KX<'_> { const TYPE_CODE: u16 = 36; } @@ -43,7 +43,7 @@ impl<'a> WireFormat<'a> for KX<'a> { } } -impl<'a> KX<'a> { +impl KX<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> KX<'b> { KX { diff --git a/simple-dns/src/dns/rdata/minfo.rs b/simple-dns/src/dns/rdata/minfo.rs index c16695f..6ed0b7f 100644 --- a/simple-dns/src/dns/rdata/minfo.rs +++ b/simple-dns/src/dns/rdata/minfo.rs @@ -14,11 +14,11 @@ pub struct MINFO<'a> { pub emailbox: Name<'a>, } -impl<'a> RR for MINFO<'a> { +impl RR for MINFO<'_> { const TYPE_CODE: u16 = 14; } -impl<'a> MINFO<'a> { +impl MINFO<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> MINFO<'b> { MINFO { diff --git a/simple-dns/src/dns/rdata/mx.rs b/simple-dns/src/dns/rdata/mx.rs index 8fae4ba..98bc422 100644 --- a/simple-dns/src/dns/rdata/mx.rs +++ b/simple-dns/src/dns/rdata/mx.rs @@ -15,11 +15,11 @@ pub struct MX<'a> { pub exchange: Name<'a>, } -impl<'a> RR for MX<'a> { +impl RR for MX<'_> { const TYPE_CODE: u16 = 15; } -impl<'a> MX<'a> { +impl MX<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> MX<'b> { MX { diff --git a/simple-dns/src/dns/rdata/naptr.rs b/simple-dns/src/dns/rdata/naptr.rs index 0d41efa..2d3482c 100644 --- a/simple-dns/src/dns/rdata/naptr.rs +++ b/simple-dns/src/dns/rdata/naptr.rs @@ -22,11 +22,11 @@ pub struct NAPTR<'a> { pub replacement: Name<'a>, } -impl<'a> RR for NAPTR<'a> { +impl RR for NAPTR<'_> { const TYPE_CODE: u16 = 35; } -impl<'a> NAPTR<'a> { +impl NAPTR<'_> { /// Transforms the inner data into it owned type pub fn into_owned<'b>(self) -> NAPTR<'b> { NAPTR { diff --git a/simple-dns/src/dns/rdata/nsec.rs b/simple-dns/src/dns/rdata/nsec.rs index 62fc5f6..913c683 100644 --- a/simple-dns/src/dns/rdata/nsec.rs +++ b/simple-dns/src/dns/rdata/nsec.rs @@ -22,7 +22,7 @@ pub struct TypeBitMap<'a> { pub bitmap: Cow<'a, [u8]>, } -impl<'a> RR for NSEC<'a> { +impl RR for NSEC<'_> { const TYPE_CODE: u16 = 47; } @@ -93,7 +93,7 @@ impl<'a> WireFormat<'a> for NSEC<'a> { } } -impl<'a> NSEC<'a> { +impl NSEC<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> NSEC<'b> { let type_bit_maps = self diff --git a/simple-dns/src/dns/rdata/null.rs b/simple-dns/src/dns/rdata/null.rs index d4ae41d..b767d82 100644 --- a/simple-dns/src/dns/rdata/null.rs +++ b/simple-dns/src/dns/rdata/null.rs @@ -11,7 +11,7 @@ pub struct NULL<'a> { data: Cow<'a, [u8]>, } -impl<'a> RR for NULL<'a> { +impl RR for NULL<'_> { const TYPE_CODE: u16 = 10; } diff --git a/simple-dns/src/dns/rdata/opt.rs b/simple-dns/src/dns/rdata/opt.rs index 52a18c0..fdb790a 100644 --- a/simple-dns/src/dns/rdata/opt.rs +++ b/simple-dns/src/dns/rdata/opt.rs @@ -28,7 +28,7 @@ pub struct OPT<'a> { pub version: u8, } -impl<'a> RR for OPT<'a> { +impl RR for OPT<'_> { const TYPE_CODE: u16 = 41; } @@ -92,7 +92,7 @@ impl<'a> WireFormat<'a> for OPT<'a> { } } -impl<'a> OPT<'a> { +impl OPT<'_> { pub(crate) fn extract_rcode_from_ttl(ttl: u32, header: &Header) -> RCODE { let mut rcode = (ttl & masks::RCODE_MASK) << 4; rcode |= header.response_code as u32; @@ -125,7 +125,7 @@ pub struct OPTCode<'a> { pub data: Cow<'a, [u8]>, } -impl<'a> OPTCode<'a> { +impl OPTCode<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> OPTCode<'b> { OPTCode { diff --git a/simple-dns/src/dns/rdata/route_through.rs b/simple-dns/src/dns/rdata/route_through.rs index 3c21667..1b54f9d 100644 --- a/simple-dns/src/dns/rdata/route_through.rs +++ b/simple-dns/src/dns/rdata/route_through.rs @@ -15,11 +15,11 @@ pub struct RouteThrough<'a> { pub intermediate_host: Name<'a>, } -impl<'a> RR for RouteThrough<'a> { +impl RR for RouteThrough<'_> { const TYPE_CODE: u16 = 21; } -impl<'a> RouteThrough<'a> { +impl RouteThrough<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> RouteThrough<'b> { RouteThrough { diff --git a/simple-dns/src/dns/rdata/rp.rs b/simple-dns/src/dns/rdata/rp.rs index c99511d..26e1e65 100644 --- a/simple-dns/src/dns/rdata/rp.rs +++ b/simple-dns/src/dns/rdata/rp.rs @@ -13,11 +13,11 @@ pub struct RP<'a> { pub txt: Name<'a>, } -impl<'a> RR for RP<'a> { +impl RR for RP<'_> { const TYPE_CODE: u16 = 17; } -impl<'a> RP<'a> { +impl RP<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> RP<'b> { RP { diff --git a/simple-dns/src/dns/rdata/rrsig.rs b/simple-dns/src/dns/rdata/rrsig.rs index e8416c0..3aabcbc 100644 --- a/simple-dns/src/dns/rdata/rrsig.rs +++ b/simple-dns/src/dns/rdata/rrsig.rs @@ -26,7 +26,7 @@ pub struct RRSIG<'a> { pub signature: Cow<'a, [u8]>, } -impl<'a> RR for RRSIG<'a> { +impl RR for RRSIG<'_> { const TYPE_CODE: u16 = 46; } @@ -94,7 +94,7 @@ impl<'a> WireFormat<'a> for RRSIG<'a> { } } -impl<'a> RRSIG<'a> { +impl RRSIG<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> RRSIG<'b> { RRSIG { diff --git a/simple-dns/src/dns/rdata/soa.rs b/simple-dns/src/dns/rdata/soa.rs index 1d71abf..78b118a 100644 --- a/simple-dns/src/dns/rdata/soa.rs +++ b/simple-dns/src/dns/rdata/soa.rs @@ -24,11 +24,11 @@ pub struct SOA<'a> { pub minimum: u32, } -impl<'a> RR for SOA<'a> { +impl RR for SOA<'_> { const TYPE_CODE: u16 = 6; } -impl<'a> SOA<'a> { +impl SOA<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> SOA<'b> { SOA { diff --git a/simple-dns/src/dns/rdata/srv.rs b/simple-dns/src/dns/rdata/srv.rs index 0ba9595..4ce2f5e 100644 --- a/simple-dns/src/dns/rdata/srv.rs +++ b/simple-dns/src/dns/rdata/srv.rs @@ -22,11 +22,11 @@ pub struct SRV<'a> { pub target: Name<'a>, } -impl<'a> RR for SRV<'a> { +impl RR for SRV<'_> { const TYPE_CODE: u16 = 33; } -impl<'a> SRV<'a> { +impl SRV<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> SRV<'b> { SRV { diff --git a/simple-dns/src/dns/rdata/svcb.rs b/simple-dns/src/dns/rdata/svcb.rs index 56587c1..db815d6 100644 --- a/simple-dns/src/dns/rdata/svcb.rs +++ b/simple-dns/src/dns/rdata/svcb.rs @@ -22,7 +22,7 @@ pub struct SVCB<'a> { params: BTreeMap>, } -impl<'a> RR for SVCB<'a> { +impl RR for SVCB<'_> { const TYPE_CODE: u16 = 64; } diff --git a/simple-dns/src/dns/rdata/txt.rs b/simple-dns/src/dns/rdata/txt.rs index 3e84c16..8ca93e5 100644 --- a/simple-dns/src/dns/rdata/txt.rs +++ b/simple-dns/src/dns/rdata/txt.rs @@ -15,11 +15,11 @@ pub struct TXT<'a> { size: usize, } -impl<'a> RR for TXT<'a> { +impl RR for TXT<'_> { const TYPE_CODE: u16 = 16; } -impl<'a> Default for TXT<'a> { +impl Default for TXT<'_> { fn default() -> Self { Self::new() } @@ -131,7 +131,7 @@ impl<'a> TXT<'a> { } } -impl<'a> TryFrom>> for TXT<'a> { +impl TryFrom>> for TXT<'_> { type Error = crate::SimpleDnsError; fn try_from(value: HashMap>) -> Result { diff --git a/simple-dns/src/dns/rdata/wks.rs b/simple-dns/src/dns/rdata/wks.rs index 5eda86d..da80415 100644 --- a/simple-dns/src/dns/rdata/wks.rs +++ b/simple-dns/src/dns/rdata/wks.rs @@ -15,11 +15,11 @@ pub struct WKS<'a> { pub bit_map: Cow<'a, [u8]>, } -impl<'a> RR for WKS<'a> { +impl RR for WKS<'_> { const TYPE_CODE: u16 = 11; } -impl<'a> WKS<'a> { +impl WKS<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> WKS<'b> { WKS { diff --git a/simple-dns/src/dns/rdata/zonemd.rs b/simple-dns/src/dns/rdata/zonemd.rs index 2679e0f..d2133e5 100644 --- a/simple-dns/src/dns/rdata/zonemd.rs +++ b/simple-dns/src/dns/rdata/zonemd.rs @@ -16,7 +16,7 @@ pub struct ZONEMD<'a> { pub digest: Cow<'a, [u8]>, } -impl<'a> RR for ZONEMD<'a> { +impl RR for ZONEMD<'_> { const TYPE_CODE: u16 = 63; } @@ -58,7 +58,7 @@ impl<'a> WireFormat<'a> for ZONEMD<'a> { } } -impl<'a> ZONEMD<'a> { +impl ZONEMD<'_> { /// Transforms the inner data into its owned type pub fn into_owned<'b>(self) -> ZONEMD<'b> { ZONEMD { diff --git a/simple-dns/src/dns/resource_record.rs b/simple-dns/src/dns/resource_record.rs index 958076e..10c72b8 100644 --- a/simple-dns/src/dns/resource_record.rs +++ b/simple-dns/src/dns/resource_record.rs @@ -174,7 +174,7 @@ impl<'a> WireFormat<'a> for ResourceRecord<'a> { } } -impl<'a> Hash for ResourceRecord<'a> { +impl Hash for ResourceRecord<'_> { fn hash(&self, state: &mut H) { self.name.hash(state); self.class.hash(state); @@ -182,7 +182,7 @@ impl<'a> Hash for ResourceRecord<'a> { } } -impl<'a> PartialEq for ResourceRecord<'a> { +impl PartialEq for ResourceRecord<'_> { fn eq(&self, other: &Self) -> bool { self.name == other.name && self.class == other.class && self.rdata == other.rdata } diff --git a/simple-mdns/src/resource_record_manager.rs b/simple-mdns/src/resource_record_manager.rs index 37a59a2..7b5b54b 100644 --- a/simple-mdns/src/resource_record_manager.rs +++ b/simple-mdns/src/resource_record_manager.rs @@ -131,7 +131,7 @@ impl<'a> ResourceRecordManager<'a> { } } -impl<'a> Default for ResourceRecordManager<'a> { +impl Default for ResourceRecordManager<'_> { fn default() -> Self { Self::new() } From 6a4dce6c21c2e47bbee67e4355933d8d11f452b3 Mon Sep 17 00:00:00 2001 From: Ilson Roberto Balliego Junior Date: Fri, 10 Jan 2025 21:53:09 +0100 Subject: [PATCH 5/8] clippy --- simple-mdns/src/async_discovery/oneshot_resolver.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/simple-mdns/src/async_discovery/oneshot_resolver.rs b/simple-mdns/src/async_discovery/oneshot_resolver.rs index e3f854a..a55910e 100644 --- a/simple-mdns/src/async_discovery/oneshot_resolver.rs +++ b/simple-mdns/src/async_discovery/oneshot_resolver.rs @@ -35,7 +35,6 @@ use tokio::{ /// /// # }; /// ``` - pub struct OneShotMdnsResolver { query_timeout: Duration, unicast_response: bool, @@ -62,9 +61,9 @@ impl OneShotMdnsResolver { } /// Send a query packet and returns the first response - pub async fn query_packet<'a>( + pub async fn query_packet( &self, - packet: Packet<'a>, + packet: Packet<'_>, ) -> Result>, SimpleMdnsError> { self.sender_socket .send_to( From 710533f3ec16086cc0a167588a46ca241294feea Mon Sep 17 00:00:00 2001 From: Ilson Roberto Balliego Junior Date: Fri, 10 Jan 2025 22:07:26 +0100 Subject: [PATCH 6/8] split clippy into a different job --- .github/workflows/rust.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 92d7097..43ad941 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,6 +10,14 @@ env: CARGO_TERM_COLOR: always jobs: + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Clippy + run: cargo clippy --all-features -- -D warnings + test-dev: name: Test Dev on ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -19,8 +27,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Clippy - run: cargo clippy --all-features -- -D warnings - name: Build run: cargo build --verbose --all-features - name: Run tests @@ -35,8 +41,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Clippy - run: cargo clippy --release --all-features -- -D warnings - name: Build run: cargo build --verbose --release --all-features - name: Run tests From c82b9b9036789ce45aa0fd8ccc922bc0fc185e52 Mon Sep 17 00:00:00 2001 From: Ilson Roberto Balliego Junior Date: Fri, 10 Jan 2025 22:31:14 +0100 Subject: [PATCH 7/8] update workflow --- .github/workflows/rust.yml | 26 ++++++++++++++++++++++---- Cargo.lock | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 43ad941..6bd5dd8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -28,9 +28,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build - run: cargo build --verbose --all-features + run: cargo build --workspace --exclude simple-dns-fuzz --verbose --all-features - name: Run tests - run: cargo test --verbose --all-features + run: cargo test --workspace --exclude simple-dns-fuzz --verbose --all-features test-release: name: Test Release on ${{ matrix.os }} @@ -42,6 +42,24 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build - run: cargo build --verbose --release --all-features + run: cargo build --workspace --exclude simple-dns-fuzz --verbose --release --all-features - name: Run tests - run: cargo test --verbose --release --all-features + run: cargo test --workspace --exclude simple-dns-fuzz --verbose --release --all-features + + fuzzing: + name: Fuzz + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + - name: Install cargo-fuzz + run: | + cargo install cargo-fuzz + - name: Run Fuzzing + run: | + cd simple-dns + cargo fuzz run packet_parse -- -max_total_time=180 diff --git a/Cargo.lock b/Cargo.lock index 99e4ca4..bfaabfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" From d594c9366b406dd26436a1b19d65c23ab9511b56 Mon Sep 17 00:00:00 2001 From: Ilson Roberto Balliego Junior Date: Fri, 10 Jan 2025 22:35:48 +0100 Subject: [PATCH 8/8] increase fuzzing time --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6bd5dd8..254ed6b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -62,4 +62,4 @@ jobs: - name: Run Fuzzing run: | cd simple-dns - cargo fuzz run packet_parse -- -max_total_time=180 + cargo fuzz run packet_parse -- -max_total_time=300