ash: fix obscure case of replacing + globbing + backslashes

function                                             old     new   delta
subevalvar                                          1152    1178     +26
readtoken1                                          3267    3275      +8
redirect                                            1284    1286      +2
expandarg                                            957     958      +1
expdir                                                 4       -      -4
evalcommand                                         1219    1209     -10
expmeta                                              481     469     -12
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 4/2 up/down: 37/-26)             Total: 11 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-06-26 22:55:44 +02:00
parent b768aeb164
commit fd33e17a2b
3 changed files with 52 additions and 21 deletions

View File

@ -6184,8 +6184,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
char *startp;
char *loc;
char *rmesc, *rmescend;
IF_ASH_BASH_COMPAT(char *repl = NULL;)
IF_ASH_BASH_COMPAT(char null = '\0';)
IF_ASH_BASH_COMPAT(const char *repl = NULL;)
IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
int saveherefd = herefd;
int amount, workloc, resetloc;
@ -6306,7 +6305,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
if (!repl) {
repl = parse_sub_pattern(str, varflags & VSQUOTE);
if (!repl)
repl = &null;
repl = nullstr;
}
/* If there's no pattern to match, return the expansion unmolested */
@ -6357,8 +6356,12 @@ subevalvar(char *p, char *str, int strloc, int subtype,
idx = loc;
}
for (loc = repl; *loc; loc++) {
for (loc = (char*)repl; *loc; loc++) {
char *restart_detect = stackblock();
if (quotes && *loc == '\\') {
STPUTC(CTLESC, expdest);
len++;
}
STPUTC(*loc, expdest);
if (stackblock() != restart_detect)
goto restart;
@ -6368,6 +6371,10 @@ subevalvar(char *p, char *str, int strloc, int subtype,
if (subtype == VSREPLACE) {
while (*idx) {
char *restart_detect = stackblock();
if (quotes && *idx == '\\') {
STPUTC(CTLESC, expdest);
len++;
}
STPUTC(*idx, expdest);
if (stackblock() != restart_detect)
goto restart;
@ -6381,11 +6388,10 @@ subevalvar(char *p, char *str, int strloc, int subtype,
/* We've put the replaced text into a buffer at workloc, now
* move it to the right place and adjust the stack.
*/
startp = stackblock() + startloc;
STPUTC('\0', expdest);
memmove(startp, stackblock() + workloc, len);
startp[len++] = '\0';
amount = expdest - ((char *)stackblock() + startloc + len - 1);
startp = (char *)stackblock() + startloc;
memmove(startp, (char *)stackblock() + workloc, len + 1);
amount = expdest - (startp + len);
STADJUST(-amount, expdest);
return startp;
}
@ -6685,7 +6691,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
*/
STPUTC('\0', expdest);
patloc = expdest - (char *)stackblock();
if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype,
startloc, varflags,
//TODO: | EXP_REDIR too? All other such places do it too
/* quotes: */ flags & (EXP_FULL | EXP_CASE),
@ -6848,13 +6854,11 @@ addfname(const char *name)
exparg.lastp = &sp->next;
}
static char *expdir;
/*
* Do metacharacter (i.e. *, ?, [...]) expansion.
*/
static void
expmeta(char *enddir, char *name)
expmeta(char *expdir, char *enddir, char *name)
{
char *p;
const char *cp;
@ -6953,7 +6957,7 @@ expmeta(char *enddir, char *name)
for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
continue;
p[-1] = '/';
expmeta(p, endname);
expmeta(expdir, p, endname);
}
}
}
@ -7035,6 +7039,7 @@ expandmeta(struct strlist *str /*, int flag*/)
/* TODO - EXP_REDIR */
while (str) {
char *expdir;
struct strlist **savelastp;
struct strlist *sp;
char *p;
@ -7051,8 +7056,7 @@ expandmeta(struct strlist *str /*, int flag*/)
int i = strlen(str->text);
expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
}
expmeta(expdir, p);
expmeta(expdir, expdir, p);
free(expdir);
if (p != str->text)
free(p);
@ -9101,19 +9105,15 @@ evalcommand(union node *cmd, int flags)
/* Print the command if xflag is set. */
if (xflag) {
int n;
const char *p = " %s";
const char *p = " %s" + 1;
p++;
fdprintf(preverrout_fd, p, expandstr(ps4val()));
sp = varlist.list;
for (n = 0; n < 2; n++) {
while (sp) {
fdprintf(preverrout_fd, p, sp->text);
sp = sp->next;
if (*p == '%') {
p--;
}
p = " %s";
}
sp = arglist.list;
}

View File

@ -0,0 +1,10 @@
192\.168\.0\.1
192\.168\.0\.1[
192\.168\.0\.1[
192\\.168\\.0\\.1[
192\.168\.0\.1[
192\.168\.0\.1
192\.168\.0\.1[
192\.168\.0\.1[
192\\.168\\.0\\.1[
192\.168\.0\.1[

View File

@ -0,0 +1,21 @@
# The bug here was triggered by:
# * performin pathname expansion because we see [
# * replace operator did not escape \ in replace string
IP=192.168.0.1
rm -f '192.168.0.1['
echo "${IP//./\\.}"
echo "${IP//./\\.}"'[' # bug was here
echo "${IP//./\\.}[" # bug was here
echo "${IP//./\\\\.}[" # bug was here
echo "192\.168\.0\.1["
echo >'192.168.0.1['
echo "${IP//./\\.}"
echo "${IP//./\\.}"'[' # bug was here
echo "${IP//./\\.}[" # bug was here
echo "${IP//./\\\\.}[" # bug was here
echo "192\.168\.0\.1["
rm -f '192.168.0.1['