hush: do not drop backslash from eval 'echo ok\'
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 10 Apr 2018 23:15:33 +0000 (01:15 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 10 Apr 2018 23:15:33 +0000 (01:15 +0200)
newer bash does not drop it, most other shells too

function                                             old     new   delta
unbackslash                                           39      57     +18
parse_stream                                        2753    2751      -2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 18/-2)              Total: 16 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c
shell/ash_test/ash-parsing/bkslash_eof1.right [new file with mode: 0644]
shell/ash_test/ash-parsing/bkslash_eof1.tests [new file with mode: 0755]
shell/ash_test/ash-redir/redir_exec1.right
shell/hush.c
shell/hush_test/hush-parsing/bkslash_eof1.right

index 713219b6e75b22c071b2bcb3c5052913f7235dd5..6f8bc904287d2c845159ba147516f8b197d7e4d5 100644 (file)
  * TODO:
  * singleword+noglob expansion:
  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
- *   [[ /bin/* ]]; echo 0:$?
+ *   [[ /bin/n* ]]; echo 0:$?
  * -a/-o are not AND/OR ops! (they are just strings)
  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
  * = is glob match operator, not equality operator: STR = GLOB
diff --git a/shell/ash_test/ash-parsing/bkslash_eof1.right b/shell/ash_test/ash-parsing/bkslash_eof1.right
new file mode 100644 (file)
index 0000000..6c6df0b
--- /dev/null
@@ -0,0 +1 @@
+ok\
diff --git a/shell/ash_test/ash-parsing/bkslash_eof1.tests b/shell/ash_test/ash-parsing/bkslash_eof1.tests
new file mode 100755 (executable)
index 0000000..97629cb
--- /dev/null
@@ -0,0 +1 @@
+eval 'echo ok\'
index d4393d10c9b5f32ab77a2e66a435320585315db5..c98455bf541b2f11d31218325ab8ee467f87be91 100644 (file)
@@ -1,2 +1,2 @@
-redir_exec1.tests: line 1: can't create /cant/be/created: nonexistent directory
+./redir_exec1.tests: line 1: can't create /cant/be/created: nonexistent directory
 First
index 3afb70cb042882be2bac29a154ef1deeea9d397a..523fc1a31bab6dfb6c41b77162535aafcc660927 100644 (file)
@@ -83,7 +83,7 @@
  * Status of [[ support:
  * [[ args ]] are CMD_SINGLEWORD_NOGLOB:
  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
- *   [[ /bin/* ]]; echo 0:$?
+ *   [[ /bin/n* ]]; echo 0:$?
  * TODO:
  * &&/|| are AND/OR ops, -a/-o are not
  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
@@ -1426,8 +1426,19 @@ static char *unbackslash(char *src)
 {
        char *dst = src = strchrnul(src, '\\');
        while (1) {
-               if (*src == '\\')
+               if (*src == '\\') {
                        src++;
+                       if (*src != '\0') {
+                               /* \x -> x */
+                               *dst++ = *src++;
+                               continue;
+                       }
+                       /* else: "\<nul>". Do not delete this backslash.
+                        * Testcase: eval 'echo ok\'
+                        */
+                       *dst++ = '\\';
+                       /* fallthrough */
+               }
                if ((*dst++ = *src++) == '\0')
                        break;
        }
@@ -5392,16 +5403,17 @@ static struct pipe *parse_stream(char **pstring,
                        continue; /* get next char */
                case '\\':
                        /*nommu_addchr(&ctx.as_string, '\\'); - already done */
+                       o_addchr(&ctx.word, '\\');
                        ch = i_getch(input);
                        if (ch == EOF) {
-                               /* Ignore this '\'. Testcase: eval 'echo Ok\' */
-#if !BB_MMU
+                               /* Testcase: eval 'echo Ok\' */
+
+#if 0 /* bash-4.3.43 was removing backslash, but 4.4.19 retains it, most other shells too */
                                /* Remove trailing '\' from ctx.as_string */
                                ctx.as_string.data[--ctx.as_string.length] = '\0';
 #endif
                                continue; /* get next char */
                        }
-                       o_addchr(&ctx.word, '\\');
                        /* Example: echo Hello \2>file
                         * we need to know that word 2 is quoted
                         */
index 9766475a4185a151dc9d56d614ffb9aaea3bfd42..6c6df0b0c4292d41ac06b8ebf1522e85e700f337 100644 (file)
@@ -1 +1 @@
-ok
+ok\