diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-08-04 22:25:28 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-08-04 22:25:28 +0200 |
commit | c2aa218f23a4e952746ebef7bb86668c6255471c (patch) | |
tree | 6a2884b85c52a31ad9b69e7bd2cde5d688fa139e | |
parent | 2005d3ff3661220f11e8ff1911b24051b3669566 (diff) | |
download | busybox-w32-c2aa218f23a4e952746ebef7bb86668c6255471c.tar.gz busybox-w32-c2aa218f23a4e952746ebef7bb86668c6255471c.tar.bz2 busybox-w32-c2aa218f23a4e952746ebef7bb86668c6255471c.zip |
ash,hush: properly handle ${v//pattern/repl} if pattern starts with /
Closes 2695
function old new delta
parse_dollar 762 790 +28
subevalvar 1258 1267 +9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 37/0) Total: 37 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
6 files changed, 28 insertions, 1 deletions
diff --git a/shell/ash.c b/shell/ash.c index 03fbbee53..5c431c9ff 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6854,8 +6854,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6854 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 6854 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
6855 | /* Find '/' and replace with NUL */ | 6855 | /* Find '/' and replace with NUL */ |
6856 | repl = p; | 6856 | repl = p; |
6857 | /* The pattern can't be empty. | ||
6858 | * IOW: if the first char after "${v//" is a slash, | ||
6859 | * it does not terminate the pattern - it's the first char of the pattern: | ||
6860 | * v=/dev/ram; echo ${v////-} prints -dev-ram (pattern is "/") | ||
6861 | * v=/dev/ram; echo ${v///r/-} prints /dev-am (pattern is "/r") | ||
6862 | */ | ||
6863 | if (*repl == '/') | ||
6864 | repl++; | ||
6857 | for (;;) { | 6865 | for (;;) { |
6858 | /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */ | ||
6859 | if (*repl == '\0') { | 6866 | if (*repl == '\0') { |
6860 | repl = NULL; | 6867 | repl = NULL; |
6861 | break; | 6868 | break; |
@@ -6864,6 +6871,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6864 | *repl = '\0'; | 6871 | *repl = '\0'; |
6865 | break; | 6872 | break; |
6866 | } | 6873 | } |
6874 | /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */ | ||
6867 | if ((unsigned char)*repl == CTLESC && repl[1]) | 6875 | if ((unsigned char)*repl == CTLESC && repl[1]) |
6868 | repl++; | 6876 | repl++; |
6869 | repl++; | 6877 | repl++; |
diff --git a/shell/ash_test/ash-vars/var_bash_pattern_starting_with_slash.right b/shell/ash_test/ash-vars/var_bash_pattern_starting_with_slash.right new file mode 100644 index 000000000..439dca578 --- /dev/null +++ b/shell/ash_test/ash-vars/var_bash_pattern_starting_with_slash.right | |||
@@ -0,0 +1,2 @@ | |||
1 | -dev-ram | ||
2 | /dev-am | ||
diff --git a/shell/ash_test/ash-vars/var_bash_pattern_starting_with_slash.tests b/shell/ash_test/ash-vars/var_bash_pattern_starting_with_slash.tests new file mode 100755 index 000000000..b83fb8eeb --- /dev/null +++ b/shell/ash_test/ash-vars/var_bash_pattern_starting_with_slash.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | v=/dev/ram | ||
2 | echo ${v////-} | ||
3 | echo ${v///r/-} | ||
diff --git a/shell/hush.c b/shell/hush.c index 6852b5f79..3407711cd 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -4930,6 +4930,15 @@ static int parse_dollar(o_string *as_string, | |||
4930 | end_ch = '}' * 0x100 + '/'; | 4930 | end_ch = '}' * 0x100 + '/'; |
4931 | } | 4931 | } |
4932 | o_addchr(dest, ch); | 4932 | o_addchr(dest, ch); |
4933 | /* The pattern can't be empty. | ||
4934 | * IOW: if the first char after "${v//" is a slash, | ||
4935 | * it does not terminate the pattern - it's the first char of the pattern: | ||
4936 | * v=/dev/ram; echo ${v////-} prints -dev-ram (pattern is "/") | ||
4937 | * v=/dev/ram; echo ${v///r/-} prints /dev-am (pattern is "/r") | ||
4938 | */ | ||
4939 | if (i_peek(input) == '/') { | ||
4940 | o_addchr(dest, i_getch(input)); | ||
4941 | } | ||
4933 | again: | 4942 | again: |
4934 | if (!BB_MMU) | 4943 | if (!BB_MMU) |
4935 | pos = dest->length; | 4944 | pos = dest->length; |
diff --git a/shell/hush_test/hush-vars/var_bash_pattern_starting_with_slash.right b/shell/hush_test/hush-vars/var_bash_pattern_starting_with_slash.right new file mode 100644 index 000000000..439dca578 --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash_pattern_starting_with_slash.right | |||
@@ -0,0 +1,2 @@ | |||
1 | -dev-ram | ||
2 | /dev-am | ||
diff --git a/shell/hush_test/hush-vars/var_bash_pattern_starting_with_slash.tests b/shell/hush_test/hush-vars/var_bash_pattern_starting_with_slash.tests new file mode 100755 index 000000000..b83fb8eeb --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash_pattern_starting_with_slash.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | v=/dev/ram | ||
2 | echo ${v////-} | ||
3 | echo ${v///r/-} | ||