diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 9219876879f..e5ad4bcd459 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -1997,7 +1997,12 @@ fn should_display(entry: &DirEntry, config: &Config) -> bool { require_literal_separator: false, case_sensitive: true, }; - let file_name = entry.file_name().into_string().unwrap(); + let file_name = entry.file_name(); + // If the decoding fails, still show an incorrect rendering + let file_name = match file_name.to_str() { + Some(s) => s.to_string(), + None => file_name.to_string_lossy().into_owned(), + }; !config .ignore_patterns .iter() diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index d460952ed97..45ced867a46 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -7,6 +7,10 @@ use crate::common::util::TestScenario; use nix::unistd::{close, dup}; use regex::Regex; use std::collections::HashMap; +#[cfg(target_os = "linux")] +use std::ffi::OsStr; +#[cfg(target_os = "linux")] +use std::os::unix::ffi::OsStrExt; #[cfg(all(unix, feature = "chmod"))] use std::os::unix::io::IntoRawFd; use std::path::Path; @@ -3434,3 +3438,13 @@ fn test_device_number() { .succeeds() .stdout_contains(major_minor_str); } + +#[test] +#[cfg(target_os = "linux")] +fn test_invalid_utf8() { + let (at, mut ucmd) = at_and_ucmd!(); + + let filename = OsStr::from_bytes(b"-\xE0-foo"); + at.touch(filename); + ucmd.succeeds(); +}