aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-07-24 10:36:39 +0100
committerRon Yorston <rmy@pobox.com>2021-07-24 10:36:39 +0100
commit79ecbe5abfc8c1c9b6ef49655225d2f8afc9119c (patch)
tree7210c6fb34af20d7e9d9bd74c6809ee858571a9a /shell
parent45863925a722c75b6ca4ba055c4a7d54f53d3f95 (diff)
parent1310d7b1d106d7ab0ec84ce88c12302cca934230 (diff)
downloadbusybox-w32-79ecbe5abfc8c1c9b6ef49655225d2f8afc9119c.tar.gz
busybox-w32-79ecbe5abfc8c1c9b6ef49655225d2f8afc9119c.tar.bz2
busybox-w32-79ecbe5abfc8c1c9b6ef49655225d2f8afc9119c.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 8b8c5f1dc..3e02a4e1f 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7538,7 +7538,8 @@ scanright(char *startp, char *rmesc, char *rmescend,
7538 * Logic: 7538 * Logic:
7539 * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc, 7539 * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
7540 * and on each iteration they go back two/one char until they reach the beginning. 7540 * and on each iteration they go back two/one char until they reach the beginning.
7541 * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc. 7541 * We try to match "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
7542 * If one of these matches, return pointer past last matched char in startp.
7542 */ 7543 */
7543 /* TODO: document in what other circumstances we are called. */ 7544 /* TODO: document in what other circumstances we are called. */
7544 7545
@@ -7826,6 +7827,7 @@ subevalvar(char *start, char *str, int strloc,
7826#if BASH_PATTERN_SUBST 7827#if BASH_PATTERN_SUBST
7827 workloc = expdest - (char *)stackblock(); 7828 workloc = expdest - (char *)stackblock();
7828 if (subtype == VSREPLACE || subtype == VSREPLACEALL) { 7829 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7830 size_t no_meta_len;
7829 int len; 7831 int len;
7830 char *idx, *end; 7832 char *idx, *end;
7831 7833
@@ -7843,16 +7845,38 @@ subevalvar(char *start, char *str, int strloc,
7843 if (str[0] == '\0') 7845 if (str[0] == '\0')
7844 goto out1; 7846 goto out1;
7845 7847
7848 no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str);
7846 len = 0; 7849 len = 0;
7847 idx = startp; 7850 idx = startp;
7848 end = str - 1; 7851 end = str - 1;
7849 while (idx <= end) { 7852 while (idx <= end) {
7850 try_to_match: 7853 try_to_match:
7851 loc = scanright(idx, rmesc, rmescend, str, quotes, 1); 7854 if (no_meta_len == 0) {
7855 /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */
7856 loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1);
7857 } else {
7858 /* Testcase for very slow replace (performs about 22k replaces):
7859 * x=::::::::::::::::::::::
7860 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
7861 * echo "${x//:/|}"
7862 */
7863 size_t n;
7864 if (strncmp(rmesc, str, no_meta_len) != 0)
7865 goto no_match;
7866 n = no_meta_len;
7867 loc = idx;
7868 do {
7869 if (quotes && (unsigned char)*loc == CTLESC)
7870 loc++;
7871 loc++;
7872 } while (--n != 0);
7873 }
7852 //bb_error_msg("scanright('%s'):'%s'", str, loc); 7874 //bb_error_msg("scanright('%s'):'%s'", str, loc);
7853 if (!loc) { 7875 if (!loc) {
7876 char *restart_detect;
7877 no_match:
7854 /* No match, advance */ 7878 /* No match, advance */
7855 char *restart_detect = stackblock(); 7879 restart_detect = stackblock();
7856 skip_matching: 7880 skip_matching:
7857 if (idx >= end) 7881 if (idx >= end)
7858 break; 7882 break;