hush: fix two corner cases in ${v/pattern/repl}. Closes 10686
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 25 Jan 2018 13:07:40 +0000 (14:07 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 25 Jan 2018 13:07:40 +0000 (14:07 +0100)
function                                             old     new   delta
expand_one_var                                      1592    1618     +26

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c
shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right [new file with mode: 0644]
shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests [new file with mode: 0755]
shell/hush_test/hush-vars/var_bash_repl_empty_var.right [new file with mode: 0644]
shell/hush_test/hush-vars/var_bash_repl_empty_var.tests [new file with mode: 0755]

index a9183c82f142cb8b2a4a7761090d810ab2957243..cf3c731bcafab6a94ddaa69858012b92799ea294 100644 (file)
@@ -5643,6 +5643,10 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c
        unsigned res_len = 0;
        unsigned repl_len = strlen(repl);
 
+       /* Null pattern never matches, including if "var" is empty */
+       if (!pattern[0])
+               return result; /* NULL, no replaces happened */
+
        while (1) {
                int size;
                char *s = strstr_pattern(val, pattern, &size);
@@ -5809,8 +5813,6 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
                         * and if // is used, it is encoded as \:
                         * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
                         */
-                       /* Empty variable always gives nothing: */
-                       // "v=''; echo ${v/*/w}" prints "", not "w"
                        if (val && val[0]) {
                                /* pattern uses non-standard expansion.
                                 * repl should be unbackslashed and globbed
@@ -5846,6 +5848,13 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
                                        val = to_be_freed;
                                free(pattern);
                                free(repl);
+                       } else {
+                               /* Empty variable always gives nothing */
+                               // "v=''; echo ${v/*/w}" prints "", not "w"
+                               /* Just skip "replace" part */
+                               *p++ = SPECIAL_VAR_SYMBOL;
+                               p = strchr(p, SPECIAL_VAR_SYMBOL);
+                               *p = '\0';
                        }
                }
 #endif /* BASH_PATTERN_SUBST */
diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right b/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right
new file mode 100644 (file)
index 0000000..d400a7e
--- /dev/null
@@ -0,0 +1,2 @@
+v
+Ok:0
diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests b/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests
new file mode 100755 (executable)
index 0000000..6e8aa2a
--- /dev/null
@@ -0,0 +1,3 @@
+v=v
+echo ${v//}
+echo Ok:$?
diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_var.right b/shell/hush_test/hush-vars/var_bash_repl_empty_var.right
new file mode 100644 (file)
index 0000000..8929167
--- /dev/null
@@ -0,0 +1,2 @@
+
+Ok:0
diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests b/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests
new file mode 100755 (executable)
index 0000000..73a43d3
--- /dev/null
@@ -0,0 +1,3 @@
+v=''
+echo ${v/*/w}
+echo Ok:$?