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 /shell | |
| 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>
Diffstat (limited to 'shell')
| -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[' | ||
