mirror of
https://github.com/NLnetLabs/domain.git
synced 2026-09-29 21:24:57 +02:00
rdata/rfc4034: fix RtypeBitmap window iteration and add tests
The previous performed a bound check on the full data slice like this: ``` let octet = octet + 2; ... return !((data[1] as usize) < octet || data[octet] & mask == 0); ``` The octet was incremented by 2 to skip window number and window length, but then compared against the window length (`data[1]`), which only contains the number of bytes in the window itself, so types with lower codes would not be detected.
This commit is contained in:
committed by
Marek Vavruša
parent
63b5b8699d
commit
417098a993
@@ -767,6 +767,11 @@ impl RtypeBitmap {
|
||||
let mut data = bytes.as_ref();
|
||||
while !data.is_empty() {
|
||||
let len = (data[1] as usize) + 2;
|
||||
// https://tools.ietf.org/html/rfc4034#section-4.1.2:
|
||||
// Blocks with no types present MUST NOT be included.
|
||||
if len == 2 {
|
||||
return Err(RtypeBitmapError::BadRtypeBitmap);
|
||||
}
|
||||
if len > 34 {
|
||||
return Err(RtypeBitmapError::BadRtypeBitmap)
|
||||
}
|
||||
@@ -797,13 +802,13 @@ impl RtypeBitmap {
|
||||
|
||||
pub fn contains(&self, rtype: Rtype) -> bool {
|
||||
let (block, octet, mask) = split_rtype(rtype);
|
||||
let octet = octet + 2;
|
||||
let mut data = self.0.as_ref();
|
||||
while !data.is_empty() {
|
||||
if data[0] == block {
|
||||
return !((data[1] as usize) < octet || data[octet] & mask == 0)
|
||||
let ((window_num, window), next_data) = read_window(data).unwrap();
|
||||
if window_num == block {
|
||||
return !(window.len() < octet || window[octet] & mask == 0);
|
||||
}
|
||||
data = &data[data[1] as usize..]
|
||||
data = next_data;
|
||||
}
|
||||
false
|
||||
}
|
||||
@@ -1139,10 +1144,24 @@ fn split_rtype(rtype: Rtype) -> (u8, usize, u8) {
|
||||
(
|
||||
(rtype >> 8) as u8,
|
||||
((rtype & 0xFF) >> 3) as usize,
|
||||
0x80u8 >> (rtype & 0x07)
|
||||
0b10000000 >> (rtype & 0x07)
|
||||
)
|
||||
}
|
||||
|
||||
/// Splits the next bitmap window from the bitmap and returns None when there's no next window.
|
||||
fn read_window<'a>(data: &'a [u8]) -> Option<((u8, &'a [u8]), &'a [u8])> {
|
||||
data.split_first()
|
||||
.and_then(|(n, data)| {
|
||||
data.split_first()
|
||||
.and_then(|(l, data)| if data.len() >= usize::from(*l) {
|
||||
let (window, data) = data.split_at(usize::from(*l));
|
||||
Some(((*n, window), data))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//============ Test ==========================================================
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -1150,6 +1169,28 @@ mod test {
|
||||
use crate::iana::Rtype;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn rtype_split() {
|
||||
assert_eq!(split_rtype(Rtype::A), (0, 0, 0b01000000));
|
||||
assert_eq!(split_rtype(Rtype::Ns), (0, 0, 0b00100000));
|
||||
assert_eq!(split_rtype(Rtype::Caa), (1, 0, 0b01000000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rtype_bitmap_read_window() {
|
||||
let mut builder = RtypeBitmapBuilder::new();
|
||||
builder.add(Rtype::A);
|
||||
builder.add(Rtype::Caa);
|
||||
let bitmap = builder.finalize();
|
||||
|
||||
let ((n, window), data) = read_window(bitmap.as_slice()).unwrap();
|
||||
assert_eq!((n, window), (0u8, b"\x40".as_ref()));
|
||||
let ((n, window), data) = read_window(data).unwrap();
|
||||
assert_eq!((n, window), (1u8, b"\x40".as_ref()));
|
||||
assert!(data.is_empty());
|
||||
assert!(read_window(data).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rtype_bitmap_builder() {
|
||||
let mut builder = RtypeBitmapBuilder::new();
|
||||
@@ -1158,14 +1199,23 @@ mod test {
|
||||
builder.add(Rtype::Mx); // 0x000F
|
||||
builder.add(Rtype::Rrsig); // 0x002E
|
||||
builder.add(Rtype::Nsec); // 0x002F
|
||||
let bitmap = builder.finalize();
|
||||
assert_eq!(
|
||||
builder.finalize().as_slice(),
|
||||
bitmap.as_slice(),
|
||||
&b"\x00\x06\x40\x01\x00\x00\x00\x03\
|
||||
\x04\x1b\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x20"[..]
|
||||
);
|
||||
|
||||
assert!(bitmap.contains(Rtype::A));
|
||||
assert!(bitmap.contains(Rtype::Mx));
|
||||
assert!(bitmap.contains(Rtype::Rrsig));
|
||||
assert!(bitmap.contains(Rtype::Nsec));
|
||||
assert!(bitmap.contains(Rtype::Int(1234)));
|
||||
assert!(!bitmap.contains(Rtype::Int(1235)));
|
||||
assert!(!bitmap.contains(Rtype::Ns));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user