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:
parent
b768aeb164
commit
fd33e17a2b
42
shell/ash.c
42
shell/ash.c
@ -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;
|
||||||
}
|
}
|
||||||
|
10
shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right
Normal file
10
shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right
Normal 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[
|
21
shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests
Executable file
21
shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests
Executable 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['
|
Loading…
Reference in New Issue
Block a user