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 <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-04-05 15:15:53 +02:00
parent 41d8f10813
commit 21b7f1b6b6
5 changed files with 46 additions and 8 deletions

View File

@ -608,7 +608,7 @@ typedef enum redir_type {
struct command { struct command {
pid_t pid; /* 0 if exited */ 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 #if ENABLE_HUSH_LINENO_VAR
unsigned lineno; unsigned lineno;
#endif #endif
@ -8317,25 +8317,26 @@ static NOINLINE int run_pipe(struct pipe *pi)
* Ensure redirects take effect (that is, create files). * Ensure redirects take effect (that is, create files).
* Try "a=t >file" * Try "a=t >file"
*/ */
only_assignments: unsigned i;
G.expand_exitcode = 0; G.expand_exitcode = 0;
only_assignments:
rcode = setup_redirects(command, &squirrel); rcode = setup_redirects(command, &squirrel);
restore_redirects(squirrel); restore_redirects(squirrel);
/* Set shell variables */ /* Set shell variables */
if (G_x_mode) if (G_x_mode)
bb_putchar_stderr('+'); bb_putchar_stderr('+');
while (*argv) { i = 0;
char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1); while (i < command->assignment_cnt) {
char *p = expand_string_to_string(argv[i], /*unbackslash:*/ 1);
if (G_x_mode) if (G_x_mode)
fprintf(stderr, " %s", p); fprintf(stderr, " %s", p);
debug_printf_exec("set shell var:'%s'->'%s'\n", debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
*argv, p);
if (set_local_var(p, /*flag:*/ 0)) { if (set_local_var(p, /*flag:*/ 0)) {
/* assignment to readonly var / putenv error? */ /* assignment to readonly var / putenv error? */
rcode = 1; rcode = 1;
} }
argv++; i++;
} }
if (G_x_mode) if (G_x_mode)
bb_putchar_stderr('\n'); 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 someone gives us an empty string: `cmd with empty output` */
if (!argv_expanded[0]) { if (!argv_expanded[0]) {
free(argv_expanded); free(argv_expanded);
/* `false` still has to set exitcode 1 */
G.expand_exitcode = G.last_exitcode;
goto only_assignments; goto only_assignments;
} }
@ -10021,6 +10024,7 @@ static int helper_export_local(char **argv, unsigned flags)
/* (Un)exporting/making local NAME=VALUE */ /* (Un)exporting/making local NAME=VALUE */
name = xstrdup(name); name = xstrdup(name);
} }
debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
if (set_local_var(name, flags)) if (set_local_var(name, flags))
return EXIT_FAILURE; return EXIT_FAILURE;
} while (*++argv); } while (*++argv);

View File

@ -0,0 +1 @@
Two:2 v:[]

View File

@ -0,0 +1,3 @@
v=v
v=`exit 2` `false`
echo Two:$? v:"[$v]"

View File

@ -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]

View File

@ -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]"