Skip to content

Commit 7807c8d

Browse files
leeeweesylvestre
authored andcommitted
numfmt: do not panic on a multibyte whitespace field separator
write_formatted_with_whitespace normalized the delimiter before the second and subsequent selected fields by writing a single space and dropping the first byte of the leading whitespace run with `&prefix[1..]`. That assumed an ASCII separator: WhitespaceSplitter splits on Unicode `char::is_whitespace`, so a multibyte separator (e.g. U+3000 IDEOGRAPHIC SPACE) made `&prefix[1..]` slice inside the character and abort with a char-boundary panic. Drop the first character instead of the first byte, using its UTF-8 length, so the slice always lands on a char boundary.
1 parent 93fa095 commit 7807c8d

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

src/uu/numfmt/src/format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ pub fn write_formatted_with_whitespace<W: std::io::Write + ?Sized>(
845845
// add delimiter before second and subsequent fields
846846
let prefix = if n > 1 {
847847
writer.write_all(b" ").unwrap();
848-
&prefix[1..]
848+
&prefix[prefix.chars().next().map_or(0, char::len_utf8)..]
849849
} else {
850850
prefix
851851
};

tests/by-util/test_numfmt.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,16 @@ fn test_format_selected_field() {
431431
.stdout_only("1K 2000 3K\n");
432432
}
433433

434+
#[test]
435+
fn test_field_with_multibyte_whitespace_separator() {
436+
// A multibyte Unicode whitespace separator (U+3000) before a selected field
437+
// is normalized to a single space rather than sliced mid-character.
438+
new_ucmd!()
439+
.args(&["--field", "2", "1 2"])
440+
.succeeds()
441+
.stdout_only("1 2\n");
442+
}
443+
434444
#[test]
435445
fn test_format_selected_fields() {
436446
new_ucmd!()

0 commit comments

Comments
 (0)