hush: fix a few more corner cases with empty-expanding `cmds`
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 5 Apr 2018 13:15:53 +0000 (15:15 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 5 Apr 2018 13:15:53 +0000 (15:15 +0200)
See added testcases

function                                             old     new   delta
run_pipe                                            1723    1784     +61

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

index 43702360aeebd0137fbeae80066501f7dc038903..577faf466145c2e0046e855cc2bf542163fe5a70 100644 (file)
@@ -608,7 +608,7 @@ typedef enum redir_type {
 
 struct command {
        pid_t pid;                  /* 0 if exited */
-       int assignment_cnt;         /* how many argv[i] are assignments? */
+       unsigned assignment_cnt;    /* how many argv[i] are assignments? */
 #if ENABLE_HUSH_LINENO_VAR
        unsigned lineno;
 #endif
@@ -8317,25 +8317,26 @@ static NOINLINE int run_pipe(struct pipe *pi)
                         * Ensure redirects take effect (that is, create files).
                         * Try "a=t >file"
                         */
- only_assignments:
+                       unsigned i;
                        G.expand_exitcode = 0;
-
+ only_assignments:
                        rcode = setup_redirects(command, &squirrel);
                        restore_redirects(squirrel);
+
                        /* Set shell variables */
                        if (G_x_mode)
                                bb_putchar_stderr('+');
-                       while (*argv) {
-                               char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1);
+                       i = 0;
+                       while (i < command->assignment_cnt) {
+                               char *p = expand_string_to_string(argv[i], /*unbackslash:*/ 1);
                                if (G_x_mode)
                                        fprintf(stderr, " %s", p);
-                               debug_printf_exec("set shell var:'%s'->'%s'\n",
-                                               *argv, p);
+                               debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
                                if (set_local_var(p, /*flag:*/ 0)) {
                                        /* assignment to readonly var / putenv error? */
                                        rcode = 1;
                                }
-                               argv++;
+                               i++;
                        }
                        if (G_x_mode)
                                bb_putchar_stderr('\n');
@@ -8365,6 +8366,8 @@ static NOINLINE int run_pipe(struct pipe *pi)
                /* If someone gives us an empty string: `cmd with empty output` */
                if (!argv_expanded[0]) {
                        free(argv_expanded);
+                       /* `false` still has to set exitcode 1 */
+                       G.expand_exitcode = G.last_exitcode;
                        goto only_assignments;
                }
 
@@ -10021,6 +10024,7 @@ static int helper_export_local(char **argv, unsigned flags)
                        /* (Un)exporting/making local NAME=VALUE */
                        name = xstrdup(name);
                }
+               debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
                if (set_local_var(name, flags))
                        return EXIT_FAILURE;
        } while (*++argv);
diff --git a/shell/hush_test/hush-psubst/falsetick2.right b/shell/hush_test/hush-psubst/falsetick2.right
new file mode 100644 (file)
index 0000000..670f560
--- /dev/null
@@ -0,0 +1 @@
+Two:2 v:[]
diff --git a/shell/hush_test/hush-psubst/falsetick2.tests b/shell/hush_test/hush-psubst/falsetick2.tests
new file mode 100755 (executable)
index 0000000..cfbd1a5
--- /dev/null
@@ -0,0 +1,3 @@
+v=v
+v=`exit 2` `false`
+echo Two:$? v:"[$v]"
diff --git a/shell/hush_test/hush-redir/redir_backquote1.right b/shell/hush_test/hush-redir/redir_backquote1.right
new file mode 100644 (file)
index 0000000..810cc23
--- /dev/null
@@ -0,0 +1,11 @@
+hush: can't open '/cant/be/created': No such file or directory
+First
+One:1 v1:[]
+hush: can't open '/cant/be/created': No such file or directory
+Second
+One:1 v2:[]
+Third
+Zero:0 v3:[]
+Fourth
+Zero:0 v4:[]
+Zero:0 v5:[1]
diff --git a/shell/hush_test/hush-redir/redir_backquote1.tests b/shell/hush_test/hush-redir/redir_backquote1.tests
new file mode 100755 (executable)
index 0000000..41bb491
--- /dev/null
@@ -0,0 +1,19 @@
+v=v
+v=`echo First >&2` `` >/cant/be/created
+echo One:$? v1:"[$v]"
+
+v=v
+v=`echo Second >&2` `true` >/cant/be/created
+echo One:$? v2:"[$v]"
+
+v=v
+v=`echo Third >&2` `true` 2>/dev/null
+echo Zero:$? v3:"[$v]"
+
+v=v
+v=`echo Fourth >&2` `false` 2>/dev/null
+echo Zero:$? v4:"[$v]"
+
+v=v
+v=`echo $?` `false` 2>/dev/null
+echo Zero:$? v5:"[$v]"