bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] read: non-raw-mode fixes


From: Grisha Levit
Subject: [PATCH] read: non-raw-mode fixes
Date: Wed, 26 Jul 2023 14:23:45 -0400

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

Attachment: 0001-read-non-raw-mode-fixes.patch
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]