aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-26 00:07:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-26 00:07:27 +0200
commit2093ad296f8a4528ad0e106b52074871a2bf070e (patch)
treed94c965340ab56f3394b4c3fba675df29ed43f80
parent1e3e2ccd5dd280371c9ca29c0e0304a0d40592af (diff)
downloadbusybox-w32-2093ad296f8a4528ad0e106b52074871a2bf070e.tar.gz
busybox-w32-2093ad296f8a4528ad0e106b52074871a2bf070e.tar.bz2
busybox-w32-2093ad296f8a4528ad0e106b52074871a2bf070e.zip
hush: fix ${##}, ${#?}, ${#!} handling
function old new delta parse_dollar 786 820 +34 expand_one_var 1579 1592 +13 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 47/0) Total: 47 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rwxr-xr-xshell/ash_test/ash-vars/param_expand_alt.tests2
-rw-r--r--shell/ash_test/ash-vars/param_expand_len1.right11
-rwxr-xr-xshell/ash_test/ash-vars/param_expand_len1.tests31
-rw-r--r--shell/hush.c27
-rwxr-xr-xshell/hush_test/hush-vars/param_expand_alt.tests2
-rw-r--r--shell/hush_test/hush-vars/param_expand_len1.right11
-rwxr-xr-xshell/hush_test/hush-vars/param_expand_len1.tests31
7 files changed, 106 insertions, 9 deletions
diff --git a/shell/ash_test/ash-vars/param_expand_alt.tests b/shell/ash_test/ash-vars/param_expand_alt.tests
index c9c4249af..d80452434 100755
--- a/shell/ash_test/ash-vars/param_expand_alt.tests
+++ b/shell/ash_test/ash-vars/param_expand_alt.tests
@@ -6,7 +6,7 @@
6# now some funky ones. 6# now some funky ones.
7# ${V+word} "if V unset, then substitute nothing, else substitute word" 7# ${V+word} "if V unset, then substitute nothing, else substitute word"
8# ${V:+word} "if V unset or '', then substitute nothing, else substitute word" 8# ${V:+word} "if V unset or '', then substitute nothing, else substitute word"
9# bash doesn't accept ${#+}. ash prints 0 (not $#). 9# bash doesn't accept ${#+}. ash prints 0 (not $#): "len of $+"
10echo _${#+}_ _${#:+}_ 10echo _${#+}_ _${#:+}_
11# Forms with non-empty word work as expected in both ash and bash. 11# Forms with non-empty word work as expected in both ash and bash.
12echo _${#+z}_ _${#:+z}_ 12echo _${#+z}_ _${#:+z}_
diff --git a/shell/ash_test/ash-vars/param_expand_len1.right b/shell/ash_test/ash-vars/param_expand_len1.right
new file mode 100644
index 000000000..dff3c7bb1
--- /dev/null
+++ b/shell/ash_test/ash-vars/param_expand_len1.right
@@ -0,0 +1,11 @@
1One:1
2Two:2
3Three:3
4
5One:1
6Two:2
7Three:3
8
9Ok ${#$}: 0
10
11Ok ${#!}: 0
diff --git a/shell/ash_test/ash-vars/param_expand_len1.tests b/shell/ash_test/ash-vars/param_expand_len1.tests
new file mode 100755
index 000000000..e1beab320
--- /dev/null
+++ b/shell/ash_test/ash-vars/param_expand_len1.tests
@@ -0,0 +1,31 @@
1# ${#c} for any single char c means "length of $c", including all special vars
2
3false
4echo One:${#?}
5(exit 10)
6echo Two:${#?}
7(exit 100)
8echo Three:${#?}
9
10echo
11echo One:${##}
12set -- 1 2 3 4 5 6 7 8 9 0
13echo Two:${##}
14set -- 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 \
15 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 \
16 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 \
17 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
18echo Three:${##}
19
20echo
21v=$$
22test "${#v}" = "${#$}"
23echo 'Ok ${#$}:' $?
24
25echo
26sleep 0 &
27v=$!
28test "${#v}" = "${#!}"
29echo 'Ok ${#!}:' $?
30
31# TODO: ${#-} ${#_}
diff --git a/shell/hush.c b/shell/hush.c
index 11b33f40a..d0225edb9 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -4466,6 +4466,8 @@ static int parse_dollar(o_string *as_string,
4466 case '@': /* args */ 4466 case '@': /* args */
4467 goto make_one_char_var; 4467 goto make_one_char_var;
4468 case '{': { 4468 case '{': {
4469 char len_single_ch;
4470
4469 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4471 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4470 4472
4471 ch = i_getch(input); /* eat '{' */ 4473 ch = i_getch(input); /* eat '{' */
@@ -4485,6 +4487,7 @@ static int parse_dollar(o_string *as_string,
4485 return 0; 4487 return 0;
4486 } 4488 }
4487 nommu_addchr(as_string, ch); 4489 nommu_addchr(as_string, ch);
4490 len_single_ch = ch;
4488 ch |= quote_mask; 4491 ch |= quote_mask;
4489 4492
4490 /* It's possible to just call add_till_closing_bracket() at this point. 4493 /* It's possible to just call add_till_closing_bracket() at this point.
@@ -4509,9 +4512,18 @@ static int parse_dollar(o_string *as_string,
4509 /* handle parameter expansions 4512 /* handle parameter expansions
4510 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 4513 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
4511 */ 4514 */
4512 if (!strchr(VAR_SUBST_OPS, ch)) /* ${var<bad_char>... */ 4515 if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
4513 goto bad_dollar_syntax; 4516 if (len_single_ch != '#'
4514 4517 /*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
4518 || i_peek(input) != '}'
4519 ) {
4520 goto bad_dollar_syntax;
4521 }
4522 /* else: it's "length of C" ${#C} op,
4523 * where C is a single char
4524 * special var name, e.g. ${#!}.
4525 */
4526 }
4515 /* Eat everything until closing '}' (or ':') */ 4527 /* Eat everything until closing '}' (or ':') */
4516 end_ch = '}'; 4528 end_ch = '}';
4517 if (BASH_SUBSTR 4529 if (BASH_SUBSTR
@@ -4568,6 +4580,7 @@ static int parse_dollar(o_string *as_string,
4568 } 4580 }
4569 break; 4581 break;
4570 } 4582 }
4583 len_single_ch = 0; /* it can't be ${#C} op */
4571 } 4584 }
4572 o_addchr(dest, SPECIAL_VAR_SYMBOL); 4585 o_addchr(dest, SPECIAL_VAR_SYMBOL);
4573 break; 4586 break;
@@ -5559,10 +5572,10 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5559 first_char = arg[0] = arg0 & 0x7f; 5572 first_char = arg[0] = arg0 & 0x7f;
5560 exp_op = 0; 5573 exp_op = 0;
5561 5574
5562 if (first_char == '#' && arg[1] /* ${#... but not ${#} */ 5575 if (first_char == '#' && arg[1] /* ${#...} but not ${#} */
5563 && (!exp_saveptr /* and (not ${#<op_char>...} */ 5576 && (!exp_saveptr /* and ( not(${#<op_char>...}) */
5564 || (arg[1] == '?' && arg[2] == '\0') /* or ${#?} - "len of $?") */ 5577 || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
5565 ) 5578 ) /* NB: skipping ^^^specvar check mishandles ${#::2} */
5566 ) { 5579 ) {
5567 /* It must be length operator: ${#var} */ 5580 /* It must be length operator: ${#var} */
5568 var++; 5581 var++;
diff --git a/shell/hush_test/hush-vars/param_expand_alt.tests b/shell/hush_test/hush-vars/param_expand_alt.tests
index c9c4249af..d80452434 100755
--- a/shell/hush_test/hush-vars/param_expand_alt.tests
+++ b/shell/hush_test/hush-vars/param_expand_alt.tests
@@ -6,7 +6,7 @@
6# now some funky ones. 6# now some funky ones.
7# ${V+word} "if V unset, then substitute nothing, else substitute word" 7# ${V+word} "if V unset, then substitute nothing, else substitute word"
8# ${V:+word} "if V unset or '', then substitute nothing, else substitute word" 8# ${V:+word} "if V unset or '', then substitute nothing, else substitute word"
9# bash doesn't accept ${#+}. ash prints 0 (not $#). 9# bash doesn't accept ${#+}. ash prints 0 (not $#): "len of $+"
10echo _${#+}_ _${#:+}_ 10echo _${#+}_ _${#:+}_
11# Forms with non-empty word work as expected in both ash and bash. 11# Forms with non-empty word work as expected in both ash and bash.
12echo _${#+z}_ _${#:+z}_ 12echo _${#+z}_ _${#:+z}_
diff --git a/shell/hush_test/hush-vars/param_expand_len1.right b/shell/hush_test/hush-vars/param_expand_len1.right
new file mode 100644
index 000000000..dff3c7bb1
--- /dev/null
+++ b/shell/hush_test/hush-vars/param_expand_len1.right
@@ -0,0 +1,11 @@
1One:1
2Two:2
3Three:3
4
5One:1
6Two:2
7Three:3
8
9Ok ${#$}: 0
10
11Ok ${#!}: 0
diff --git a/shell/hush_test/hush-vars/param_expand_len1.tests b/shell/hush_test/hush-vars/param_expand_len1.tests
new file mode 100755
index 000000000..e1beab320
--- /dev/null
+++ b/shell/hush_test/hush-vars/param_expand_len1.tests
@@ -0,0 +1,31 @@
1# ${#c} for any single char c means "length of $c", including all special vars
2
3false
4echo One:${#?}
5(exit 10)
6echo Two:${#?}
7(exit 100)
8echo Three:${#?}
9
10echo
11echo One:${##}
12set -- 1 2 3 4 5 6 7 8 9 0
13echo Two:${##}
14set -- 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 \
15 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 \
16 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 \
17 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
18echo Three:${##}
19
20echo
21v=$$
22test "${#v}" = "${#$}"
23echo 'Ok ${#$}:' $?
24
25echo
26sleep 0 &
27v=$!
28test "${#v}" = "${#!}"
29echo 'Ok ${#!}:' $?
30
31# TODO: ${#-} ${#_}