aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-08-01 14:06:20 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-08-01 14:06:20 +0200
commit4fb53fb08ce3da8eac13438ce613df20e523c75d (patch)
treef54399ad4ae2015d87fee1a064354220f16a4f7e
parent954dbd3a004dcb8df7e1e7283c4e249e02a300a4 (diff)
downloadbusybox-w32-4fb53fb08ce3da8eac13438ce613df20e523c75d.tar.gz
busybox-w32-4fb53fb08ce3da8eac13438ce613df20e523c75d.tar.bz2
busybox-w32-4fb53fb08ce3da8eac13438ce613df20e523c75d.zip
hush: partially fix wrong expansion on $IFS (bug 4027).
In the added testcase, before patch we failed 8 out of 9 tests, now we fail only 2 (4th and 5th). function old new delta expand_on_ifs 225 258 +33 expand_vars_to_list 1038 1054 +16 o_save_ptr_helper 115 119 +4 builtin_umask 132 133 +1 o_addQstr 165 161 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 54/-4) Total: 50 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c39
-rw-r--r--shell/hush_test/hush-vars/var_expand_on_ifs.right9
-rwxr-xr-xshell/hush_test/hush-vars/var_expand_on_ifs.tests11
3 files changed, 50 insertions, 9 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 1082738a2..503cb770b 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2281,7 +2281,7 @@ static void o_addqblock(o_string *o, const char *str, int len)
2281 ordinary_cnt = len; 2281 ordinary_cnt = len;
2282 o_addblock(o, str, ordinary_cnt); 2282 o_addblock(o, str, ordinary_cnt);
2283 if (ordinary_cnt == len) 2283 if (ordinary_cnt == len)
2284 return; 2284 return; /* NUL is already added by o_addblock */
2285 str += ordinary_cnt; 2285 str += ordinary_cnt;
2286 len -= ordinary_cnt + 1; /* we are processing + 1 char below */ 2286 len -= ordinary_cnt + 1; /* we are processing + 1 char below */
2287 2287
@@ -2295,8 +2295,8 @@ static void o_addqblock(o_string *o, const char *str, int len)
2295 o_grow_by(o, sz); 2295 o_grow_by(o, sz);
2296 o->data[o->length] = ch; 2296 o->data[o->length] = ch;
2297 o->length++; 2297 o->length++;
2298 o->data[o->length] = '\0';
2299 } 2298 }
2299 o->data[o->length] = '\0';
2300} 2300}
2301 2301
2302static void o_addQblock(o_string *o, const char *str, int len) 2302static void o_addQblock(o_string *o, const char *str, int len)
@@ -2385,6 +2385,7 @@ static int o_save_ptr_helper(o_string *o, int n)
2385 n, string_len, string_start); 2385 n, string_len, string_start);
2386 o->has_empty_slot = 0; 2386 o->has_empty_slot = 0;
2387 } 2387 }
2388 o->has_quoted_part = 0;
2388 list[n] = (char*)(uintptr_t)string_len; 2389 list[n] = (char*)(uintptr_t)string_len;
2389 return n + 1; 2390 return n + 1;
2390} 2391}
@@ -4754,8 +4755,13 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len
4754static int expand_on_ifs(o_string *output, int n, const char *str) 4755static int expand_on_ifs(o_string *output, int n, const char *str)
4755{ 4756{
4756 while (1) { 4757 while (1) {
4757 int word_len = strcspn(str, G.ifs); 4758 int word_len;
4759
4760 if (!*str) /* EOL - do not finalize word */
4761 break;
4762 word_len = strcspn(str, G.ifs);
4758 if (word_len) { 4763 if (word_len) {
4764 /* We have WORD_LEN leading non-IFS chars */
4759 if (!(output->o_expflags & EXP_FLAG_GLOB)) { 4765 if (!(output->o_expflags & EXP_FLAG_GLOB)) {
4760 o_addblock(output, str, word_len); 4766 o_addblock(output, str, word_len);
4761 } else { 4767 } else {
@@ -4769,13 +4775,25 @@ static int expand_on_ifs(o_string *output, int n, const char *str)
4769 /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */ 4775 /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
4770 } 4776 }
4771 str += word_len; 4777 str += word_len;
4778 if (!*str) /* EOL - do not finalize word */
4779 break;
4780 goto finalize; /* optimization (can just fall thru) */
4781 }
4782 /* Case "v=' a'; echo ''$v": we do need to finalize empty word */
4783 if (output->has_quoted_part
4784 /* Case "v=' a'; echo $v":
4785 * here nothing precedes the space in $v expansion,
4786 * therefore we should not finish the word
4787 * (IOW: if there *is* word to finalize, only then do it)
4788 */
4789 || (output->length && output->data[output->length - 1])
4790 ) {
4791 finalize:
4792 o_addchr(output, '\0');
4793 debug_print_list("expand_on_ifs", output, n);
4794 n = o_save_ptr(output, n);
4772 } 4795 }
4773 if (!*str) /* EOL - do not finalize word */ 4796 str += strspn(str, G.ifs); /* skip IFS chars */
4774 break;
4775 o_addchr(output, '\0');
4776 debug_print_list("expand_on_ifs", output, n);
4777 n = o_save_ptr(output, n);
4778 str += strspn(str, G.ifs); /* skip ifs chars */
4779 } 4797 }
4780 debug_print_list("expand_on_ifs[1]", output, n); 4798 debug_print_list("expand_on_ifs[1]", output, n);
4781 return n; 4799 return n;
@@ -5270,11 +5288,13 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
5270 if (G.ifs[0]) 5288 if (G.ifs[0])
5271 o_addchr(output, G.ifs[0]); 5289 o_addchr(output, G.ifs[0]);
5272 } 5290 }
5291 output->has_quoted_part = 1;
5273 } 5292 }
5274 break; 5293 break;
5275 } 5294 }
5276 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */ 5295 case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
5277 /* "Empty variable", used to make "" etc to not disappear */ 5296 /* "Empty variable", used to make "" etc to not disappear */
5297 output->has_quoted_part = 1;
5278 arg++; 5298 arg++;
5279 cant_be_null = 0x80; 5299 cant_be_null = 0x80;
5280 break; 5300 break;
@@ -5316,6 +5336,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
5316 val = NULL; 5336 val = NULL;
5317 } 5337 }
5318 } else { /* quoted $VAR, val will be appended below */ 5338 } else { /* quoted $VAR, val will be appended below */
5339 output->has_quoted_part = 1;
5319 debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, 5340 debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
5320 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); 5341 !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5321 } 5342 }
diff --git a/shell/hush_test/hush-vars/var_expand_on_ifs.right b/shell/hush_test/hush-vars/var_expand_on_ifs.right
new file mode 100644
index 000000000..2ed2069f7
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_expand_on_ifs.right
@@ -0,0 +1,9 @@
11 a b c
22 a + b c
33 a b c
44 a b c
55 a b c
66 a b + c
77 a b c
88 a b c
99 a b c
diff --git a/shell/hush_test/hush-vars/var_expand_on_ifs.tests b/shell/hush_test/hush-vars/var_expand_on_ifs.tests
new file mode 100755
index 000000000..a12ff8ec8
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_expand_on_ifs.tests
@@ -0,0 +1,11 @@
1b=' b '
2e=''
3echo 1 a $b c
4echo 2 a +$b c
5echo 3 a $e$b c
6echo 4 a "$e"$b c
7echo 5 a ""$b c
8echo 6 a $b+ c
9echo 7 a $b$e c
10echo 8 a $b"$e" c
11echo 9 a $b"" c