From 51a52b16cfa224dc3c480d5b2bb4a7a524ab6828 Mon Sep 17 00:00:00 2001 From: Steven Malis Date: Thu, 5 Mar 2026 11:17:34 -0500 Subject: [PATCH 1/2] address_filter: Fix parsing of 'all' --- support/address_filter/src/lib.rs | 139 +++++++++++++++++++++++++----- 1 file changed, 116 insertions(+), 23 deletions(-) diff --git a/support/address_filter/src/lib.rs b/support/address_filter/src/lib.rs index 3760e73fcb..5fbd50b618 100644 --- a/support/address_filter/src/lib.rs +++ b/support/address_filter/src/lib.rs @@ -166,31 +166,34 @@ impl FromStr for AddressFilter { fn from_str(s: &str) -> Result { let mut v = Vec::new(); let mut unknown = false; - for range in s.split(',') { - if range == "?" { - unknown = true; - } else if s == "all" { - unknown = true; - v.push((T::ZERO, T::MAX)); - } else { - let (start, end) = if let Some((start, end)) = range.split_once('-') { - let start = parse_value(start)?; - let end = parse_value(end)?; - if end < start { - return Err(InvalidRangeSet::EndBeforeStart); - } - (start, end) + + if s == "all" { + unknown = true; + v.push((T::ZERO, T::MAX)); + } else { + for range in s.split(',') { + if range == "?" { + unknown = true; } else { - let start = parse_value(range)?; - (start, start) - }; - v.push((start, end)); + let (start, end) = if let Some((start, end)) = range.split_once('-') { + let start = parse_value(start)?; + let end = parse_value(end)?; + if end < start { + return Err(InvalidRangeSet::EndBeforeStart); + } + (start, end) + } else { + let start = parse_value(range)?; + (start, start) + }; + v.push((start, end)); + } } - } - v.sort(); - for ((_, end1), (start2, _)) in v.iter().zip(v.iter().skip(1)) { - if end1 >= start2 { - return Err(InvalidRangeSet::Overlapping); + v.sort(); + for ((_, end1), (start2, _)) in v.iter().zip(v.iter().skip(1)) { + if end1 >= start2 { + return Err(InvalidRangeSet::Overlapping); + } } } Ok(Self { ranges: v, unknown }) @@ -213,3 +216,93 @@ impl InspectMut for AddressFilter { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_all() { + let filter: AddressFilter = "all".parse().unwrap(); + assert!(filter.unknown); + assert_eq!(filter.ranges, vec![(0, u32::MAX)]); + assert_eq!(filter.to_string(), "all"); + assert!(filter.filtered(&0, true)); + assert!(filter.filtered(&0x1000, true)); + assert!(filter.filtered(&u32::MAX, true)); + assert!(filter.filtered(&0, false)); + } + + #[test] + fn parse_unknown_only() { + let filter: AddressFilter = "?".parse().unwrap(); + assert!(filter.unknown); + assert!(filter.ranges.is_empty()); + assert!(!filter.filtered(&0x40, true)); + assert!(filter.filtered(&0x40, false)); + } + + #[test] + fn parse_single_address() { + let filter: AddressFilter = "0x63".parse().unwrap(); + assert!(!filter.unknown); + assert_eq!(filter.ranges, vec![(0x63, 0x63)]); + assert!(filter.filtered(&0x63, true)); + assert!(!filter.filtered(&0x64, true)); + } + + #[test] + fn parse_range() { + let filter: AddressFilter = "0x40-0x4f".parse().unwrap(); + assert!(filter.filtered(&0x40, true)); + assert!(filter.filtered(&0x45, true)); + assert!(filter.filtered(&0x4f, true)); + assert!(!filter.filtered(&0x3f, true)); + assert!(!filter.filtered(&0x50, true)); + } + + #[test] + fn parse_compound() { + let filter: AddressFilter = "0x40-0x4f,0x63,?".parse().unwrap(); + assert!(filter.unknown); + assert_eq!(filter.ranges, vec![(0x40, 0x4f), (0x63, 0x63)]); + assert!(filter.filtered(&0x45, true)); + assert!(filter.filtered(&0x63, true)); + assert!(!filter.filtered(&0x50, true)); + assert!(filter.filtered(&0x99, false)); + let reparsed: AddressFilter = filter.to_string().parse().unwrap(); + assert_eq!(filter.ranges, reparsed.ranges); + assert_eq!(filter.unknown, reparsed.unknown); + } + + #[test] + fn parse_rejects_end_before_start() { + let result: Result, _> = "0x4f-0x40".parse(); + assert!(matches!(result, Err(InvalidRangeSet::EndBeforeStart))); + } + + #[test] + fn parse_rejects_overlapping() { + let result: Result, _> = "0x40-0x4f,0x45-0x50".parse(); + assert!(matches!(result, Err(InvalidRangeSet::Overlapping))); + } + + #[test] + fn parse_rejects_missing_prefix() { + let result: Result, _> = "40".parse(); + assert!(result.is_err()); + } + + #[test] + fn parse_rejects_nested_all() { + let result: Result, _> = "0x40-0x4f,all".parse(); + assert!(result.is_err()); + } + + #[test] + fn empty_filter_matches_nothing() { + let filter = AddressFilter::::new(false); + assert!(!filter.filtered(&0, true)); + assert!(!filter.filtered(&0, false)); + } +} From fd344c7ddefdfa19cbc78f6930f4596b3c9afba1 Mon Sep 17 00:00:00 2001 From: Steven Malis <137308034+smalis-msft@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:23:03 -0500 Subject: [PATCH 2/2] Apply suggestion from @smalis-msft --- support/address_filter/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support/address_filter/src/lib.rs b/support/address_filter/src/lib.rs index 5fbd50b618..d68cb9a43d 100644 --- a/support/address_filter/src/lib.rs +++ b/support/address_filter/src/lib.rs @@ -69,6 +69,8 @@ impl RangeKey for u64 { /// /// For example: `0x40-0x4f,0x63,?` would filter addresses 0x40 through 0x4f, address /// 0x63, and any unknown addresses. +/// +/// The string "all" is a special case that will match everything. #[derive(Debug)] pub struct AddressFilter { unknown: bool,