aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--builtin.cpp4
-rw-r--r--builtin_printf.cpp5
-rw-r--r--tests/printf.in4
-rw-r--r--tests/printf.out1
-rw-r--r--tests/test1.in2
-rw-r--r--tests/test1.out1
6 files changed, 13 insertions, 4 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 597f51c5..44f4e84e 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 f77a3a72..916166b0 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 06b9cbb4..78c0d977 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 04e0a94b..f1c1960b 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 6f25e8ae..1a701695 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 5f002f2a..744348d5 100644
--- a/tests/test1.out
+++ b/tests/test1.out
@@ -34,6 +34,7 @@ abcQdef
abcQ2def
abc
-
+fe
Catch your breath
abc!def
abc!1def