ash: [EXPAND] Do not split quoted VSLENGTH and VSTRIM

Upstream patch:

    Date: Wed, 8 Oct 2014 15:42:08 +0800
    [EXPAND] Do not split quoted VSLENGTH and VSTRIM

    Currently VSLENGTH and VSTRIM* are field-split even within quotes.
    This is obviously wrong.  This patch fixes that.

    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2016-10-01 20:55:02 +02:00
parent c4d4380a07
commit 88ac97d02d
9 changed files with 88 additions and 30 deletions

View File

@ -6753,7 +6753,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
* input string. * input string.
*/ */
static char * static char *
evalvar(char *p, int flags, struct strlist *var_str_list) evalvar(char *p, int flag, struct strlist *var_str_list)
{ {
char varflags; char varflags;
char subtype; char subtype;
@ -6767,7 +6767,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
varflags = (unsigned char) *p++; varflags = (unsigned char) *p++;
subtype = varflags & VSTYPE; subtype = varflags & VSTYPE;
quoted = flags & EXP_QUOTED; quoted = flag & EXP_QUOTED;
var = p; var = p;
easy = (!quoted || (*var == '@' && shellparam.nparam)); easy = (!quoted || (*var == '@' && shellparam.nparam));
nulonly = easy; nulonly = easy;
@ -6775,7 +6775,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
p = strchr(p, '=') + 1; //TODO: use var_end(p)? p = strchr(p, '=') + 1; //TODO: use var_end(p)?
again: again:
varlen = varvalue(var, varflags, flags, var_str_list, &nulonly); varlen = varvalue(var, varflags, flag, var_str_list, &nulonly);
if (varflags & VSNUL) if (varflags & VSNUL)
varlen--; varlen--;
@ -6789,36 +6789,27 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
if (varlen < 0) { if (varlen < 0) {
argstr( argstr(
p, p,
flags | EXP_TILDE | EXP_WORD, flag | EXP_TILDE | EXP_WORD,
var_str_list var_str_list
); );
goto end; goto end;
} }
if (easy) goto record;
goto record;
goto end;
} }
if (subtype == VSASSIGN || subtype == VSQUESTION) { if (subtype == VSASSIGN || subtype == VSQUESTION) {
if (varlen < 0) { if (varlen >= 0)
if (subevalvar(p, var, /* strloc: */ 0,
subtype, startloc, varflags,
/* quotes: */ flags & ~QUOTES_ESC,
var_str_list)
) {
varflags &= ~VSNUL;
/*
* Remove any recorded regions beyond
* start of variable
*/
removerecordregions(startloc);
goto again;
}
goto end;
}
if (easy)
goto record; goto record;
goto end;
subevalvar(p, var, 0, subtype, startloc, varflags,
flag & ~QUOTES_ESC, var_str_list);
varflags &= ~VSNUL;
/*
* Remove any recorded regions beyond
* start of variable
*/
removerecordregions(startloc);
goto again;
} }
if (varlen < 0 && uflag) if (varlen < 0 && uflag)
@ -6830,8 +6821,10 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
} }
if (subtype == VSNORMAL) { if (subtype == VSNORMAL) {
if (easy) record:
goto record; if (!easy)
goto end;
recordregion(startloc, expdest - (char *)stackblock(), nulonly);
goto end; goto end;
} }
@ -6860,7 +6853,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
STPUTC('\0', expdest); STPUTC('\0', expdest);
patloc = expdest - (char *)stackblock(); patloc = expdest - (char *)stackblock();
if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
startloc, varflags, flags, var_str_list)) { startloc, varflags, flag, var_str_list)) {
int amount = expdest - ( int amount = expdest - (
(char *)stackblock() + patloc - 1 (char *)stackblock() + patloc - 1
); );
@ -6868,8 +6861,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
} }
/* Remove any recorded regions beyond start of variable */ /* Remove any recorded regions beyond start of variable */
removerecordregions(startloc); removerecordregions(startloc);
record: goto record;
recordregion(startloc, expdest - (char *)stackblock(), nulonly);
} }
end: end:

View File

@ -0,0 +1,3 @@
Unquoted:<1>
Unquoted:<3>
Quoted:<123>

View File

@ -0,0 +1,13 @@
# 123 chars long
a="\
01234567890123456789\
01234567890123456789\
01234567890123456789\
01234567890123456789\
01234567890123456789\
0123456789\
0123456789\
012"
IFS=2; for v in ${#a}; do echo Unquoted:"<$v>"; done
IFS=2; for v in "${#a}"; do echo Quoted:"<$v>"; done

View File

@ -0,0 +1,12 @@
Unquoted%:<q>
Unquoted%:<w>
Unquoted%:<e>
Unquoted%:<r>
Unquoted%:<t>
Unquoted#:<w>
Unquoted#:<e>
Unquoted#:<r>
Unquoted#:<t>
Unquoted#:<y>
Quoted%:<q w e r t >
Quoted#:< w e r t y>

View File

@ -0,0 +1,5 @@
a="q w e r t y"
for v in ${a%y}; do echo Unquoted%:"<$v>"; done
for v in ${a#q}; do echo Unquoted#:"<$v>"; done
for v in "${a%y}"; do echo Quoted%:"<$v>"; done
for v in "${a#q}"; do echo Quoted#:"<$v>"; done

View File

@ -0,0 +1,3 @@
Unquoted:<1>
Unquoted:<3>
Quoted:<123>

View File

@ -0,0 +1,13 @@
# 123 chars long
a="\
01234567890123456789\
01234567890123456789\
01234567890123456789\
01234567890123456789\
01234567890123456789\
0123456789\
0123456789\
012"
IFS=2; for v in ${#a}; do echo Unquoted:"<$v>"; done
IFS=2; for v in "${#a}"; do echo Quoted:"<$v>"; done

View File

@ -0,0 +1,12 @@
Unquoted%:<q>
Unquoted%:<w>
Unquoted%:<e>
Unquoted%:<r>
Unquoted%:<t>
Unquoted#:<w>
Unquoted#:<e>
Unquoted#:<r>
Unquoted#:<t>
Unquoted#:<y>
Quoted%:<q w e r t >
Quoted#:< w e r t y>

View File

@ -0,0 +1,5 @@
a="q w e r t y"
for v in ${a%y}; do echo Unquoted%:"<$v>"; done
for v in ${a#q}; do echo Unquoted#:"<$v>"; done
for v in "${a%y}"; do echo Quoted%:"<$v>"; done
for v in "${a#q}"; do echo Quoted#:"<$v>"; done