Skip to content

Fix overflow for /0 #323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 11, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 59 additions & 10 deletions src/repository/resources/ipres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,15 +1042,17 @@ impl AddressRange {
pub fn to_v6_prefixes(self) -> impl Iterator<Item = Prefix> {
let mut start = self.min.to_bits();
let end = self.max.to_bits();

let mut cidrs: Vec<Prefix> = vec![];

std::iter::from_fn(move || {
loop {
// The idea is to take the largest prefix possible from the start
// then move the start to the address after the last address in
// that prefix, and do it again until there are no addresses left.

// Based loosely on <https://github.com/arineng/cidr-calc>
if start > end {
return None;
break;
}

// Determine how many of the last bits of the address are prefixable
Expand All @@ -1077,22 +1079,29 @@ impl AddressRange {

debug_assert!(prefix_len <= 128);
let prefix = Prefix::new(Addr::from_bits(start), prefix_len as u8);
cidrs.push(prefix);

start += 2_u128.pow(same_bits);
if prefix.max().to_bits() == end {
break;
}

Some(prefix)
})
start += 1 << same_bits;
}

cidrs.into_iter()
}

/// Convert a range into a set of V4 prefixes
pub fn to_v4_prefixes(self) -> impl Iterator<Item = Prefix> {
let mut start = (self.min.to_bits() >> 96) as u32;
let end = (self.max.to_bits() >> 96) as u32;

std::iter::from_fn(move || {
let mut cidrs: Vec<Prefix> = vec![];

loop {
// This works the same as `to_v6_prefixes` above
if start > end {
return None;
break;
}

let addr_host_bits = start.trailing_zeros();
Expand All @@ -1110,10 +1119,16 @@ impl AddressRange {
prefix_len as u8
);

start += 2u32.pow(same_bits);
cidrs.push(prefix);

Some(prefix)
})
if (prefix.max().to_bits() >> 96) as u32 == end {
break;
}

start += 1 << same_bits;
}

cidrs.into_iter()
}

/// Formats the range as an IPv4 range.
Expand Down Expand Up @@ -2760,6 +2775,40 @@ mod tests {

assert_eq!(2, prefixes.count());
}
{
let range = AddressRange::new(
Addr::from(Ipv4Addr::from_str("192.168.2.255").unwrap()),
Addr::from(Ipv4Addr::from_str("192.168.0.0").unwrap())
);

let prefixes = range.to_v4_prefixes();

assert_eq!(0, prefixes.count());
}
}

#[test]
fn to_full_prefixes() {
{
let range = AddressRange::new(
Addr::from(Ipv6Addr::from_str("::").unwrap()),
Addr::from(Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap())
);

let prefixes = range.to_v6_prefixes();

assert_eq!(1, prefixes.count());
}
{
let range = AddressRange::new(
Addr::from(Ipv4Addr::from_str("0.0.0.0").unwrap()),
Addr::from(Ipv4Addr::from_str("255.255.255.255").unwrap())
);

let prefixes = range.to_v4_prefixes();

assert_eq!(1, prefixes.count());
}
}
}

Expand Down