diff --git a/builtin.cpp b/builtin.cpp index 597f51c5b..44f4e84ea 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -1937,8 +1937,8 @@ static int builtin_echo(parser_t &parser, wchar_t **argv) unsigned char narrow_val = 0; if (builtin_echo_parse_numeric_sequence(str + j + 1, &consumed, &narrow_val)) { - /* Here consumed must have been set to something */ - wc = narrow_val; //is this OK for conversion? + /* Here consumed must have been set to something. The narrow_val is a literal byte that we want to output (#1894) */ + wc = ENCODE_DIRECT_BASE + narrow_val % 256; } else { diff --git a/builtin_printf.cpp b/builtin_printf.cpp index f77a3a721..916166b0f 100644 --- a/builtin_printf.cpp +++ b/builtin_printf.cpp @@ -357,16 +357,17 @@ long builtin_printf_state_t::print_esc(const wchar_t *escstart, bool octal_0) esc_value = esc_value * 16 + hex_to_bin(*p); if (esc_length == 0) this->fatal_error(_(L"missing hexadecimal number in escape")); - this->append_output(esc_value); + this->append_output(ENCODE_DIRECT_BASE + esc_value % 256); } else if (is_octal_digit(*p)) { /* Parse \0ooo (if octal_0 && *p == L'0') or \ooo (otherwise). Allow \ooo if octal_0 && *p != L'0'; this is an undocumented extension to POSIX that is compatible with Bash 2.05b. */ + /* Wrap mod 256, which matches historic behavior */ for (esc_length = 0, p += octal_0 && *p == L'0'; esc_length < 3 && is_octal_digit(*p); ++esc_length, ++p) esc_value = esc_value * 8 + octal_to_bin(*p); - this->append_output(esc_value); + this->append_output(ENCODE_DIRECT_BASE + esc_value % 256); } else if (*p && wcschr(L"\"\\abcefnrtv", *p)) { diff --git a/tests/printf.in b/tests/printf.in index 06b9cbb43..78c0d9771 100644 --- a/tests/printf.in +++ b/tests/printf.in @@ -30,4 +30,8 @@ echo # Bogus printf specifier, should produce no stdout printf "%5" 10 ^ /dev/null +# Octal escapes produce literal bytes, not characters +# \376 is 0xFE +printf '\376' | xxd -p + true diff --git a/tests/printf.out b/tests/printf.out index 04e0a94bb..f1c1960ba 100644 --- a/tests/printf.out +++ b/tests/printf.out @@ -13,3 +13,4 @@ foo bar baz I P Q R Test escapes a +fe diff --git a/tests/test1.in b/tests/test1.in index 6f25e8ae6..1a7016956 100644 --- a/tests/test1.in +++ b/tests/test1.in @@ -118,6 +118,8 @@ echo -e 'abc\cdef' # won't output a newline! echo '' echo - +echo -ne '\376' | xxd -p + echo -e Catch your breath echo -e 'abc\x21def' diff --git a/tests/test1.out b/tests/test1.out index 5f002f2a1..744348d50 100644 --- a/tests/test1.out +++ b/tests/test1.out @@ -34,6 +34,7 @@ abcQdef abcQ2def abc - +fe Catch your breath abc!def abc!1def