hush: fix handling of '' in ${var:+ARG}
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 20 Jul 2018 15:36:06 +0000 (17:36 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 20 Jul 2018 15:36:06 +0000 (17:36 +0200)
This wasn't an ash bug in dollar_altvalue9, it was hush bug (and bash!)

function                                             old     new   delta
expand_one_var                                      2236    2254     +18
expand_vars_to_list                                 1097    1103      +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 24/0)               Total: 24 bytes

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

diff --git a/shell/ash_test/ash-quoting/dollar_altvalue2.right b/shell/ash_test/ash-quoting/dollar_altvalue2.right
new file mode 100644 (file)
index 0000000..7cf37e3
--- /dev/null
@@ -0,0 +1,69 @@
+Unquoted '':
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+||
+end
+
+Unquoted "":
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+||
+end
+
+Quoted '':
+start:
+|''|
+end
+start:
+|'' |
+end
+start:
+| ''|
+end
+start:
+| '' |
+end
+start:
+|'' ''|
+end
+
+Quoted "":
+start:
+||
+end
+start:
+| |
+end
+start:
+| |
+end
+start:
+|  |
+end
+start:
+| |
+end
diff --git a/shell/ash_test/ash-quoting/dollar_altvalue2.tests b/shell/ash_test/ash-quoting/dollar_altvalue2.tests
new file mode 100755 (executable)
index 0000000..3377eb2
--- /dev/null
@@ -0,0 +1,33 @@
+f() { echo start:; for i; do echo "|$i|"; done; echo end; }
+x=a
+
+echo "Unquoted '':"
+f ${x:+''}
+f ${x:+'' }
+f ${x:+ ''}
+f ${x:+ '' }
+f ${x:+'' ''}
+
+echo
+echo 'Unquoted "":'
+f ${x:+""}
+f ${x:+"" }
+f ${x:+ ""}
+f ${x:+ "" }
+f ${x:+"" ""}
+
+echo
+echo "Quoted '':"
+f "${x:+''}"
+f "${x:+'' }"
+f "${x:+ ''}"
+f "${x:+ '' }"
+f "${x:+'' ''}"
+
+echo
+echo 'Quoted "":'
+f "${x:+""}"
+f "${x:+"" }"
+f "${x:+ ""}"
+f "${x:+ "" }"
+f "${x:+"" ""}"
index fc6c2697cdada577e5e3df343b1bb224a06b4e5f..39342fe7c039512512b0b6cc9e45d29cace8dbf4 100644 (file)
@@ -3,6 +3,7 @@ Unquoted 1:
 |x y|
 |1|
 |2|
+||
 |1 2|
 |A|
 |B|
@@ -14,6 +15,7 @@ Unquoted 2:
 |ax y|
 |1|
 |2|
+||
 |1 2|
 |A|
 |B|
index fc77b89fc7410fa50638f72583793ed546648ecf..559595d2e4b248d271585c4697b28a03b6219e7f 100644 (file)
 #endif
 
 #define SPECIAL_VAR_SYMBOL_STR "\3"
-#define SPECIAL_VAR_SYMBOL_CHR '\3'
 #define SPECIAL_VAR_SYMBOL       3
 /* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */
 #define SPECIAL_VAR_QUOTED_SVS   1
@@ -5950,6 +5949,8 @@ static int encode_then_append_var_plusminus(o_string *output, int n,
                                                break;
                                        o_addqchr(&dest, ch);
                                }
+                               o_addchr(&dest, SPECIAL_VAR_SYMBOL);
+                               o_addchr(&dest, SPECIAL_VAR_SYMBOL);
                                continue;
                        }
                }
@@ -5959,6 +5960,10 @@ static int encode_then_append_var_plusminus(o_string *output, int n,
                }
                if (ch == '"') {
                        dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
+                       if (dest.o_expflags) {
+                               o_addchr(&dest, SPECIAL_VAR_SYMBOL);
+                               o_addchr(&dest, SPECIAL_VAR_SYMBOL);
+                       }
                        continue;
                }
                if (ch == '\\') {
@@ -6565,7 +6570,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
                case SPECIAL_VAR_QUOTED_SVS:
                        /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */
                        /* "^C variable", represents literal ^C char (possible in scripts) */
-                       o_addchr(output, SPECIAL_VAR_SYMBOL_CHR);
+                       o_addchr(output, SPECIAL_VAR_SYMBOL);
                        arg++;
                        break;
 #if ENABLE_HUSH_TICK
@@ -6627,7 +6632,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
                o_addstr(output, arg);
                debug_print_list("expand_vars_to_list[b]", output, n);
        } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
-        && !(cant_be_null & 0x80) /* and all vars were not quoted. */
+        && !(cant_be_null & 0x80)   /* and all vars were not quoted */
+        && !output->has_quoted_part
        ) {
                n--;
                /* allow to reuse list[n] later without re-growth */
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue2.right b/shell/hush_test/hush-quoting/dollar_altvalue2.right
new file mode 100644 (file)
index 0000000..7cf37e3
--- /dev/null
@@ -0,0 +1,69 @@
+Unquoted '':
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+||
+end
+
+Unquoted "":
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+end
+start:
+||
+||
+end
+
+Quoted '':
+start:
+|''|
+end
+start:
+|'' |
+end
+start:
+| ''|
+end
+start:
+| '' |
+end
+start:
+|'' ''|
+end
+
+Quoted "":
+start:
+||
+end
+start:
+| |
+end
+start:
+| |
+end
+start:
+|  |
+end
+start:
+| |
+end
diff --git a/shell/hush_test/hush-quoting/dollar_altvalue2.tests b/shell/hush_test/hush-quoting/dollar_altvalue2.tests
new file mode 100755 (executable)
index 0000000..3377eb2
--- /dev/null
@@ -0,0 +1,33 @@
+f() { echo start:; for i; do echo "|$i|"; done; echo end; }
+x=a
+
+echo "Unquoted '':"
+f ${x:+''}
+f ${x:+'' }
+f ${x:+ ''}
+f ${x:+ '' }
+f ${x:+'' ''}
+
+echo
+echo 'Unquoted "":'
+f ${x:+""}
+f ${x:+"" }
+f ${x:+ ""}
+f ${x:+ "" }
+f ${x:+"" ""}
+
+echo
+echo "Quoted '':"
+f "${x:+''}"
+f "${x:+'' }"
+f "${x:+ ''}"
+f "${x:+ '' }"
+f "${x:+'' ''}"
+
+echo
+echo 'Quoted "":'
+f "${x:+""}"
+f "${x:+"" }"
+f "${x:+ ""}"
+f "${x:+ "" }"
+f "${x:+"" ""}"
index fc6c2697cdada577e5e3df343b1bb224a06b4e5f..39342fe7c039512512b0b6cc9e45d29cace8dbf4 100644 (file)
@@ -3,6 +3,7 @@ Unquoted 1:
 |x y|
 |1|
 |2|
+||
 |1 2|
 |A|
 |B|
@@ -14,6 +15,7 @@ Unquoted 2:
 |ax y|
 |1|
 |2|
+||
 |1 2|
 |A|
 |B|