aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-07-25 03:56:00 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-07-25 03:56:00 +0200
commitf8ddbe1ccce9eceaaac28b4b1aa71631fcc56db6 (patch)
tree0782f9ae0ab8bfb74ad8c3fca455f2dcd4de6b33
parent0fb0045aa9261be1dda49dfdfb95cbc585402a8b (diff)
downloadbusybox-w32-f8ddbe1ccce9eceaaac28b4b1aa71631fcc56db6.tar.gz
busybox-w32-f8ddbe1ccce9eceaaac28b4b1aa71631fcc56db6.tar.bz2
busybox-w32-f8ddbe1ccce9eceaaac28b4b1aa71631fcc56db6.zip
ash: fix handling of ${VAR: -2}
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c12
-rw-r--r--shell/ash_test/ash-vars/var_bash1a.right6
-rwxr-xr-xshell/ash_test/ash-vars/var_bash1a.tests11
3 files changed, 25 insertions, 4 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 4f6376f78..496167fbe 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6323,6 +6323,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6323 6323
6324#if ENABLE_ASH_BASH_COMPAT 6324#if ENABLE_ASH_BASH_COMPAT
6325 case VSSUBSTR: 6325 case VSSUBSTR:
6326//TODO: support more general format ${v:EXPR:EXPR},
6327// where EXPR follows $(()) rules
6326 loc = str = stackblock() + strloc; 6328 loc = str = stackblock() + strloc;
6327 /* Read POS in ${var:POS:LEN} */ 6329 /* Read POS in ${var:POS:LEN} */
6328 pos = atoi(loc); /* number(loc) errors out on "1:4" */ 6330 pos = atoi(loc); /* number(loc) errors out on "1:4" */
@@ -11577,15 +11579,18 @@ parsesub: {
11577 STPUTC('=', out); 11579 STPUTC('=', out);
11578 flags = 0; 11580 flags = 0;
11579 if (subtype == 0) { 11581 if (subtype == 0) {
11582 static const char types[] ALIGN1 = "}-+?=";
11580 /* ${VAR...} but not $VAR or ${#VAR} */ 11583 /* ${VAR...} but not $VAR or ${#VAR} */
11581 /* c == first char after VAR */ 11584 /* c == first char after VAR */
11582 switch (c) { 11585 switch (c) {
11583 case ':': 11586 case ':':
11584 c = pgetc(); 11587 c = pgetc();
11585#if ENABLE_ASH_BASH_COMPAT 11588#if ENABLE_ASH_BASH_COMPAT
11586 if (c == ':' || c == '$' || isdigit(c)) { 11589 /* This check is only needed to not misinterpret
11587//TODO: support more general format ${v:EXPR:EXPR}, 11590 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11588// where EXPR follows $(()) rules 11591 * constructs.
11592 */
11593 if (!strchr(types, c)) {
11589 subtype = VSSUBSTR; 11594 subtype = VSSUBSTR;
11590 pungetc(); 11595 pungetc();
11591 break; /* "goto do_pungetc" is bigger (!) */ 11596 break; /* "goto do_pungetc" is bigger (!) */
@@ -11594,7 +11599,6 @@ parsesub: {
11594 flags = VSNUL; 11599 flags = VSNUL;
11595 /*FALLTHROUGH*/ 11600 /*FALLTHROUGH*/
11596 default: { 11601 default: {
11597 static const char types[] ALIGN1 = "}-+?=";
11598 const char *p = strchr(types, c); 11602 const char *p = strchr(types, c);
11599 if (p == NULL) 11603 if (p == NULL)
11600 goto badsub; 11604 goto badsub;
diff --git a/shell/ash_test/ash-vars/var_bash1a.right b/shell/ash_test/ash-vars/var_bash1a.right
new file mode 100644
index 000000000..1965b5c6c
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash1a.right
@@ -0,0 +1,6 @@
1parameter 'abcdef'
2varoffset2 'cdef'
3varoffset-2 'ef'
4literal '2' 'cdef'
5literal '-2' 'abcdef'
6literal ' -2' 'ef'
diff --git a/shell/ash_test/ash-vars/var_bash1a.tests b/shell/ash_test/ash-vars/var_bash1a.tests
new file mode 100755
index 000000000..551dd9acc
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash1a.tests
@@ -0,0 +1,11 @@
1parameter=abcdef
2offset=2
3noffset=-2
4echo "parameter '${parameter}'"
5echo "varoffset2 '${parameter:${offset}}'"
6echo "varoffset-2 '${parameter:${noffset}}'"
7echo "literal '2' '${parameter:2}'"
8# This is not inrpreted as ${VAR:POS{:LEN}},
9# but as ${VAR:=WORD} - if VAR is unset or null, substitute WORD
10echo "literal '-2' '${parameter:-2}'"
11echo "literal ' -2' '${parameter: -2}'"