diff --git a/src/find/matchers/mod.rs b/src/find/matchers/mod.rs index e35ebbbb..c4cef7d2 100644 --- a/src/find/matchers/mod.rs +++ b/src/find/matchers/mod.rs @@ -341,7 +341,11 @@ fn convert_arg_to_comparable_value_and_suffix( option_name: &str, value_as_string: &str, ) -> Result<(ComparableValue, String), Box> { - let re = Regex::new(r"([-+]?)[-+]?(\d+)(.*)$")?; + // Anchor at the start so a non-numeric prefix like "x5c" is rejected instead + // of silently parsing the "5c" in the middle. After the comparison sign GNU + // accepts one more optional '+' (so "++5c" and "-+5c" are valid, but "+-5c" + // and "--5c" are not), which `\+?` reproduces. + let re = Regex::new(r"^([-+]?)\+?(\d+)(.*)$")?; if let Some(groups) = re.captures(value_as_string) { if let Ok(val) = groups[2].parse::() { return Ok(( @@ -1815,6 +1819,41 @@ mod tests { ); } + #[test] + fn convert_arg_to_comparable_value_and_suffix_test() { + // Valid sign forms, matching GNU find's -size grammar. + assert_eq!( + convert_arg_to_comparable_value_and_suffix("-size", "5c").unwrap(), + (ComparableValue::EqualTo(5), "c".to_string()), + ); + assert_eq!( + convert_arg_to_comparable_value_and_suffix("-size", "+5c").unwrap(), + (ComparableValue::MoreThan(5), "c".to_string()), + ); + assert_eq!( + convert_arg_to_comparable_value_and_suffix("-size", "-5c").unwrap(), + (ComparableValue::LessThan(5), "c".to_string()), + ); + // GNU accepts one extra '+' after the comparison sign. + assert_eq!( + convert_arg_to_comparable_value_and_suffix("-size", "++5c").unwrap(), + (ComparableValue::MoreThan(5), "c".to_string()), + ); + assert_eq!( + convert_arg_to_comparable_value_and_suffix("-size", "-+5c").unwrap(), + (ComparableValue::LessThan(5), "c".to_string()), + ); + + // A non-numeric prefix ("x5c" used to be silently parsed as "5c") and the + // invalid double-sign forms are rejected, matching GNU. + for bad in ["x5c", "abc5c", "+-5c", "--5c", "+++5c"] { + assert!( + convert_arg_to_comparable_value_and_suffix("-size", bad).is_err(), + "expected `{bad}` to be rejected", + ); + } + } + #[test] fn convert_exception_arg_to_comparable_value_test() { let exception_args = ["1%2", "1%2%3", "1a2", "1%2a", "abc", "-", "+", "%"];