hush: fix handling of empty arguments
function old new delta builtin_exec 25 83 +58 parse_stream 2242 2261 +19 run_pipe 1782 1787 +5 static.pseudo_null_str - 3 +3 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/0 up/down: 85/0) Total: 85 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
7673e7fda4
commit
f37eb3999b
43
shell/hush.c
43
shell/hush.c
@ -2185,7 +2185,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
|
|||||||
|
|
||||||
ored_ch = 0;
|
ored_ch = 0;
|
||||||
|
|
||||||
debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg);
|
debug_printf_expand("expand_vars_to_list: arg:'%s' or_mask:%x\n", arg, or_mask);
|
||||||
debug_print_list("expand_vars_to_list", output, n);
|
debug_print_list("expand_vars_to_list", output, n);
|
||||||
n = o_save_ptr(output, n);
|
n = o_save_ptr(output, n);
|
||||||
debug_print_list("expand_vars_to_list[0]", output, n);
|
debug_print_list("expand_vars_to_list[0]", output, n);
|
||||||
@ -3425,7 +3425,7 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save,
|
|||||||
sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
|
sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
bb_perror_msg("can't execute '%s'", argv[0]);
|
bb_perror_msg("can't execute '%s'", argv[0]);
|
||||||
_exit(EXIT_FAILURE);
|
_exit(127); /* bash compat */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called after [v]fork() in run_pipe
|
/* Called after [v]fork() in run_pipe
|
||||||
@ -3895,7 +3895,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
|
argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if someone gives us an empty string: ``, $(), ... */
|
/* if someone gives us an empty string: `cmd with empty output` */
|
||||||
if (!argv_expanded[0]) {
|
if (!argv_expanded[0]) {
|
||||||
debug_leave();
|
debug_leave();
|
||||||
return 0;
|
return 0;
|
||||||
@ -5802,7 +5802,7 @@ static int parse_stream_dquoted(o_string *as_string,
|
|||||||
if (ch != '\n') {
|
if (ch != '\n') {
|
||||||
next = i_peek(input);
|
next = i_peek(input);
|
||||||
}
|
}
|
||||||
debug_printf_parse(": ch=%c (%d) escape=%d\n",
|
debug_printf_parse("\" ch=%c (%d) escape=%d\n",
|
||||||
ch, ch, dest->o_escape);
|
ch, ch, dest->o_escape);
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
if (next == EOF) {
|
if (next == EOF) {
|
||||||
@ -5882,6 +5882,11 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
end_trigger ? end_trigger : 'X');
|
end_trigger ? end_trigger : 'X');
|
||||||
debug_enter();
|
debug_enter();
|
||||||
|
|
||||||
|
/* If very first arg is "" or '', dest.data may end up NULL.
|
||||||
|
* Preventing this: */
|
||||||
|
o_addchr(&dest, '\0');
|
||||||
|
dest.length = 0;
|
||||||
|
|
||||||
G.ifs = get_local_var_value("IFS");
|
G.ifs = get_local_var_value("IFS");
|
||||||
if (G.ifs == NULL)
|
if (G.ifs == NULL)
|
||||||
G.ifs = " \t\n";
|
G.ifs = " \t\n";
|
||||||
@ -6979,16 +6984,32 @@ static int FAST_FUNC builtin_cd(char **argv)
|
|||||||
|
|
||||||
static int FAST_FUNC builtin_exec(char **argv)
|
static int FAST_FUNC builtin_exec(char **argv)
|
||||||
{
|
{
|
||||||
|
static const char pseudo_null_str[] = { SPECIAL_VAR_SYMBOL, SPECIAL_VAR_SYMBOL, '\0' };
|
||||||
|
char **pp = argv;
|
||||||
|
#if !BB_MMU
|
||||||
|
nommu_save_t dummy;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (*++argv == NULL)
|
if (*++argv == NULL)
|
||||||
return EXIT_SUCCESS; /* bash does this */
|
return EXIT_SUCCESS; /* bash does this */
|
||||||
{
|
|
||||||
#if !BB_MMU
|
/* Make sure empty arguments aren't ignored */
|
||||||
nommu_save_t dummy;
|
/* Example: exec ls '' */
|
||||||
#endif
|
pp = argv;
|
||||||
/* TODO: if exec fails, bash does NOT exit! We do... */
|
while (*pp) {
|
||||||
pseudo_exec_argv(&dummy, argv, 0, NULL);
|
if ((*pp)[0] == '\0')
|
||||||
/* never returns */
|
*pp = (char*)pseudo_null_str;
|
||||||
|
pp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Careful: we can end up here after [v]fork. Do not restore
|
||||||
|
* tty pgrp then, only top-level shell process does that */
|
||||||
|
if (G_saved_tty_pgrp && getpid() == G.root_pid)
|
||||||
|
tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
|
||||||
|
|
||||||
|
/* TODO: if exec fails, bash does NOT exit! We do... */
|
||||||
|
pseudo_exec_argv(&dummy, argv, 0, NULL);
|
||||||
|
/* never returns */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FAST_FUNC builtin_exit(char **argv)
|
static int FAST_FUNC builtin_exit(char **argv)
|
||||||
|
6
shell/hush_test/hush-misc/empty_args.right
Normal file
6
shell/hush_test/hush-misc/empty_args.right
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Null 0th arg:
|
||||||
|
hush: can't execute '': No such file or directory
|
||||||
|
127
|
||||||
|
Null 1st arg:
|
||||||
|
0
|
||||||
|
Null arg in exec:
|
9
shell/hush_test/hush-misc/empty_args.tests
Executable file
9
shell/hush_test/hush-misc/empty_args.tests
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
echo Null 0th arg:
|
||||||
|
""
|
||||||
|
echo $?
|
||||||
|
echo Null 1st arg:
|
||||||
|
# printf without args would print usage info
|
||||||
|
printf ""
|
||||||
|
echo $?
|
||||||
|
echo Null arg in exec:
|
||||||
|
exec printf ""
|
@ -1,14 +1,17 @@
|
|||||||
0
|
0
|
||||||
0
|
0
|
||||||
|
hush: can't execute '': No such file or directory
|
||||||
|
0
|
||||||
|
hush: can't execute '': No such file or directory
|
||||||
|
0
|
||||||
|
0
|
||||||
0
|
0
|
||||||
0
|
0
|
||||||
0
|
0
|
||||||
|
hush: can't execute '': No such file or directory
|
||||||
|
0
|
||||||
|
hush: can't execute '': No such file or directory
|
||||||
0
|
0
|
||||||
0
|
0
|
||||||
0
|
0
|
||||||
0
|
hush: can't execute '': No such file or directory
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
true; ``; echo $?
|
true; ``; echo $?
|
||||||
false; ``; echo $?
|
false; ``; echo $?
|
||||||
|
# UNFIXED BUG. bash sets $? to 127:
|
||||||
true; `""`; echo $?
|
true; `""`; echo $?
|
||||||
|
# bash sets $? to 127:
|
||||||
false; `""`; echo $?
|
false; `""`; echo $?
|
||||||
true; ` `; echo $?
|
true; ` `; echo $?
|
||||||
false; ` `; echo $?
|
false; ` `; echo $?
|
||||||
|
|
||||||
true; $(); echo $?
|
true; $(); echo $?
|
||||||
false; $(); echo $?
|
false; $(); echo $?
|
||||||
|
# bash sets $? to 127:
|
||||||
true; $(""); echo $?
|
true; $(""); echo $?
|
||||||
|
# bash sets $? to 127:
|
||||||
false; $(""); echo $?
|
false; $(""); echo $?
|
||||||
true; $( ); echo $?
|
true; $( ); echo $?
|
||||||
false; $( ); echo $?
|
false; $( ); echo $?
|
||||||
|
|
||||||
true; exec ''; echo $?
|
exec ''; echo $?
|
||||||
false; exec ''; echo $?
|
echo Not reached
|
||||||
|
Loading…
x
Reference in New Issue
Block a user