From 08992ec6b31406ba7f4722f09ab6f48b9aff0662 Mon Sep 17 00:00:00 2001 From: Andrew Liebenow Date: Wed, 18 Sep 2024 17:29:11 -0500 Subject: [PATCH] tr: fix unescaped trailing backslash warning This warning is being emitted whenever the input string ends with a backslash, even if the backslash is escaped. --- src/uu/tr/src/tr.rs | 23 ++++++++++++++++++----- tests/by-util/test_tr.rs | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/uu/tr/src/tr.rs b/src/uu/tr/src/tr.rs index defe575af..867d99755 100644 --- a/src/uu/tr/src/tr.rs +++ b/src/uu/tr/src/tr.rs @@ -98,11 +98,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } if let Some(first) = sets.first() { - if let Some(b'\\') = os_str_as_bytes(first)?.last() { - show!(USimpleError::new( - 0, - "warning: an unescaped backslash at end of string is not portable" - )); + let slice = os_str_as_bytes(first)?; + + let mut iter = slice.iter(); + + if let Some(b'\\') = iter.next_back() { + match iter.next_back() { + Some(b'\\') => { + // The trailing backslash has a backslash preceding it, so it is properly escaped + } + _ => { + // The trailing backslash has a non-backslash character before it OR is the only character in the + // string, so the warning applies + show!(USimpleError::new( + 0, + "warning: an unescaped backslash at end of string is not portable" + )); + } + } } } diff --git a/tests/by-util/test_tr.rs b/tests/by-util/test_tr.rs index 7445b1dc5..c8f94d9eb 100644 --- a/tests/by-util/test_tr.rs +++ b/tests/by-util/test_tr.rs @@ -1445,3 +1445,26 @@ fn test_truncate_non_utf8_set() { .succeeds() .stdout_is_bytes(b"\x010mp12"); } + +#[test] +#[cfg(unix)] +fn test_unescaped_backslash_warning_false_positive() { + // Was erroneously printing this warning (even though the backslash was escaped): + // "tr: warning: an unescaped backslash at end of string is not portable" + new_ucmd!() + .args(&["-d", r"\\"]) + .pipe_in(r"a\b\c\") + .succeeds() + .stdout_only("abc"); +} + +#[test] +#[cfg(unix)] +fn test_trailing_backslash_is_only_input_character() { + new_ucmd!() + .args(&["-d", r"\"]) + .pipe_in(r"a\b\c\") + .succeeds() + .stderr_is("tr: warning: an unescaped backslash at end of string is not portable\n") + .stdout_is("abc"); +}