diff --git a/src/uu/uniq/src/uniq.rs b/src/uu/uniq/src/uniq.rs index 4a7c86edf60..a54b4876c76 100644 --- a/src/uu/uniq/src/uniq.rs +++ b/src/uu/uniq/src/uniq.rs @@ -357,7 +357,9 @@ fn opt_parsed(opt_name: &str, matches: &ArgMatches) -> UResult> { Some(arg_str) => match arg_str.parse::() { Ok(v) => Ok(Some(v)), Err(e) => match e.kind() { - IntErrorKind::PosOverflow => Ok(Some(usize::MAX)), + IntErrorKind::PosOverflow if arg_str.chars().all(|c| c.is_ascii_digit()) => { + Ok(Some(usize::MAX)) + } _ => Err(USimpleError::new( 1, translate!("uniq-error-invalid-argument", "opt_name" => opt_name, "arg" => arg_str.maybe_quote()), diff --git a/tests/by-util/test_uniq.rs b/tests/by-util/test_uniq.rs index 98d72cda27d..a622b543803 100644 --- a/tests/by-util/test_uniq.rs +++ b/tests/by-util/test_uniq.rs @@ -1351,3 +1351,32 @@ fn test_obsolete_skip_fields_not_read_after_double_dash() { .fails() .stderr_contains("-1"); } + +#[test] +fn test_overflowing_numeric_options_with_trailing_garbage_rejected() { + // Large values that overflow usize but have trailing non-digits must be rejected (issue #16122) + new_ucmd!() + .args(&["-f", "18446744073709551616x"]) + .pipe_in("first\nsecond\nthird\n") + .fails_with_code(1) + .stderr_contains("Invalid argument"); + + new_ucmd!() + .args(&["-s", "18446744073709551616x"]) + .pipe_in("first\nsecond\nthird\n") + .fails_with_code(1) + .stderr_contains("Invalid argument"); + + new_ucmd!() + .args(&["-w", "18446744073709551616x"]) + .pipe_in("first\nsecond\nthird\n") + .fails_with_code(1) + .stderr_contains("Invalid argument"); + + // Purely numeric overflowing values remain accepted (clamped to usize::MAX) + new_ucmd!() + .args(&["-f", "18446744073709551616"]) + .pipe_in("first\nsecond\nthird\n") + .succeeds() + .stdout_is("first\n"); +}