diff --git a/src/uu/date/src/date.rs b/src/uu/date/src/date.rs index d2100fc80..45bceaec3 100644 --- a/src/uu/date/src/date.rs +++ b/src/uu/date/src/date.rs @@ -487,6 +487,7 @@ pub fn uu_app() -> Command { .short('s') .long(OPT_SET) .value_name("STRING") + .allow_hyphen_values(true) .help({ #[cfg(not(any(target_os = "macos", target_os = "redox")))] { diff --git a/src/uu/kill/src/kill.rs b/src/uu/kill/src/kill.rs index 809d59b7d..94aa81964 100644 --- a/src/uu/kill/src/kill.rs +++ b/src/uu/kill/src/kill.rs @@ -137,8 +137,8 @@ pub fn uu_app() -> Command { } fn handle_obsolete(args: &mut Vec) -> Option { - // Sanity check - if args.len() > 2 { + // Sanity check - need at least the program name and one argument + if args.len() >= 2 { // Old signal can only be in the first argument position let slice = args[1].as_str(); if let Some(signal) = slice.strip_prefix('-') { diff --git a/src/uucore/src/lib/features/format/spec.rs b/src/uucore/src/lib/features/format/spec.rs index 467f09850..3bef0fbb1 100644 --- a/src/uucore/src/lib/features/format/spec.rs +++ b/src/uucore/src/lib/features/format/spec.rs @@ -595,14 +595,10 @@ fn eat_number(rest: &mut &[u8], index: &mut usize) -> Option { match rest[*index..].iter().position(|b| !b.is_ascii_digit()) { None | Some(0) => None, Some(i) => { - // TODO: This might need to handle errors better - // For example in case of overflow. - let parsed = std::str::from_utf8(&rest[*index..(*index + i)]) - .unwrap() - .parse() - .unwrap(); + // Handle large numbers that would cause overflow + let num_str = std::str::from_utf8(&rest[*index..(*index + i)]).unwrap(); *index += i; - Some(parsed) + Some(num_str.parse().unwrap_or(usize::MAX)) } } } diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index 9d59efd58..512c5c799 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -293,6 +293,27 @@ fn test_date_set_permissions_error() { } } +#[test] +#[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] +fn test_date_set_hyphen_prefixed_values() { + // test -s flag accepts hyphen-prefixed values like "-3 days" + if !(geteuid() == 0 || uucore::os::is_wsl_1()) { + let test_cases = vec!["-1 hour", "-2 days", "-3 weeks", "-1 month"]; + + for date_str in test_cases { + let result = new_ucmd!().arg("--set").arg(date_str).fails(); + result.no_stdout(); + // permission error, not argument parsing error + assert!( + result.stderr_str().starts_with("date: cannot set date: "), + "Expected permission error for '{}', but got: {}", + date_str, + result.stderr_str() + ); + } + } +} + #[test] #[cfg(target_os = "macos")] fn test_date_set_mac_unavailable() { diff --git a/tests/by-util/test_kill.rs b/tests/by-util/test_kill.rs index 5fb8fb312..aad1982d6 100644 --- a/tests/by-util/test_kill.rs +++ b/tests/by-util/test_kill.rs @@ -395,3 +395,27 @@ fn test_kill_with_signal_and_table() { .arg("-t") .fails(); } + +/// Test that `kill -1` (signal without PID) reports "no process ID" error +/// instead of being misinterpreted as pid=-1 which would kill all processes. +/// This matches GNU kill behavior. +#[test] +fn test_kill_signal_only_no_pid() { + // Test with -1 (SIGHUP) + new_ucmd!() + .arg("-1") + .fails() + .stderr_contains("no process ID specified"); + + // Test with -9 (SIGKILL) + new_ucmd!() + .arg("-9") + .fails() + .stderr_contains("no process ID specified"); + + // Test with -TERM + new_ucmd!() + .arg("-TERM") + .fails() + .stderr_contains("no process ID specified"); +} diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 6bfcecbb4..21e638f7c 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -1482,3 +1482,13 @@ fn test_large_width_format() { .stdout_is(""); } } + +#[test] +fn test_extreme_field_width_overflow() { + // Test the specific case that was causing panic due to integer overflow + // in the field width parsing. + new_ucmd!() + .args(&["%999999999999999999999999d", "1"]) + .fails_with_code(1) + .stderr_only("printf: write error\n"); +}