summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2010-06-26 22:55:44 +0200
committerDenys Vlasenko2010-06-26 22:55:44 +0200
commitfd33e17a2bf4c09bb12ac09a645cfd0f0f914fec (patch)
tree45d99d8cc103dcd97086b61f8f8616f5ac14e931
parentb768aeb164d361d1ca2c8f6c091e93442f072656 (diff)
downloadbusybox-fd33e17a2bf4c09bb12ac09a645cfd0f0f914fec.zip
busybox-fd33e17a2bf4c09bb12ac09a645cfd0f0f914fec.tar.gz
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>
-rw-r--r--shell/ash.c42
-rw-r--r--shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right10
-rwxr-xr-xshell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests21
3 files changed, 52 insertions, 21 deletions
diff --git a/shell/ash.c b/shell/ash.c
index cfd8154..0337a55 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -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;
}
diff --git a/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right b/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right
new file mode 100644
index 0000000..b212c24
--- /dev/null
+++ b/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right
@@ -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[
diff --git a/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests b/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests
new file mode 100755
index 0000000..3fa2f18
--- /dev/null
+++ b/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests
@@ -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['