summaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
authorDenys Vlasenko2020-02-22 19:38:40 +0100
committerDenys Vlasenko2020-02-24 19:20:51 +0100
commit1555895b4af44ce47fe2365aec82e8e67c685f08 (patch)
treebd821be779bc1d489ac966b0d83e4a5e026979dd /shell/ash.c
parent823318822ccb0e0910abbd4e1f983637dfd9d3c0 (diff)
downloadbusybox-1555895b4af44ce47fe2365aec82e8e67c685f08.zip
busybox-1555895b4af44ce47fe2365aec82e8e67c685f08.tar.gz
ash: expand: Fix multiple issues with EXP_DISCARD in evalvar
Upstream commit: Date: Wed, 12 Sep 2018 14:27:16 +0800 expand: Fix multiple issues with EXP_DISCARD in evalvar The commit 3cd538634f71538370f5af239f342aec48b7470b broke parameter expansion in multiple ways because the EXP_DISCARD flag wasn't set or tested for various cases: $ src/dash -c 'var=; echo ${var:+nonempty}' nonempty $ src/dash -u -c 'unset foo bar; echo ${foo+${bar}}' dash: 1: bar: parameter not set $ src/dash -c 'foo=bar; echo ${foo=BUG}; echo $foo' barBUG bar $ This patch fixes them by introducing a new discard variable that tracks whether the extra word should be discarded or not when it is parsed. Reported-by: Martijn Dekker <martijn@inlv.org> Fixes: 3cd538634f71 ("expand: Do not reprocess data when...") Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Reported-by: Martijn Dekker <martijn@inlv.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 425da6b..d0d99f6 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7454,6 +7454,7 @@ evalvar(char *p, int flag)
int patloc;
int startloc;
ssize_t varlen;
+ int discard;
int quoted;
varflags = (unsigned char) *p++;
@@ -7469,33 +7470,31 @@ evalvar(char *p, int flag)
if (varflags & VSNUL)
varlen--;
+ discard = varlen < 0 ? EXP_DISCARD : 0;
+
switch (subtype) {
case VSPLUS:
- varlen = -1 - varlen;
+ discard ^= EXP_DISCARD;
/* fall through */
case 0:
case VSMINUS:
- p = argstr(p, flag | EXP_TILDE | EXP_WORD);
- if (varlen < 0)
- return p;
+ p = argstr(p, flag | EXP_TILDE | EXP_WORD | (discard ^ EXP_DISCARD));
goto record;
case VSASSIGN:
case VSQUESTION:
- if (varlen >= 0)
- goto record;
-
p = subevalvar(p, var, 0, startloc, varflags,
- flag & ~QUOTES_ESC);
+ (flag & ~QUOTES_ESC) | (discard ^ EXP_DISCARD));
- if (flag & EXP_DISCARD)
- return p;
+ if ((flag | ~discard) & EXP_DISCARD)
+ goto record;
varflags &= ~VSNUL;
+ subtype = VSNORMAL;
goto again;
}
- if (varlen < 0 && uflag)
+ if ((discard & ~flag) && uflag)
varunset(p, var, 0, 0);
if (subtype == VSLENGTH) {
@@ -7503,7 +7502,7 @@ evalvar(char *p, int flag)
if (flag & EXP_DISCARD)
return p;
cvtnum(varlen > 0 ? varlen : 0, flag);
- goto record;
+ goto really_record;
}
if (subtype == VSNORMAL)
@@ -7528,7 +7527,7 @@ evalvar(char *p, int flag)
}
#endif
- flag |= varlen < 0 ? EXP_DISCARD : 0;
+ flag |= discard;
if (!(flag & EXP_DISCARD)) {
/*
* Terminate the string and start recording the pattern
@@ -7541,9 +7540,10 @@ evalvar(char *p, int flag)
p = subevalvar(p, NULL, patloc, startloc, varflags, flag);
record:
- if (flag & EXP_DISCARD)
+ if ((flag | discard) & EXP_DISCARD)
return p;
+ really_record:
if (quoted) {
quoted = *var == '@' && shellparam.nparam;
if (!quoted)