From b54d999cc6e6362f05a3c3a53cc1a64261b30f06 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 8 Aug 2025 14:57:19 +0200 Subject: [PATCH] Fix more to handle non-UTF-8 filenames --- src/uu/more/src/more.rs | 17 ++++++++++------- tests/by-util/test_more.rs | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/uu/more/src/more.rs b/src/uu/more/src/more.rs index 8aa6b7729..262dc9940 100644 --- a/src/uu/more/src/more.rs +++ b/src/uu/more/src/more.rs @@ -4,6 +4,7 @@ // file that was distributed with this source code. use std::{ + ffi::OsString, fs::File, io::{BufRead, BufReader, Stdin, Stdout, Write, stdin, stdout}, panic::set_hook, @@ -154,12 +155,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { })); let matches = uu_app().get_matches_from_localized(args); let mut options = Options::from(&matches); - if let Some(files) = matches.get_many::(options::FILES) { + if let Some(files) = matches.get_many::(options::FILES) { let length = files.len(); - let mut files_iter = files.map(|s| s.as_str()).peekable(); - while let (Some(file), next_file) = (files_iter.next(), files_iter.peek()) { - let file = Path::new(file); + let mut files_iter = files.peekable(); + while let (Some(file_os), next_file) = (files_iter.next(), files_iter.peek()) { + let file = Path::new(file_os); if file.is_dir() { show!(UUsageError::new( 0, @@ -188,11 +189,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } Ok(opened_file) => opened_file, }; + let next_file_str = next_file.map(|f| f.to_string_lossy().into_owned()); more( InputType::File(BufReader::new(opened_file)), length > 1, - file.to_str(), - next_file.copied(), + Some(&file.to_string_lossy()), + next_file_str.as_deref(), &mut options, )?; } @@ -311,7 +313,8 @@ pub fn uu_app() -> Command { .required(false) .action(ArgAction::Append) .help(translate!("more-help-files")) - .value_hint(clap::ValueHint::FilePath), + .value_hint(clap::ValueHint::FilePath) + .value_parser(clap::value_parser!(OsString)), ) } diff --git a/tests/by-util/test_more.rs b/tests/by-util/test_more.rs index 4cd984d7c..e925c71b9 100644 --- a/tests/by-util/test_more.rs +++ b/tests/by-util/test_more.rs @@ -126,3 +126,27 @@ fn test_invalid_file_perms() { .stderr_contains("permission denied"); } } + +#[test] +#[cfg(target_os = "linux")] +fn test_more_non_utf8_paths() { + use std::fs; + + if std::io::stdout().is_terminal() { + let (at, mut ucmd) = at_and_ucmd!(); + + // Create test file with normal name first + at.write("temp.txt", "test content for non-UTF-8 file"); + + // Rename to non-UTF-8 name + #[cfg(unix)] + { + use std::os::unix::ffi::OsStrExt; + let file_name = std::ffi::OsStr::from_bytes(b"test_\xFF\xFE.txt"); + fs::rename(at.subdir.join("temp.txt"), at.subdir.join(file_name)).unwrap(); + + // Test that more can handle non-UTF-8 filenames without crashing + ucmd.arg(file_name).succeeds(); + } + } +}