mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
tr: fix possible usage in invalid utf8 set sequence. (#10791)
This commit is contained in:
@@ -23,6 +23,7 @@ tr-error-write-error = write error
|
||||
# Warning messages
|
||||
tr-warning-unescaped-backslash = warning: an unescaped backslash at end of string is not portable
|
||||
tr-warning-ambiguous-octal-escape = the ambiguous octal escape \{ $origin_octal } is being interpreted as the 2-byte sequence \0{ $actual_octal_tail }, { $outstand_char }
|
||||
tr-warning-invalid-utf8 = invalid utf8 sequence
|
||||
|
||||
# Sequence parsing error messages
|
||||
tr-error-missing-char-class-name = missing character class name '[::]'
|
||||
|
||||
@@ -24,6 +24,7 @@ tr-error-write-error = erreur d'écriture
|
||||
tr-warning-unescaped-backslash = avertissement : une barre oblique inverse non échappée à la fin de la chaîne n'est pas portable
|
||||
tr-warning-ambiguous-octal-escape = l'échappement octal ambigu \{ $origin_octal } est en cours
|
||||
d'interprétation comme la séquence de 2 octets \0{ $actual_octal_tail }, { $outstand_char }
|
||||
tr-warning-invalid-utf8 = séquence UTF-8 non valide
|
||||
|
||||
# Messages d'erreur d'analyse de séquence
|
||||
tr-error-missing-char-class-name = nom de classe de caractères manquant '[::]'
|
||||
|
||||
@@ -379,13 +379,16 @@ impl Sequence {
|
||||
let str_to_parse = std::str::from_utf8(out).unwrap();
|
||||
let result = u8::from_str_radix(str_to_parse, 8).ok();
|
||||
if result.is_none() {
|
||||
let origin_octal: &str = std::str::from_utf8(input).unwrap();
|
||||
let actual_octal_tail: &str = std::str::from_utf8(&input[0..2]).unwrap();
|
||||
let outstand_char: char = char::from_u32(input[2] as u32).unwrap();
|
||||
show_warning!(
|
||||
"{}",
|
||||
translate!("tr-warning-ambiguous-octal-escape", "origin_octal" => origin_octal, "actual_octal_tail" => actual_octal_tail, "outstand_char" => outstand_char)
|
||||
);
|
||||
if let Ok(origin_octal) = std::str::from_utf8(input) {
|
||||
let actual_octal_tail: &str = std::str::from_utf8(&input[0..2]).unwrap();
|
||||
let outstand_char: char = char::from_u32(input[2] as u32).unwrap();
|
||||
show_warning!(
|
||||
"{}",
|
||||
translate!("tr-warning-ambiguous-octal-escape", "origin_octal" => origin_octal, "actual_octal_tail" => actual_octal_tail, "outstand_char" => outstand_char)
|
||||
);
|
||||
} else {
|
||||
show_warning!("{}", translate!("tr-warning-invalid-utf8"));
|
||||
}
|
||||
}
|
||||
result
|
||||
},
|
||||
|
||||
@@ -1544,6 +1544,30 @@ fn test_non_digit_repeat() {
|
||||
.stderr_only("tr: invalid repeat count 'c' in [c*n] construct\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_octal_escape_ambiguous_followed_by_non_utf8() {
|
||||
// This case does not trigger the panic
|
||||
let set1 = OsStr::from_bytes(b"\\501a");
|
||||
new_ucmd!()
|
||||
.arg("-d")
|
||||
.arg(set1)
|
||||
.pipe_in("(1a)")
|
||||
.succeeds()
|
||||
.stderr_contains("warning: the ambiguous octal escape")
|
||||
.stdout_is(")");
|
||||
|
||||
// An user is not supposed to use this invalid utf8 set but
|
||||
// we would need to make the command more error-proof still
|
||||
let set1 = OsStr::from_bytes(b"\\501\xff");
|
||||
new_ucmd!()
|
||||
.arg("-d")
|
||||
.arg(set1)
|
||||
.pipe_in([b'(', b'1', 0xff, b')'])
|
||||
.succeeds()
|
||||
.stderr_contains("warning: invalid utf8 sequence");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_failed_write_is_reported() {
|
||||
|
||||
Reference in New Issue
Block a user