This patches addresses a few issues with `read' when not in raw mode. If the last character read was an (unescaped) backslash, store it as such instead of as a CTLESC. Avoids:
$ printf '\\' | { read; echo "${REPLY@Q}"; } bash: DEBUG warning: dequote_string: string with bare CTLESC $'\001' If an escaped null byte is read, skip it as we do with an unescaped one, instead of adding it to input_string. Avoids: $ printf 'A\\\0B\nC\n' | while read; do echo "${REPLY@Q}"; done 'A' 'C' $ printf '\\\0' | { read; echo "${REPLY@Q}"; } bash: DEBUG warning: dequote_string: string with bare CTLESC $'\001' # even after fix for first issue If IFS contains \177 and the input consists of only backslash-newline pairs and a sole \177, prevent the bare CTLNUL from being turned into an empty string. Avoids: $ printf '\\\n\177' | { IFS=$'\177' read; echo "${REPLY@Q}"; } '' --- builtins/read.def | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/builtins/read.def b/builtins/read.def index 5b2621fe..84878699 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -404,7 +404,7 @@ read_builtin (WORD_LIST *list) input_string[0] = '\0'; pass_next = 0; /* Non-zero signifies last char was backslash. */ - saw_escape = 0; /* Non-zero signifies that we saw an escape char */ + saw_escape = 0; /* Index+1 of when we last saw an escape char. */ /* More input and options validation */ if (nflag == 1 && nchars == 0) @@ -751,11 +751,11 @@ read_builtin (WORD_LIST *list) if (pass_next) { pass_next = 0; - if (c == '\n') + if (c == '\n' || c == '\0') { if (skip_ctlesc == 0 && i > 0) i--; /* back up over the CTLESC */ - if (interactive && input_is_tty && raw == 0) + if (interactive && input_is_tty && raw == 0 && c == '\n') print_ps2 = 1; } else @@ -769,8 +769,8 @@ read_builtin (WORD_LIST *list) pass_next++; if (skip_ctlesc == 0) { - saw_escape++; input_string[i++] = CTLESC; + saw_escape=i; } continue; } @@ -783,8 +783,8 @@ read_builtin (WORD_LIST *list) if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL)) { - saw_escape++; input_string[i++] = CTLESC; + saw_escape=i; } add_char: @@ -825,6 +825,12 @@ add_char: if (nchars > 0 && nr >= nchars) break; } + + if (i && saw_escape == i && input_string[i-1] == CTLESC) + input_string[i-1] = '\\'; /* Preserve trailing backslash */ + else if (skip_ctlnul && i == 1 & saw_escape == 1 && input_string[0] == CTLNUL) + saw_escape = 0; /* Avoid dequoting bare CTLNUL */ + input_string[i] = '\0'; check_read_timeout (); -- 2.41.0
0001-read-non-raw-mode-fixes.patch
Description: Binary data