fix globbing in unquoted $* and $@
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 18 Jun 2008 17:49:58 +0000 (17:49 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 18 Jun 2008 17:49:58 +0000 (17:49 -0000)
shell/hush.c
shell/hush_test/hush-vars/param_glob.right [new file with mode: 0644]
shell/hush_test/hush-vars/param_glob.tests [new file with mode: 0755]

index b83265899b3bd8f2fc82e182bf81028186e833c7..4d7d14b1a969869861fc1f46c0dfcee91c868e01 100644 (file)
@@ -342,6 +342,8 @@ typedef struct {
        char *data;
        int length;
        int maxlen;
+       /* Misnomer! it's not "quoting", it's "protection against globbing"!
+        * (by prepending \ to *, ?, [ and to \ too) */
        smallint o_quote;
        smallint o_glob;
        smallint nonnull;
@@ -2398,8 +2400,10 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                        if (!global_argv[i])
                                break;
                        if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
+                               smallint sv = output->o_quote;
+                               /* unquoted var's contents should be globbed, so don't quote */
+                               output->o_quote = 0;
                                while (global_argv[i]) {
-//see expand_on_ifs below - same??
                                        n = expand_on_ifs(output, n, global_argv[i]);
                                        debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, global_argc-1);
                                        if (global_argv[i++][0] && global_argv[i]) {
@@ -2411,12 +2415,13 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                                                debug_print_list("expand_vars_to_list[3]", output, n);
                                        }
                                }
+                               output->o_quote = sv;
                        } else
                        /* If or_mask is nonzero, we handle assignment 'a=....$@.....'
                         * and in this case should treat it like '$*' - see 'else...' below */
                        if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */
                                while (1) {
-                                       o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q?
+                                       o_addQstr(output, global_argv[i], strlen(global_argv[i]));
                                        if (++i >= global_argc)
                                                break;
                                        o_addchr(output, '\0');
@@ -2425,7 +2430,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                                }
                        } else { /* quoted $*: add as one word */
                                while (1) {
-                                       o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q?
+                                       o_addQstr(output, global_argv[i], strlen(global_argv[i]));
                                        if (!global_argv[++i])
                                                break;
                                        if (ifs[0])
@@ -2482,7 +2487,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                        }
                }
                if (val) {
-                       o_addQstr(output, val, strlen(val)); ///maybe q?
+                       o_addQstr(output, val, strlen(val));
                }
 
 #if ENABLE_HUSH_TICK
@@ -2517,8 +2522,8 @@ static char **expand_variables(char **argv, int or_mask)
        o_string output = NULL_O_STRING;
 
        if (or_mask & 0x100) {
-               output.o_quote = 1;
-/* why? */
+               output.o_quote = 1; /* protect against globbing for "$var" */
+               /* (unquoted $var will temporarily switch it off) */
                output.o_glob = 1;
        }
 
diff --git a/shell/hush_test/hush-vars/param_glob.right b/shell/hush_test/hush-vars/param_glob.right
new file mode 100644 (file)
index 0000000..bdee8fe
--- /dev/null
@@ -0,0 +1,4 @@
+param_glob.tests
+param_glob.tests
+param_glob.t*
+param_glob.t*
diff --git a/shell/hush_test/hush-vars/param_glob.tests b/shell/hush_test/hush-vars/param_glob.tests
new file mode 100755 (executable)
index 0000000..801d58e
--- /dev/null
@@ -0,0 +1,10 @@
+if test $# = 0; then
+    #BUG in builtin_exec! will glob param!
+    #exec "$THIS_SH" "$0" 'param_glob.t*'
+    "$THIS_SH" "$0" 'param_glob.t*'
+    exit
+fi
+echo $*
+echo $@
+echo "$*"
+echo "$@"