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