From 7e27e28ed2fe05e62d380a86eef7ee173f4646a5 Mon Sep 17 00:00:00 2001 From: Raphii Date: Sun, 24 Dec 2023 18:16:50 +0100 Subject: [PATCH] Fix panic due to range out of bounds in txt record parsing (#159) --- src/service_info.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/service_info.rs b/src/service_info.rs index 140de77..05ef0d6 100644 --- a/src/service_info.rs +++ b/src/service_info.rs @@ -642,7 +642,12 @@ fn decode_txt(txt: &[u8]) -> Vec { } offset += 1; // move over the length byte - let kv_bytes = &txt[offset..offset + length]; + let offset_end = offset + length; + if offset_end > txt.len() { + error!("DNS TXT record contains invalid data: Size given for property would be out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len()); + break; // Skipping the rest of the record content, as the size for this property would already be out of range. + } + let kv_bytes = &txt[offset..offset_end]; // split key and val using the first `=` let (k, v) = match kv_bytes.iter().position(|&x| x == b'=') { @@ -846,4 +851,24 @@ mod tests { "TxtProperty {key: \"key2\", val: Some(0x969798)}" ); } + + #[test] + fn test_txt_decode_property_size_out_of_bounds() { + // Construct a TXT record with an invalid property length that would be out of bounds. + let encoded: Vec = vec![ + 0x0b, // Length 11 + b'k', b'e', b'y', b'1', b'=', b'v', b'a', b'l', b'u', b'e', + b'1', // key1=value1 (Length 11) + 0x10, // Length 16 (Would be out of bounds) + b'k', b'e', b'y', b'2', b'=', b'v', b'a', b'l', b'u', b'e', + b'2', // key2=value2 (Length 11) + ]; + // Decode the record content + let decoded = decode_txt(&encoded); + // We expect the out of bounds length for the second property to have caused the rest of the record content to be skipped. + // Test that we only parsed the first property. + assert_eq!(decoded.len(), 1); + // Test that the key of the property we parsed is "key1" + assert_eq!(decoded[0].key, "key1"); + } }