From 21b7f1b6b67f191ca187910a5fd4cd2cb1eb5353 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 5 Apr 2018 15:15:53 +0200 Subject: [PATCH] hush: fix a few more corner cases with empty-expanding `cmds` See added testcases function old new delta run_pipe 1723 1784 +61 Signed-off-by: Denys Vlasenko --- shell/hush.c | 20 +++++++++++-------- shell/hush_test/hush-psubst/falsetick2.right | 1 + shell/hush_test/hush-psubst/falsetick2.tests | 3 +++ .../hush-redir/redir_backquote1.right | 11 ++++++++++ .../hush-redir/redir_backquote1.tests | 19 ++++++++++++++++++ 5 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 shell/hush_test/hush-psubst/falsetick2.right create mode 100755 shell/hush_test/hush-psubst/falsetick2.tests create mode 100644 shell/hush_test/hush-redir/redir_backquote1.right create mode 100755 shell/hush_test/hush-redir/redir_backquote1.tests diff --git a/shell/hush.c b/shell/hush.c index 43702360a..577faf466 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -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 index 000000000..670f560f1 --- /dev/null +++ b/shell/hush_test/hush-psubst/falsetick2.right @@ -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 index 000000000..cfbd1a5de --- /dev/null +++ b/shell/hush_test/hush-psubst/falsetick2.tests @@ -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 index 000000000..810cc2314 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_backquote1.right @@ -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 index 000000000..41bb4913c --- /dev/null +++ b/shell/hush_test/hush-redir/redir_backquote1.tests @@ -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]"