hush: fix handling of \" in quoted/unquoted `cmd`
authorDenys Vlasenko <dvlasenk@redhat.com>
Sun, 12 Sep 2010 13:05:39 +0000 (15:05 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Sun, 12 Sep 2010 13:05:39 +0000 (15:05 +0200)
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
shell/hush.c
shell/hush_test/hush-misc/heredoc_backslash1.right
shell/hush_test/hush-misc/heredoc_backslash1.tests
shell/hush_test/hush-psubst/tick3.right
shell/hush_test/hush-psubst/tick3.tests

index 76737a2..b01f903 100644 (file)
 //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, '`');
index 2633908..6a61148 100644 (file)
@@ -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
index 22045d4..501af54 100755 (executable)
@@ -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
index dc84e92..00f267a 100644 (file)
@@ -2,5 +2,5 @@
 $TEST
 Q
 a\bc
-a"c
+11-$a-\t-\-\"-`-\--\z-\*-\?-22 33-$a-\t-\-"-`-\--\z-\*-\?-44
 done:0
index 469c43c..3aeb241 100755 (executable)
@@ -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:$?