diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 203bb30a111..49893d03d3b 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -2042,13 +2042,23 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { path: files0_from.clone(), error, })?; - let f = std::str::from_utf8(&line) - .expect("Could not parse string from zero terminated input."); - match f { - STDIN_FILE => { + + let f: OsString = { + #[cfg(unix)] + { + OsStr::from_bytes(&line).to_os_string() + } + #[cfg(not(unix))] + { + String::from_utf8_lossy(&line).into_owned().into() + } + }; + + match f.to_str() { + Some(s) if s == STDIN_FILE => { return Err(SortError::MinusInStdIn.into()); } - "" => { + Some("") => { return Err(SortError::ZeroLengthFileName { file: files0_from, line_num: line_num + 1, @@ -2058,11 +2068,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { _ => {} } - files.push(OsString::from( - std::str::from_utf8(&line) - .expect("Could not parse string from zero terminated input."), - )); + files.push(f); } + if files.is_empty() { return Err(SortError::EmptyInputFile { file: files0_from }.into()); } diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index b0e7602fd7f..45384d20032 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -1851,6 +1851,25 @@ fn test_files0_from_2a() { .stdout_only("a\na\n"); } +#[test] +// Test for GNU tests/sort/sort-files0-from.pl "non-utf8" +#[cfg(unix)] +fn test_files0_from_non_utf8() { + use std::os::unix::ffi::OsStringExt; + let (at, mut ucmd) = at_and_ucmd!(); + + // non-UTF-8 bytes (0xFF) + let filename = std::ffi::OsString::from_vec(b"a\xffb".into()); + std::fs::write(at.plus(&filename), b"20\n10\n").unwrap(); + + let list_contents = vec![b'a', 0xFF, b'b', 0]; + at.write_bytes("list0", &list_contents); + + ucmd.args(&["--files0-from", "list0"]) + .succeeds() + .stdout_only("10\n20\n"); +} + #[test] // Test for GNU tests/sort/sort-files0-from.pl "zero-len" fn test_files0_from_zero_length() {