diff --git a/src/locate/main.rs b/src/locate/main.rs index d550d431..f1013654 100644 --- a/src/locate/main.rs +++ b/src/locate/main.rs @@ -3,7 +3,21 @@ // https://opensource.org/licenses/MIT. fn main() { - let args = std::env::args().collect::>(); + // `std::env::args` panics on a non-UTF-8 argument, so read the arguments + // with `args_os` and report the first invalid one instead of aborting. + let args = match std::env::args_os() + .map(std::ffi::OsString::into_string) + .collect::, _>>() + { + Ok(args) => args, + Err(invalid) => { + eprintln!( + "locate: invalid (non-UTF-8) argument: {}", + invalid.to_string_lossy() + ); + std::process::exit(1); + } + }; let strs: Vec<&str> = args.iter().map(std::convert::AsRef::as_ref).collect(); std::process::exit(findutils::locate::locate_main(strs.as_slice())); } diff --git a/src/updatedb/main.rs b/src/updatedb/main.rs index e96570a0..247507cb 100644 --- a/src/updatedb/main.rs +++ b/src/updatedb/main.rs @@ -3,7 +3,21 @@ // https://opensource.org/licenses/MIT. fn main() { - let args = std::env::args().collect::>(); + // `std::env::args` panics on a non-UTF-8 argument, so read the arguments + // with `args_os` and report the first invalid one instead of aborting. + let args = match std::env::args_os() + .map(std::ffi::OsString::into_string) + .collect::, _>>() + { + Ok(args) => args, + Err(invalid) => { + eprintln!( + "updatedb: invalid (non-UTF-8) argument: {}", + invalid.to_string_lossy() + ); + std::process::exit(1); + } + }; let strs: Vec<&str> = args.iter().map(std::convert::AsRef::as_ref).collect(); std::process::exit(findutils::updatedb::updatedb_main(strs.as_slice())); } diff --git a/src/xargs/main.rs b/src/xargs/main.rs index 061ac21e..6ae43936 100644 --- a/src/xargs/main.rs +++ b/src/xargs/main.rs @@ -5,7 +5,21 @@ // https://opensource.org/licenses/MIT. fn main() { - let args = std::env::args().collect::>(); + // `std::env::args` panics on a non-UTF-8 argument, so read the arguments + // with `args_os` and report the first invalid one instead of aborting. + let args = match std::env::args_os() + .map(std::ffi::OsString::into_string) + .collect::, _>>() + { + Ok(args) => args, + Err(invalid) => { + eprintln!( + "xargs: invalid (non-UTF-8) argument: {}", + invalid.to_string_lossy() + ); + std::process::exit(1); + } + }; std::process::exit(findutils::xargs::xargs_main( &args .iter() diff --git a/tests/db_tests.rs b/tests/db_tests.rs index 619d4965..69696e9e 100644 --- a/tests/db_tests.rs +++ b/tests/db_tests.rs @@ -323,3 +323,41 @@ fn test_locate_one_byte_db() { .assert() .code(1); } + +#[cfg(unix)] +#[test] +fn test_locate_non_utf8_argument() { + // A non-UTF-8 argument must produce a clean error, not a panic in + // std::env::args. + use std::ffi::OsString; + use std::os::unix::ffi::OsStringExt; + let assert = Command::cargo_bin("locate") + .expect("couldn't find locate binary") + .arg(OsString::from_vec(vec![0xff])) + .assert() + .code(1); + let stderr = String::from_utf8_lossy(&assert.get_output().stderr); + assert!( + stderr.contains("non-UTF-8"), + "expected an error naming the invalid argument, got: {stderr:?}" + ); +} + +#[cfg(unix)] +#[test] +fn test_updatedb_non_utf8_argument() { + // A non-UTF-8 argument must produce a clean error, not a panic in + // std::env::args. + use std::ffi::OsString; + use std::os::unix::ffi::OsStringExt; + let assert = Command::cargo_bin("updatedb") + .expect("couldn't find updatedb binary") + .arg(OsString::from_vec(vec![0xff])) + .assert() + .code(1); + let stderr = String::from_utf8_lossy(&assert.get_output().stderr); + assert!( + stderr.contains("non-UTF-8"), + "expected an error naming the invalid argument, got: {stderr:?}" + ); +} diff --git a/tests/test_xargs.rs b/tests/test_xargs.rs index 45e9a571..c7858421 100644 --- a/tests/test_xargs.rs +++ b/tests/test_xargs.rs @@ -601,3 +601,17 @@ fn xargs_arg_file_missing_strips_errno() { .stderr_contains(MISSING) .stderr_str_check(|s| !s.contains("(os error")); } + +#[cfg(unix)] +#[test] +fn xargs_non_utf8_argument_is_rejected_gracefully() { + // A non-UTF-8 argument must produce a clean error, not a panic in + // std::env::args. + use std::ffi::OsString; + use std::os::unix::ffi::OsStringExt; + ucmd() + .arg(OsString::from_vec(vec![b'-', b'I', 0xff])) + .fails_with_code(1) + .stderr_contains("non-UTF-8") + .no_stdout(); +}