diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-26 22:55:44 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-26 22:55:44 +0200 |
commit | fd33e17a2bf4c09bb12ac09a645cfd0f0f914fec (patch) | |
tree | 45d99d8cc103dcd97086b61f8f8616f5ac14e931 | |
parent | b768aeb164d361d1ca2c8f6c091e93442f072656 (diff) | |
download | busybox-w32-fd33e17a2bf4c09bb12ac09a645cfd0f0f914fec.tar.gz busybox-w32-fd33e17a2bf4c09bb12ac09a645cfd0f0f914fec.tar.bz2 busybox-w32-fd33e17a2bf4c09bb12ac09a645cfd0f0f914fec.zip |
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.c | 42 | ||||
-rw-r--r-- | shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right | 10 | ||||
-rwxr-xr-x | shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests | 21 |
3 files changed, 52 insertions, 21 deletions
diff --git a/shell/ash.c b/shell/ash.c index cfd8154ef..0337a5535 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6184,8 +6184,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6184 | char *startp; | 6184 | char *startp; |
6185 | char *loc; | 6185 | char *loc; |
6186 | char *rmesc, *rmescend; | 6186 | char *rmesc, *rmescend; |
6187 | IF_ASH_BASH_COMPAT(char *repl = NULL;) | 6187 | IF_ASH_BASH_COMPAT(const char *repl = NULL;) |
6188 | IF_ASH_BASH_COMPAT(char null = '\0';) | ||
6189 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) | 6188 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) |
6190 | int saveherefd = herefd; | 6189 | int saveherefd = herefd; |
6191 | int amount, workloc, resetloc; | 6190 | int amount, workloc, resetloc; |
@@ -6306,7 +6305,7 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6306 | if (!repl) { | 6305 | if (!repl) { |
6307 | repl = parse_sub_pattern(str, varflags & VSQUOTE); | 6306 | repl = parse_sub_pattern(str, varflags & VSQUOTE); |
6308 | if (!repl) | 6307 | if (!repl) |
6309 | repl = &null; | 6308 | repl = nullstr; |
6310 | } | 6309 | } |
6311 | 6310 | ||
6312 | /* If there's no pattern to match, return the expansion unmolested */ | 6311 | /* If there's no pattern to match, return the expansion unmolested */ |
@@ -6357,8 +6356,12 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6357 | idx = loc; | 6356 | idx = loc; |
6358 | } | 6357 | } |
6359 | 6358 | ||
6360 | for (loc = repl; *loc; loc++) { | 6359 | for (loc = (char*)repl; *loc; loc++) { |
6361 | char *restart_detect = stackblock(); | 6360 | char *restart_detect = stackblock(); |
6361 | if (quotes && *loc == '\\') { | ||
6362 | STPUTC(CTLESC, expdest); | ||
6363 | len++; | ||
6364 | } | ||
6362 | STPUTC(*loc, expdest); | 6365 | STPUTC(*loc, expdest); |
6363 | if (stackblock() != restart_detect) | 6366 | if (stackblock() != restart_detect) |
6364 | goto restart; | 6367 | goto restart; |
@@ -6368,6 +6371,10 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6368 | if (subtype == VSREPLACE) { | 6371 | if (subtype == VSREPLACE) { |
6369 | while (*idx) { | 6372 | while (*idx) { |
6370 | char *restart_detect = stackblock(); | 6373 | char *restart_detect = stackblock(); |
6374 | if (quotes && *idx == '\\') { | ||
6375 | STPUTC(CTLESC, expdest); | ||
6376 | len++; | ||
6377 | } | ||
6371 | STPUTC(*idx, expdest); | 6378 | STPUTC(*idx, expdest); |
6372 | if (stackblock() != restart_detect) | 6379 | if (stackblock() != restart_detect) |
6373 | goto restart; | 6380 | goto restart; |
@@ -6381,11 +6388,10 @@ subevalvar(char *p, char *str, int strloc, int subtype, | |||
6381 | /* We've put the replaced text into a buffer at workloc, now | 6388 | /* We've put the replaced text into a buffer at workloc, now |
6382 | * move it to the right place and adjust the stack. | 6389 | * move it to the right place and adjust the stack. |
6383 | */ | 6390 | */ |
6384 | startp = stackblock() + startloc; | ||
6385 | STPUTC('\0', expdest); | 6391 | STPUTC('\0', expdest); |
6386 | memmove(startp, stackblock() + workloc, len); | 6392 | startp = (char *)stackblock() + startloc; |
6387 | startp[len++] = '\0'; | 6393 | memmove(startp, (char *)stackblock() + workloc, len + 1); |
6388 | amount = expdest - ((char *)stackblock() + startloc + len - 1); | 6394 | amount = expdest - (startp + len); |
6389 | STADJUST(-amount, expdest); | 6395 | STADJUST(-amount, expdest); |
6390 | return startp; | 6396 | return startp; |
6391 | } | 6397 | } |
@@ -6685,7 +6691,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) | |||
6685 | */ | 6691 | */ |
6686 | STPUTC('\0', expdest); | 6692 | STPUTC('\0', expdest); |
6687 | patloc = expdest - (char *)stackblock(); | 6693 | patloc = expdest - (char *)stackblock(); |
6688 | if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype, | 6694 | if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype, |
6689 | startloc, varflags, | 6695 | startloc, varflags, |
6690 | //TODO: | EXP_REDIR too? All other such places do it too | 6696 | //TODO: | EXP_REDIR too? All other such places do it too |
6691 | /* quotes: */ flags & (EXP_FULL | EXP_CASE), | 6697 | /* quotes: */ flags & (EXP_FULL | EXP_CASE), |
@@ -6848,13 +6854,11 @@ addfname(const char *name) | |||
6848 | exparg.lastp = &sp->next; | 6854 | exparg.lastp = &sp->next; |
6849 | } | 6855 | } |
6850 | 6856 | ||
6851 | static char *expdir; | ||
6852 | |||
6853 | /* | 6857 | /* |
6854 | * Do metacharacter (i.e. *, ?, [...]) expansion. | 6858 | * Do metacharacter (i.e. *, ?, [...]) expansion. |
6855 | */ | 6859 | */ |
6856 | static void | 6860 | static void |
6857 | expmeta(char *enddir, char *name) | 6861 | expmeta(char *expdir, char *enddir, char *name) |
6858 | { | 6862 | { |
6859 | char *p; | 6863 | char *p; |
6860 | const char *cp; | 6864 | const char *cp; |
@@ -6953,7 +6957,7 @@ expmeta(char *enddir, char *name) | |||
6953 | for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';) | 6957 | for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';) |
6954 | continue; | 6958 | continue; |
6955 | p[-1] = '/'; | 6959 | p[-1] = '/'; |
6956 | expmeta(p, endname); | 6960 | expmeta(expdir, p, endname); |
6957 | } | 6961 | } |
6958 | } | 6962 | } |
6959 | } | 6963 | } |
@@ -7035,6 +7039,7 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7035 | /* TODO - EXP_REDIR */ | 7039 | /* TODO - EXP_REDIR */ |
7036 | 7040 | ||
7037 | while (str) { | 7041 | while (str) { |
7042 | char *expdir; | ||
7038 | struct strlist **savelastp; | 7043 | struct strlist **savelastp; |
7039 | struct strlist *sp; | 7044 | struct strlist *sp; |
7040 | char *p; | 7045 | char *p; |
@@ -7051,8 +7056,7 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7051 | int i = strlen(str->text); | 7056 | int i = strlen(str->text); |
7052 | expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ | 7057 | expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ |
7053 | } | 7058 | } |
7054 | 7059 | expmeta(expdir, expdir, p); | |
7055 | expmeta(expdir, p); | ||
7056 | free(expdir); | 7060 | free(expdir); |
7057 | if (p != str->text) | 7061 | if (p != str->text) |
7058 | free(p); | 7062 | free(p); |
@@ -9101,19 +9105,15 @@ evalcommand(union node *cmd, int flags) | |||
9101 | /* Print the command if xflag is set. */ | 9105 | /* Print the command if xflag is set. */ |
9102 | if (xflag) { | 9106 | if (xflag) { |
9103 | int n; | 9107 | int n; |
9104 | const char *p = " %s"; | 9108 | const char *p = " %s" + 1; |
9105 | 9109 | ||
9106 | p++; | ||
9107 | fdprintf(preverrout_fd, p, expandstr(ps4val())); | 9110 | fdprintf(preverrout_fd, p, expandstr(ps4val())); |
9108 | |||
9109 | sp = varlist.list; | 9111 | sp = varlist.list; |
9110 | for (n = 0; n < 2; n++) { | 9112 | for (n = 0; n < 2; n++) { |
9111 | while (sp) { | 9113 | while (sp) { |
9112 | fdprintf(preverrout_fd, p, sp->text); | 9114 | fdprintf(preverrout_fd, p, sp->text); |
9113 | sp = sp->next; | 9115 | sp = sp->next; |
9114 | if (*p == '%') { | 9116 | p = " %s"; |
9115 | p--; | ||
9116 | } | ||
9117 | } | 9117 | } |
9118 | sp = arglist.list; | 9118 | sp = arglist.list; |
9119 | } | 9119 | } |
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 000000000..b212c246c --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.right | |||
@@ -0,0 +1,10 @@ | |||
1 | 192\.168\.0\.1 | ||
2 | 192\.168\.0\.1[ | ||
3 | 192\.168\.0\.1[ | ||
4 | 192\\.168\\.0\\.1[ | ||
5 | 192\.168\.0\.1[ | ||
6 | 192\.168\.0\.1 | ||
7 | 192\.168\.0\.1[ | ||
8 | 192\.168\.0\.1[ | ||
9 | 192\\.168\\.0\\.1[ | ||
10 | 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 000000000..3fa2f186d --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_slash_bash1.tests | |||
@@ -0,0 +1,21 @@ | |||
1 | # The bug here was triggered by: | ||
2 | # * performin pathname expansion because we see [ | ||
3 | # * replace operator did not escape \ in replace string | ||
4 | |||
5 | IP=192.168.0.1 | ||
6 | |||
7 | rm -f '192.168.0.1[' | ||
8 | echo "${IP//./\\.}" | ||
9 | echo "${IP//./\\.}"'[' # bug was here | ||
10 | echo "${IP//./\\.}[" # bug was here | ||
11 | echo "${IP//./\\\\.}[" # bug was here | ||
12 | echo "192\.168\.0\.1[" | ||
13 | |||
14 | echo >'192.168.0.1[' | ||
15 | echo "${IP//./\\.}" | ||
16 | echo "${IP//./\\.}"'[' # bug was here | ||
17 | echo "${IP//./\\.}[" # bug was here | ||
18 | echo "${IP//./\\\\.}[" # bug was here | ||
19 | echo "192\.168\.0\.1[" | ||
20 | |||
21 | rm -f '192.168.0.1[' | ||