From: Denis Vlasenko Date: Wed, 16 May 2007 10:39:24 +0000 (-0000) Subject: hush: fix expansion of quoted $VAR, $* and $@ X-Git-Tag: 1_6_0~62 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=1f4cf517f5803b0e300906c487d365a331122091;p=oweals%2Fbusybox.git hush: fix expansion of quoted $VAR, $* and $@ --- diff --git a/shell/hush.c b/shell/hush.c index e49c0c989..e3dd6663e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2425,6 +2425,7 @@ static int expand_on_ifs(char **list, int n, char **posp, const char *str) static int expand_vars_to_list(char **list, int n, char **posp, char *arg) { char first_ch, ored_ch; + int i; const char *val; char *p; char *pos = *posp; @@ -2462,8 +2463,8 @@ static int expand_vars_to_list(char **list, int n, char **posp, char *arg) break; case '*': case '@': + i = 1; if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ - int i = 1; while (i < global_argc) { n = expand_on_ifs(list, n, &pos, global_argv[i]); debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, global_argc-1); @@ -2478,16 +2479,33 @@ static int expand_vars_to_list(char **list, int n, char **posp, char *arg) } } } else if (first_ch == ('@'|0x80)) { /* quoted $@ */ - /* TODO */ - } else { /* quoted $* */ - /* TODO */ + while (1) { + strcpy(pos, global_argv[i]); + pos += strlen(global_argv[i]); + if (++i >= global_argc) + break; + *pos++ = '\0'; + if (n) debug_printf_expand("expand_vars_to_list 3 finalized list[%d]=%p '%s' " + "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1], + strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos); + list[n++] = pos; + } + } else { /* quoted $*: add as one word */ + while (1) { + strcpy(pos, global_argv[i]); + pos += strlen(global_argv[i]); + if (++i >= global_argc) + break; + if (ifs[0]) + *pos++ = ifs[0]; + } } break; default: *p = '\0'; arg[0] = first_ch & 0x7f; if (isdigit(arg[0])) { - int i = xatoi_u(arg); + i = xatoi_u(arg); val = NULL; if (i < global_argc) val = global_argv[i]; @@ -2495,12 +2513,12 @@ static int expand_vars_to_list(char **list, int n, char **posp, char *arg) val = lookup_param(arg); arg[0] = first_ch; *p = SPECIAL_VAR_SYMBOL; - if (!(first_ch & 0x80)) { /* unquoted var */ + if (!(first_ch & 0x80)) { /* unquoted $VAR */ if (val) { n = expand_on_ifs(list, n, &pos, val); val = NULL; } - } + } /* else: quoted $VAR, val will be appended at pos */ } if (val) { strcpy(pos, val); @@ -3268,18 +3286,18 @@ static char* make_string(char **inp) /* return code: 0 for OK, 1 for syntax error */ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input) { -// int i; -// char sep[] = " "; int ch = b_peek(input); /* first character after the $ */ + unsigned char quote_mask = dest->quote ? 0x80 : 0; debug_printf_parse("handle_dollar entered: ch='%c'\n", ch); - if (isalpha(ch) || ch == '?') { + if (isalpha(ch)) { b_addchr(dest, SPECIAL_VAR_SYMBOL); ctx->child->sp++; while (1) { debug_printf_parse(": '%c'\n", ch); b_getch(input); - b_addchr(dest, ch); + b_addchr(dest, ch | quote_mask); + quote_mask = 0; ch = b_peek(input); if (!isalnum(ch) && ch != '_') break; @@ -3291,7 +3309,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i ctx->child->sp++; debug_printf_parse(": '%c'\n", ch); b_getch(input); - b_addchr(dest, ch); + b_addchr(dest, ch | quote_mask); b_addchr(dest, SPECIAL_VAR_SYMBOL); } else switch (ch) { case '$': /* pid */ @@ -3316,7 +3334,8 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i if (ch == '}') break; debug_printf_parse(": '%c'\n", ch); - b_addchr(dest, ch); + b_addchr(dest, ch | quote_mask); + quote_mask = 0; } b_addchr(dest, SPECIAL_VAR_SYMBOL); break; diff --git a/shell/hush_test/hush-bugs/quote3.right b/shell/hush_test/hush-bugs/quote3.right index 11443f54b..069a46e8f 100644 --- a/shell/hush_test/hush-bugs/quote3.right +++ b/shell/hush_test/hush-bugs/quote3.right @@ -1,8 +1,3 @@ Testing: in $empty"" .. -Testing: in "$*" -.abc d e. -Testing: in "$@" -.abc. -.d e. Finished diff --git a/shell/hush_test/hush-bugs/quote3.tests b/shell/hush_test/hush-bugs/quote3.tests index c52e040cc..075e78570 100755 --- a/shell/hush_test/hush-bugs/quote3.tests +++ b/shell/hush_test/hush-bugs/quote3.tests @@ -5,8 +5,4 @@ fi echo 'Testing: in $empty""' empty='' for a in $empty""; do echo ".$a."; done -echo 'Testing: in "$*"' -for a in "$*"; do echo ".$a."; done -echo 'Testing: in "$@"' -for a in "$@"; do echo ".$a."; done echo Finished diff --git a/shell/hush_test/hush-bugs/starquoted.right b/shell/hush_test/hush-bugs/starquoted.right deleted file mode 100644 index fedaf4805..000000000 --- a/shell/hush_test/hush-bugs/starquoted.right +++ /dev/null @@ -1 +0,0 @@ -.1 abc d e f. diff --git a/shell/hush_test/hush-bugs/starquoted.tests b/shell/hush_test/hush-bugs/starquoted.tests deleted file mode 100755 index 3be2026b7..000000000 --- a/shell/hush_test/hush-bugs/starquoted.tests +++ /dev/null @@ -1,4 +0,0 @@ -if test $# = 0; then - exec "$THIS_SH" starquoted.tests 1 abc 'd e f' -fi -for a in "$*"; do echo ".$a."; done diff --git a/shell/hush_test/hush-parsing/quote4.right b/shell/hush_test/hush-parsing/quote4.right new file mode 100644 index 000000000..b2901ea97 --- /dev/null +++ b/shell/hush_test/hush-parsing/quote4.right @@ -0,0 +1 @@ +a b diff --git a/shell/hush_test/hush-parsing/quote4.tests b/shell/hush_test/hush-parsing/quote4.tests new file mode 100755 index 000000000..f1dabfa54 --- /dev/null +++ b/shell/hush_test/hush-parsing/quote4.tests @@ -0,0 +1,2 @@ +a_b='a b' +echo "$a_b" diff --git a/shell/hush_test/hush-parsing/starquoted.right b/shell/hush_test/hush-parsing/starquoted.right new file mode 100644 index 000000000..b56323fe1 --- /dev/null +++ b/shell/hush_test/hush-parsing/starquoted.right @@ -0,0 +1,8 @@ +.1 abc d e f. +.1. +.abc. +.d e f. +.-1 abc d e f-. +.-1. +.abc. +.d e f-. diff --git a/shell/hush_test/hush-parsing/starquoted.tests b/shell/hush_test/hush-parsing/starquoted.tests new file mode 100755 index 000000000..2fe49b1cd --- /dev/null +++ b/shell/hush_test/hush-parsing/starquoted.tests @@ -0,0 +1,8 @@ +if test $# = 0; then + exec "$THIS_SH" "$0" 1 abc 'd e f' +fi + +for a in "$*"; do echo ".$a."; done +for a in "$@"; do echo ".$a."; done +for a in "-$*-"; do echo ".$a."; done +for a in "-$@-"; do echo ".$a."; done