Skip to content

Commit e1837a0

Browse files
committed
sort: --files0-from should not panic when invalid utf-8
1 parent adaaa3f commit e1837a0

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

src/uu/sort/src/sort.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,26 +1291,34 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
12911291
let reader = open_with_open_failed_error(&files0_from)?;
12921292
let buf_reader = BufReader::new(reader);
12931293
for (line_num, line) in buf_reader.split(b'\0').flatten().enumerate() {
1294-
let f = std::str::from_utf8(&line)
1295-
.expect("Could not parse string from zero terminated input.");
1296-
match f {
1297-
STDIN_FILE => {
1298-
return Err(SortError::MinusInStdIn.into());
1294+
// Handle filenames as raw bytes to support non-UTF-8 paths
1295+
#[cfg(unix)]
1296+
let filename = {
1297+
use std::os::unix::ffi::OsStrExt;
1298+
OsStr::from_bytes(&line).to_owned()
1299+
};
1300+
#[cfg(not(unix))]
1301+
let filename = {
1302+
// On non-Unix systems, convert to UTF-8 with replacement chars
1303+
match std::str::from_utf8(&line) {
1304+
Ok(s) => OsString::from(s),
1305+
Err(_) => OsString::from(String::from_utf8_lossy(&line).into_owned()),
12991306
}
1300-
"" => {
1301-
return Err(SortError::ZeroLengthFileName {
1302-
file: files0_from,
1303-
line_num: line_num + 1,
1304-
}
1305-
.into());
1307+
};
1308+
1309+
// Check for special cases using bytes comparison
1310+
if line == b"-" {
1311+
return Err(SortError::MinusInStdIn.into());
1312+
}
1313+
if line.is_empty() {
1314+
return Err(SortError::ZeroLengthFileName {
1315+
file: files0_from,
1316+
line_num: line_num + 1,
13061317
}
1307-
_ => {}
1318+
.into());
13081319
}
13091320

1310-
files.push(OsString::from(
1311-
std::str::from_utf8(&line)
1312-
.expect("Could not parse string from zero terminated input."),
1313-
));
1321+
files.push(filename);
13141322
}
13151323
if files.is_empty() {
13161324
return Err(SortError::EmptyInputFile { file: files0_from }.into());

tests/by-util/test_sort.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,25 @@ fn test_files0_from_zero_length() {
15441544
.stderr_only("sort: -:2: invalid zero-length file name\n");
15451545
}
15461546

1547+
#[test]
1548+
fn test_files0_from_non_utf8_filename() {
1549+
let (at, mut ucmd) = at_and_ucmd!();
1550+
1551+
// Create files with UTF-8 names
1552+
at.touch("file1.txt");
1553+
at.append("file1.txt", "content1\n");
1554+
at.touch("file2.txt");
1555+
at.append("file2.txt", "content2\n");
1556+
1557+
// Create a files0-from list containing non-UTF-8 filename bytes
1558+
let files0_input = b"file1.txt\0\xff\xfe\x00invalid.txt\0file2.txt\0";
1559+
1560+
ucmd.args(&["--files0-from", "-"])
1561+
.pipe_in(files0_input)
1562+
.fails_with_code(2)
1563+
.stderr_contains("No such file or directory");
1564+
}
1565+
15471566
#[test]
15481567
// Test for GNU tests/sort/sort-float.sh
15491568
fn test_g_float() {

0 commit comments

Comments
 (0)