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>
This commit is contained in:
parent
823318822c
commit
1555895b4a
30
shell/ash.c
30
shell/ash.c
@ -7454,6 +7454,7 @@ evalvar(char *p, int flag)
|
|||||||
int patloc;
|
int patloc;
|
||||||
int startloc;
|
int startloc;
|
||||||
ssize_t varlen;
|
ssize_t varlen;
|
||||||
|
int discard;
|
||||||
int quoted;
|
int quoted;
|
||||||
|
|
||||||
varflags = (unsigned char) *p++;
|
varflags = (unsigned char) *p++;
|
||||||
@ -7469,33 +7470,31 @@ evalvar(char *p, int flag)
|
|||||||
if (varflags & VSNUL)
|
if (varflags & VSNUL)
|
||||||
varlen--;
|
varlen--;
|
||||||
|
|
||||||
|
discard = varlen < 0 ? EXP_DISCARD : 0;
|
||||||
|
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case VSPLUS:
|
case VSPLUS:
|
||||||
varlen = -1 - varlen;
|
discard ^= EXP_DISCARD;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 0:
|
case 0:
|
||||||
case VSMINUS:
|
case VSMINUS:
|
||||||
p = argstr(p, flag | EXP_TILDE | EXP_WORD);
|
p = argstr(p, flag | EXP_TILDE | EXP_WORD | (discard ^ EXP_DISCARD));
|
||||||
if (varlen < 0)
|
|
||||||
return p;
|
|
||||||
goto record;
|
goto record;
|
||||||
|
|
||||||
case VSASSIGN:
|
case VSASSIGN:
|
||||||
case VSQUESTION:
|
case VSQUESTION:
|
||||||
if (varlen >= 0)
|
p = subevalvar(p, var, 0, startloc, varflags,
|
||||||
|
(flag & ~QUOTES_ESC) | (discard ^ EXP_DISCARD));
|
||||||
|
|
||||||
|
if ((flag | ~discard) & EXP_DISCARD)
|
||||||
goto record;
|
goto record;
|
||||||
|
|
||||||
p = subevalvar(p, var, 0, startloc, varflags,
|
|
||||||
flag & ~QUOTES_ESC);
|
|
||||||
|
|
||||||
if (flag & EXP_DISCARD)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
varflags &= ~VSNUL;
|
varflags &= ~VSNUL;
|
||||||
|
subtype = VSNORMAL;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (varlen < 0 && uflag)
|
if ((discard & ~flag) && uflag)
|
||||||
varunset(p, var, 0, 0);
|
varunset(p, var, 0, 0);
|
||||||
|
|
||||||
if (subtype == VSLENGTH) {
|
if (subtype == VSLENGTH) {
|
||||||
@ -7503,7 +7502,7 @@ evalvar(char *p, int flag)
|
|||||||
if (flag & EXP_DISCARD)
|
if (flag & EXP_DISCARD)
|
||||||
return p;
|
return p;
|
||||||
cvtnum(varlen > 0 ? varlen : 0, flag);
|
cvtnum(varlen > 0 ? varlen : 0, flag);
|
||||||
goto record;
|
goto really_record;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subtype == VSNORMAL)
|
if (subtype == VSNORMAL)
|
||||||
@ -7528,7 +7527,7 @@ evalvar(char *p, int flag)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
flag |= varlen < 0 ? EXP_DISCARD : 0;
|
flag |= discard;
|
||||||
if (!(flag & EXP_DISCARD)) {
|
if (!(flag & EXP_DISCARD)) {
|
||||||
/*
|
/*
|
||||||
* Terminate the string and start recording the pattern
|
* 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);
|
p = subevalvar(p, NULL, patloc, startloc, varflags, flag);
|
||||||
|
|
||||||
record:
|
record:
|
||||||
if (flag & EXP_DISCARD)
|
if ((flag | discard) & EXP_DISCARD)
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
|
really_record:
|
||||||
if (quoted) {
|
if (quoted) {
|
||||||
quoted = *var == '@' && shellparam.nparam;
|
quoted = *var == '@' && shellparam.nparam;
|
||||||
if (!quoted)
|
if (!quoted)
|
||||||
|
Loading…
Reference in New Issue
Block a user