From: Denis Vlasenko Date: Fri, 10 Apr 2009 12:03:20 +0000 (-0000) Subject: hush: tighten up "for" variable name check. X-Git-Tag: 1_14_0~39 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=1fd1ea4395e520694bd9f8b1dc9e60af6442946d;p=oweals%2Fbusybox.git hush: tighten up "for" variable name check. Add TODOs. Disable redir4.right part where we differ from bash. It is not a bug per standards. Add a few tests, one is in hush-bugs section: and_or_and_backgrounding.right. It will likely bite users in real world usage. --- diff --git a/shell/hush.c b/shell/hush.c index bb4fdc295..422fc63f6 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -344,8 +344,7 @@ typedef enum redir_type { REDIRFD_CLOSE = -3, REDIRFD_SYNTAX_ERR = -2, - REDIRFD_TO_FILE = -1, - /* otherwise, rd_fd is redirected to rd_dup */ + REDIRFD_TO_FILE = -1, /* otherwise, rd_fd if redirected to rd_dup */ HEREDOC_SKIPTABS = 1, HEREDOC_QUOTED = 2, @@ -3999,6 +3998,7 @@ static int done_word(o_string *word, struct parse_context *ctx) ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED; } debug_printf_parse("word stored in rd_filename: '%s'\n", word->data); + ctx->pending_redirect = NULL; } else { /* If this word wasn't an assignment, next ones definitely * can't be assignments. Even if they look like ones. */ @@ -4076,19 +4076,19 @@ static int done_word(o_string *word, struct parse_context *ctx) debug_print_strings("word appended to argv", command->argv); } - o_reset(word); - ctx->pending_redirect = NULL; - #if ENABLE_HUSH_LOOPS - /* Force FOR to have just one word (variable name) */ - /* NB: basically, this makes hush see "for v in ..." syntax as if - * as it is "for v; in ...". FOR and IN become two pipe structs - * in parse tree. */ if (ctx->ctx_res_w == RES_FOR) { - if (!is_well_formed_var_name(command->argv[0], '\0')) { - syntax_error("malformed variable name in for"); + if (word->o_quoted + || !is_well_formed_var_name(command->argv[0], '\0') + ) { + /* bash says "not a valid identifier" */ + syntax_error("not a valid identifier in for"); return 1; } + /* Force FOR to have just one word (variable name) */ + /* NB: basically, this makes hush see "for v in ..." + * syntax as if it is "for v; in ...". FOR and IN become + * two pipe structs in parse tree. */ done_pipe(ctx, PIPE_SEQ); } #endif @@ -4098,6 +4098,9 @@ static int done_word(o_string *word, struct parse_context *ctx) done_pipe(ctx, PIPE_SEQ); } #endif + + o_reset(word); + debug_printf_parse("done_word return 0\n"); return 0; } @@ -6197,6 +6200,8 @@ static int builtin_read(char **argv) if (argv[1]) { name = argv[1]; + /* bash (3.2.33(1)) bug: "read 0abcd" will execute, + * and _after_ that_ it will complain */ if (!is_well_formed_var_name(name, '\0')) { /* Mimic bash message */ bb_error_msg("read: '%s': not a valid identifier", name); @@ -6204,6 +6209,8 @@ static int builtin_read(char **argv) } } +//TODO: bash unbackslashes input, splits words and puts them in argv[i] + string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name), NULL); return set_local_var(string, 0, 0); } diff --git a/shell/hush_test/hush-bugs/and_or_and_backgrounding.right b/shell/hush_test/hush-bugs/and_or_and_backgrounding.right new file mode 100644 index 000000000..90ce63e01 --- /dev/null +++ b/shell/hush_test/hush-bugs/and_or_and_backgrounding.right @@ -0,0 +1,4 @@ +First +Second +Third +Done diff --git a/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests b/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests new file mode 100755 index 000000000..05acfb863 --- /dev/null +++ b/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests @@ -0,0 +1,31 @@ +# UNFIXED BUG: hush thinks that ; && || & have the same precedence. +# According to this doc, && || have higher precedence than ; &. +# See example below. +# Precedence of ; is not a problem in practice. Precedence of & is. +# +#http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html +# +#2.9.3 Lists +# +#An AND-OR list is a sequence of one or more pipelines separated by +#the operators "&&" and "||" . +# +#A list is a sequence of one or more AND-OR lists separated by the operators +#';' and '&' and optionally terminated by ';', '&', or . +# +#The operators "&&" and "||" shall have equal precedence and shall be +#evaluated with left associativity. For example, both of the following +#commands write solely bar to standard output: +# +# false && echo foo || echo bar +# true || echo foo && echo bar +# +#A ';' or terminator shall cause the preceding AND-OR list +#to be executed sequentially; an '&' shall cause asynchronous execution +#of the preceding AND-OR list. + +echo First && sleep 0.2 && echo Third & +sleep 0.1 +echo Second +wait +echo Done diff --git a/shell/hush_test/hush-misc/for_with_bslashes.right b/shell/hush_test/hush-misc/for_with_bslashes.right new file mode 100644 index 000000000..02d96692c --- /dev/null +++ b/shell/hush_test/hush-misc/for_with_bslashes.right @@ -0,0 +1,8 @@ +a +b\c +b\\c +b"c +b'c +b$c +b`true`c +Zero:0 diff --git a/shell/hush_test/hush-misc/for_with_bslashes.tests b/shell/hush_test/hush-misc/for_with_bslashes.tests new file mode 100755 index 000000000..363f3d85b --- /dev/null +++ b/shell/hush_test/hush-misc/for_with_bslashes.tests @@ -0,0 +1,10 @@ +# UNFIXED BUG. +# commented-out words contain ^C character. +# It's a SPECIAL_VAR_SYMBOL, for now hush does not escape it. +# When it is fixed, update this test. + +for a in 'a' 'b\c' 'b\\c' 'b"c' "b'c" 'b$c' 'b`true`c' ### 'b#c' +do + echo $a +done +echo Zero:$? diff --git a/shell/hush_test/hush-misc/redir1.tests b/shell/hush_test/hush-misc/redir1.tests index 70e9e17f0..ef2fbfb77 100755 --- a/shell/hush_test/hush-misc/redir1.tests +++ b/shell/hush_test/hush-misc/redir1.tests @@ -27,7 +27,7 @@ var=ok { var=bad >shell_test_$$; } & # cant use usleep as it isnt standard in $PATH -- # we fail when testing busybox compiled solely as "hush" -sleep 1 +wait echo "Test 4: var:$var" test -f shell_test_$$ && echo "File created:ok" diff --git a/shell/hush_test/hush-misc/redir4.right b/shell/hush_test/hush-misc/redir4.right index ada6c2d85..ead25f603 100644 --- a/shell/hush_test/hush-misc/redir4.right +++ b/shell/hush_test/hush-misc/redir4.right @@ -10,16 +10,9 @@ Here3 Ok3 Here4 Ok4 -How with variable refs +Now with variable refs shell_test_1 \shell_test_1 \shell_test_1 \shell_test_1 -Here1 -Ok1 -Here2 -Ok2 -Here3 -Ok3 -Here4 -Ok4 +Done diff --git a/shell/hush_test/hush-misc/redir4.tests b/shell/hush_test/hush-misc/redir4.tests index ac2a44166..c50b8cedf 100755 --- a/shell/hush_test/hush-misc/redir4.tests +++ b/shell/hush_test/hush-misc/redir4.tests @@ -38,7 +38,7 @@ Here4 echo Ok4 -echo How with variable refs +echo Now with variable refs i=1 @@ -58,6 +58,11 @@ rm *shell_test* echo *shell_test* rm *shell_test* +echo Done;exit +# UNFIXED BUG. bash apparently will expand $i even in terminating delimiter. +# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html +# does not mandate this behavior. +# This is not likely to be used much in real-world. cat <<\shell_test_$i Here1 diff --git a/shell/hush_test/hush-vars/param_subshell.tests b/shell/hush_test/hush-vars/param_subshell.tests index 565a84589..27fdc5b9b 100755 --- a/shell/hush_test/hush-vars/param_subshell.tests +++ b/shell/hush_test/hush-vars/param_subshell.tests @@ -7,9 +7,9 @@ echo 1=$1 { echo 3=$3; } & # cant use usleep as it isnt standard in $PATH -- # we fail when testing busybox compiled solely as "hush" -sleep 1 +wait ( echo 4=$4 ) ( echo 5=$5 ) & -sleep 1 +wait true | echo 6=$6 | cat true | { echo 7=$7; } | cat