From acd5bc8f649fad335d80c5289512b404f08ac8e2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 12 Sep 2010 15:05:39 +0200 Subject: [PATCH] hush: fix handling of \" in quoted/unquoted `cmd` Signed-off-by: Denys Vlasenko --- shell/hush.c | 48 +++++++++++-------- .../hush-misc/heredoc_backslash1.right | 8 ++++ .../hush-misc/heredoc_backslash1.tests | 8 ++++ shell/hush_test/hush-psubst/tick3.right | 2 +- shell/hush_test/hush-psubst/tick3.tests | 6 ++- 5 files changed, 50 insertions(+), 22 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 76737a234..b01f90370 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -234,6 +234,10 @@ //usage:#define hush_full_usage "" //usage:#define msh_trivial_usage NOUSAGE_STR //usage:#define msh_full_usage "" +//usage:#define sh_trivial_usage NOUSAGE_STR +//usage:#define sh_full_usage "" +//usage:#define bash_trivial_usage NOUSAGE_STR +//usage:#define bash_full_usage "" /* Build knobs */ @@ -1367,9 +1371,15 @@ static void hush_exit(int exitcode) #endif } + static int check_and_run_traps(int sig) { - static const struct timespec zero_timespec; + /* I want it in rodata, not in bss. + * gcc 4.2.1 puts it in rodata only if it has { 0, 0 } + * initializer. But other compilers may still use bss. + * TODO: find more portable solution. + */ + static const struct timespec zero_timespec = { 0, 0 }; smalluint save_rcode; int last_sig = 0; @@ -3367,7 +3377,7 @@ static int parse_group(o_string *dest, struct parse_context *ctx, #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS /* Subroutines for copying $(...) and `...` things */ -static void add_till_backquote(o_string *dest, struct in_str *input); +static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); /* '...' */ static void add_till_single_quote(o_string *dest, struct in_str *input) { @@ -3399,7 +3409,7 @@ static void add_till_double_quote(o_string *dest, struct in_str *input) } o_addchr(dest, ch); if (ch == '`') { - add_till_backquote(dest, input); + add_till_backquote(dest, input, /*in_dquote:*/ 1); o_addchr(dest, ch); continue; } @@ -3420,26 +3430,26 @@ static void add_till_double_quote(o_string *dest, struct in_str *input) * Example Output * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST */ -static void add_till_backquote(o_string *dest, struct in_str *input) +static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote) { while (1) { int ch = i_getch(input); - if (ch == EOF) { - syntax_error_unterm_ch('`'); - /*xfunc_die(); - redundant */ - } if (ch == '`') return; if (ch == '\\') { - /* \x. Copy both chars unless it is \` */ - int ch2 = i_getch(input); - if (ch2 == EOF) { - syntax_error_unterm_ch('`'); - /*xfunc_die(); - redundant */ + /* \x. Copy both unless it is \`, \$, \\ and maybe \" */ + ch = i_getch(input); + if (ch != '`' + && ch != '$' + && ch != '\\' + && (!in_dquote || ch != '"') + ) { + o_addchr(dest, '\\'); } - if (ch2 != '`' && ch2 != '$' && ch2 != '\\') - o_addchr(dest, ch); - ch = ch2; + } + if (ch == EOF) { + syntax_error_unterm_ch('`'); + /*xfunc_die(); - redundant */ } o_addchr(dest, ch); } @@ -3504,7 +3514,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign continue; } if (ch == '`') { - add_till_backquote(dest, input); + add_till_backquote(dest, input, /*in_dquote:*/ 0); o_addchr(dest, ch); continue; } @@ -3818,7 +3828,7 @@ static int encode_string(o_string *as_string, //unsigned pos = dest->length; o_addchr(dest, SPECIAL_VAR_SYMBOL); o_addchr(dest, 0x80 | '`'); - add_till_backquote(dest, input); + add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'); o_addchr(dest, SPECIAL_VAR_SYMBOL); //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); goto again; @@ -4191,7 +4201,7 @@ static struct pipe *parse_stream(char **pstring, o_addchr(&dest, SPECIAL_VAR_SYMBOL); o_addchr(&dest, '`'); pos = dest.length; - add_till_backquote(&dest, input); + add_till_backquote(&dest, input, /*in_dquote:*/ 0); # if !BB_MMU o_addstr(&ctx.as_string, dest.data + pos); o_addchr(&ctx.as_string, '`'); diff --git a/shell/hush_test/hush-misc/heredoc_backslash1.right b/shell/hush_test/hush-misc/heredoc_backslash1.right index 2633908fb..6a6114821 100644 --- a/shell/hush_test/hush-misc/heredoc_backslash1.right +++ b/shell/hush_test/hush-misc/heredoc_backslash1.right @@ -5,6 +5,8 @@ a\\ b 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- + 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` + 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') c\ Unquoted heredoc: @@ -13,6 +15,8 @@ a\ b 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- + 123456 v-$a-\t-\-\"-\x-`-\--\z-\*-\?- + 123456 v-$a-\t-\\-\"-\x-\`-\--\z-\*-\?- cEOF2 Quoted -heredoc: @@ -22,6 +26,8 @@ a\\ b 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- + 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` + 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') c\ Unquoted -heredoc: @@ -30,6 +36,8 @@ a\ b 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- -qwerty-\t-\-\"-\'-`-\--\z-\*-\?- + 123456 v-$a-\t-\-\"-\x-`-\--\z-\*-\?- + 123456 v-$a-\t-\\-\"-\x-\`-\--\z-\*-\?- cEOF4 Done: 0 diff --git a/shell/hush_test/hush-misc/heredoc_backslash1.tests b/shell/hush_test/hush-misc/heredoc_backslash1.tests index 22045d42e..501af5490 100755 --- a/shell/hush_test/hush-misc/heredoc_backslash1.tests +++ b/shell/hush_test/hush-misc/heredoc_backslash1.tests @@ -11,6 +11,8 @@ a\\ b 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- + 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` + 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') c\ EOF1 echo @@ -23,6 +25,8 @@ a\\ b 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- + 123456 `echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'` + 123456 $(echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-') c\ EOF2 EOF2 @@ -36,6 +40,8 @@ a\\ b 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- + 123456 `echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'` + 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-') c\ EOF3 # In -heredoc case the marker is detected even if it is indented. @@ -49,6 +55,8 @@ a\\ b 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- -$a-\t-\\-\"-\'-\`-\--\z-\*-\?- + 123456 `echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'` + 123456 $(echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-') c\ EOF4 EOF4 diff --git a/shell/hush_test/hush-psubst/tick3.right b/shell/hush_test/hush-psubst/tick3.right index dc84e9263..00f267ae5 100644 --- a/shell/hush_test/hush-psubst/tick3.right +++ b/shell/hush_test/hush-psubst/tick3.right @@ -2,5 +2,5 @@ $TEST Q a\bc -a"c +11-$a-\t-\-\"-`-\--\z-\*-\?-22 33-$a-\t-\-"-`-\--\z-\*-\?-44 done:0 diff --git a/shell/hush_test/hush-psubst/tick3.tests b/shell/hush_test/hush-psubst/tick3.tests index 469c43c27..3aeb241c3 100755 --- a/shell/hush_test/hush-psubst/tick3.tests +++ b/shell/hush_test/hush-psubst/tick3.tests @@ -7,6 +7,8 @@ echo `echo '\'TEST\`echo ZZ\`BEST` echo `echo \\$TEST` echo `echo \$TEST` echo a`echo \\\\b`c -# \" etc are NOT special (passed verbatim WITH \)! -echo a`echo \"`c + +# \" is not special if in unquoted `cmd` (passed verbatim WITH \), +# but is special in quoted one +echo `echo 11'-$a-\t-\\-\"-\`-\--\z-\*-\?-'22` "`echo 33'-$a-\t-\\-\"-\`-\--\z-\*-\?-'44`" echo done:$?