Skip to content

stat: str char-boundary panic on a %.P precision that truncates a multibyte string value mid-character #13750

Description

@leeewee

stat's string formatter (print_str) applies a %.P precision by byte-slicing the value: &s[..p].

/// * `s` - The string to be printed.
/// * `flags` - A reference to the Flags struct containing formatting flags.
/// * `width` - The width of the field for the printed string.
/// * `precision` - How many digits of precision, if any.
fn print_str(s: &str, flags: Flags, width: usize, precision: Precision) {
let s = match precision {
Precision::Number(p) if p < s.len() => &s[..p],
_ => s,
};
pad_and_print(s, flags.left, width, Padding::Space);
}

When the value is a multibyte UTF-8 string (e.g. a file name with non-ASCII characters) and the precision p lands in the middle of a multibyte character, the slice is not on a char boundary and the process panics (byte index N is not a char boundary) and aborts (exit 134).

$ mkdir -p /tmp/st && : > "$(printf '/tmp/st/\xc3\xa9')"   # a file named é (2 bytes)
$ stat -c '%.9n' "$(printf '/tmp/st/\xc3\xa9')"            # path is 10 bytes; .9 splits the é
thread 'main' (2444786) panicked at src/uu/stat/src/stat.rs:409:50:
end byte index 9 is not a char boundary; it is inside 'é' (bytes 8..10 of string)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Aborted (core dumped)
$ echo $?
134

Any %.P<string-directive> where P falls inside a multibyte char of the value triggers it.

GNU stat truncates by bytes without crashing.

$ stat -c '%.9n' "$(printf '/tmp/st/\xc3\xa9')" ; echo $?   # GNU: prints /tmp/st/<partial>, exit 0
/tmp/st/�
0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions