aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-04 19:52:44 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-04 19:52:44 +0200
commite298ce69baef029f3951dd1d5ed50fdbc6c55c80 (patch)
tree85060a1578474d8ca4e1d5f89e1b0c8241235ba5
parent8ae6e9be5c1c7e7a1e9ce96f463c7d6ab1c9500f (diff)
downloadbusybox-w32-e298ce69baef029f3951dd1d5ed50fdbc6c55c80.tar.gz
busybox-w32-e298ce69baef029f3951dd1d5ed50fdbc6c55c80.tar.bz2
busybox-w32-e298ce69baef029f3951dd1d5ed50fdbc6c55c80.zip
hush: fix handling of backslashes in variable assignment
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rwxr-xr-xshell/ash_test/ash-vars/var_bash5.tests4
-rw-r--r--shell/hush.c43
-rw-r--r--shell/hush_test/hush-vars/var_unbackslash.right11
-rwxr-xr-xshell/hush_test/hush-vars/var_unbackslash.tests23
-rw-r--r--shell/match.c34
5 files changed, 74 insertions, 41 deletions
diff --git a/shell/ash_test/ash-vars/var_bash5.tests b/shell/ash_test/ash-vars/var_bash5.tests
index 3f49321e1..7f482a554 100755
--- a/shell/ash_test/ash-vars/var_bash5.tests
+++ b/shell/ash_test/ash-vars/var_bash5.tests
@@ -1,5 +1,5 @@
1# This testcase checks whether slashes in ${v/a/b} are parsed before or after expansions 1# This testcase checks whether slashes in ${v/a/b} are parsed before
2# in a part 2# or after expansions
3 3
4v='a/b/c' 4v='a/b/c'
5s='b/c' 5s='b/c'
diff --git a/shell/hush.c b/shell/hush.c
index e8dfb2499..d3dab5863 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -390,6 +390,7 @@ typedef struct o_string {
390 smallint o_glob; 390 smallint o_glob;
391 /* At least some part of the string was inside '' or "", 391 /* At least some part of the string was inside '' or "",
392 * possibly empty one: word"", wo''rd etc. */ 392 * possibly empty one: word"", wo''rd etc. */
393//TODO: rename to no_empty_expansion?
393 smallint o_quoted; 394 smallint o_quoted;
394 smallint has_empty_slot; 395 smallint has_empty_slot;
395 smallint o_assignment; /* 0:maybe, 1:yes, 2:no */ 396 smallint o_assignment; /* 0:maybe, 1:yes, 2:no */
@@ -2018,11 +2019,10 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len
2018{ 2019{
2019 while (len) { 2020 while (len) {
2020 o_addchr(o, *str); 2021 o_addchr(o, *str);
2021 if (*str++ == '\\' 2022 if (*str == '\\') {
2022 && (*str != '*' && *str != '?' && *str != '[')
2023 ) {
2024 o_addchr(o, '\\'); 2023 o_addchr(o, '\\');
2025 } 2024 }
2025 str++;
2026 len--; 2026 len--;
2027 } 2027 }
2028} 2028}
@@ -2128,8 +2128,8 @@ static void debug_print_list(const char *prefix, o_string *o, int n)
2128 int i = 0; 2128 int i = 0;
2129 2129
2130 indent(); 2130 indent();
2131 fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d\n", 2131 fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
2132 prefix, list, n, string_start, o->length, o->maxlen); 2132 prefix, list, n, string_start, o->length, o->maxlen, o->o_glob, o->o_quoted, o->o_escape);
2133 while (i < n) { 2133 while (i < n) {
2134 indent(); 2134 indent();
2135 fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], 2135 fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i],
@@ -2563,9 +2563,9 @@ static char *expand_pseudo_dquoted(const char *str)
2563 struct in_str input; 2563 struct in_str input;
2564 o_string dest = NULL_O_STRING; 2564 o_string dest = NULL_O_STRING;
2565 2565
2566 if (strchr(str, '$') == NULL 2566 if (!strchr(str, '$')
2567#if ENABLE_HUSH_TICK 2567#if ENABLE_HUSH_TICK
2568 && strchr(str, '`') == NULL 2568 && !strchr(str, '`')
2569#endif 2569#endif
2570 ) { 2570 ) {
2571 return NULL; 2571 return NULL;
@@ -2740,6 +2740,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2740 } 2740 }
2741#endif 2741#endif
2742 default: { /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */ 2742 default: { /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */
2743//TODO: move to a subroutine?
2743 char *var; 2744 char *var;
2744 char first_char; 2745 char first_char;
2745 char exp_op; 2746 char exp_op;
@@ -3000,18 +3001,22 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
3000 return n; 3001 return n;
3001} 3002}
3002 3003
3003static char **expand_variables(char **argv, int or_mask) 3004enum {
3005 EXPVAR_FLAG_GLOB = 0x200,
3006 EXPVAR_FLAG_ESCAPE_VARS = 0x100,
3007 EXPVAR_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */
3008};
3009static char **expand_variables(char **argv, unsigned or_mask)
3004{ 3010{
3005 int n; 3011 int n;
3006 char **list; 3012 char **list;
3007 char **v; 3013 char **v;
3008 o_string output = NULL_O_STRING; 3014 o_string output = NULL_O_STRING;
3009 3015
3010 if (or_mask & 0x100) { 3016 /* protect against globbing for "$var"? */
3011 output.o_escape = 1; /* protect against globbing for "$var" */ 3017 /* (unquoted $var will temporarily switch it off) */
3012 /* (unquoted $var will temporarily switch it off) */ 3018 output.o_escape = 1 & (or_mask / EXPVAR_FLAG_ESCAPE_VARS);
3013 output.o_glob = 1; 3019 output.o_glob = 1 & (or_mask / EXPVAR_FLAG_GLOB);
3014 }
3015 3020
3016 n = 0; 3021 n = 0;
3017 v = argv; 3022 v = argv;
@@ -3029,13 +3034,13 @@ static char **expand_variables(char **argv, int or_mask)
3029 3034
3030static char **expand_strvec_to_strvec(char **argv) 3035static char **expand_strvec_to_strvec(char **argv)
3031{ 3036{
3032 return expand_variables(argv, 0x100); 3037 return expand_variables(argv, EXPVAR_FLAG_GLOB | EXPVAR_FLAG_ESCAPE_VARS);
3033} 3038}
3034 3039
3035#if ENABLE_HUSH_BASH_COMPAT 3040#if ENABLE_HUSH_BASH_COMPAT
3036static char **expand_strvec_to_strvec_singleword_noglob(char **argv) 3041static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
3037{ 3042{
3038 return expand_variables(argv, 0x80); 3043 return expand_variables(argv, EXPVAR_FLAG_SINGLEWORD);
3039} 3044}
3040#endif 3045#endif
3041 3046
@@ -3075,15 +3080,15 @@ static char **expand_strvec_to_strvec_singleword_noglob_cond(char **argv)
3075#endif 3080#endif
3076 3081
3077/* Used for expansion of right hand of assignments */ 3082/* Used for expansion of right hand of assignments */
3078/* NB: should NOT do globbing! "export v=/bin/c*; env | grep ^v=" outputs 3083/* NB: should NOT do globbing!
3079 * "v=/bin/c*" */ 3084 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*" */
3080static char *expand_string_to_string(const char *str) 3085static char *expand_string_to_string(const char *str)
3081{ 3086{
3082 char *argv[2], **list; 3087 char *argv[2], **list;
3083 3088
3084 argv[0] = (char*)str; 3089 argv[0] = (char*)str;
3085 argv[1] = NULL; 3090 argv[1] = NULL;
3086 list = expand_variables(argv, 0x80); /* 0x80: singleword expansion */ 3091 list = expand_variables(argv, EXPVAR_FLAG_ESCAPE_VARS | EXPVAR_FLAG_SINGLEWORD);
3087 if (HUSH_DEBUG) 3092 if (HUSH_DEBUG)
3088 if (!list[0] || list[1]) 3093 if (!list[0] || list[1])
3089 bb_error_msg_and_die("BUG in varexp2"); 3094 bb_error_msg_and_die("BUG in varexp2");
@@ -3099,7 +3104,7 @@ static char* expand_strvec_to_string(char **argv)
3099{ 3104{
3100 char **list; 3105 char **list;
3101 3106
3102 list = expand_variables(argv, 0x80); 3107 list = expand_variables(argv, EXPVAR_FLAG_SINGLEWORD);
3103 /* Convert all NULs to spaces */ 3108 /* Convert all NULs to spaces */
3104 if (list[0]) { 3109 if (list[0]) {
3105 int n = 1; 3110 int n = 1;
diff --git a/shell/hush_test/hush-vars/var_unbackslash.right b/shell/hush_test/hush-vars/var_unbackslash.right
new file mode 100644
index 000000000..20c2ddf55
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_unbackslash.right
@@ -0,0 +1,11 @@
1b1=-qwerty-t-\-"---z-*-?-
2b1=-qwerty-t-\-"---z-*-?-
3b2=-qwerty-\t-\-"-\--\z-\*-\?-
4b2=-qwerty-\t-\-"-\--\z-\*-\?-
5b3=-$a-\t-\\-\"-\--\z-\*-\?-
6b3=-$a-\t-\\-\"-\--\z-\*-\?-
7c=-$a-\t-\\-\"-\--\z-\*-\?-
8c=-$a-\t-\\-\"-\--\z-\*-\?-
9c=-$a-\t-\\-\"-\--\z-\*-\?-
10c=-$a-\t-\\-\"-\--\z-\*-\?-
11Done: 0
diff --git a/shell/hush_test/hush-vars/var_unbackslash.tests b/shell/hush_test/hush-vars/var_unbackslash.tests
new file mode 100755
index 000000000..3c35d7df5
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_unbackslash.tests
@@ -0,0 +1,23 @@
1# Test for correct handling of backslashes
2a=qwerty
3
4b=-$a-\t-\\-\"-\--\z-\*-\?-
5echo b1=$b
6echo "b1=$b"
7b="-$a-\t-\\-\"-\--\z-\*-\?-"
8echo b2=$b
9echo "b2=$b"
10b='-$a-\t-\\-\"-\--\z-\*-\?-'
11echo b3=$b
12echo "b3=$b"
13
14c=$b
15echo "c=$c"
16c=${b}
17echo "c=$c"
18c="$b"
19echo "c=$c"
20c="${b}"
21echo "c=$c"
22
23echo "Done: $?"
diff --git a/shell/match.c b/shell/match.c
index 8b1ddacd5..01b843918 100644
--- a/shell/match.c
+++ b/shell/match.c
@@ -31,26 +31,23 @@ char *scanleft(char *string, char *pattern, bool match_at_left)
31 char c; 31 char c;
32 char *loc = string; 32 char *loc = string;
33 33
34 do { 34 while (1) {
35 int match; 35 int match;
36 const char *s;
37 36
38 c = *loc; 37 c = *loc;
39 if (match_at_left) { 38 if (match_at_left) {
40 *loc = '\0'; 39 *loc = '\0';
41 s = string; 40 match = pmatch(pattern, string);
42 } else 41 *loc = c;
43 s = loc; 42 } else {
44 match = pmatch(pattern, s); 43 match = pmatch(pattern, loc);
45 *loc = c; 44 }
46
47 if (match) 45 if (match)
48 return loc; 46 return loc;
49 47 if (!c)
48 return NULL;
50 loc++; 49 loc++;
51 } while (c); 50 }
52
53 return NULL;
54} 51}
55 52
56char *scanright(char *string, char *pattern, bool match_at_left) 53char *scanright(char *string, char *pattern, bool match_at_left)
@@ -60,20 +57,17 @@ char *scanright(char *string, char *pattern, bool match_at_left)
60 57
61 while (loc >= string) { 58 while (loc >= string) {
62 int match; 59 int match;
63 const char *s;
64 60
65 c = *loc; 61 c = *loc;
66 if (match_at_left) { 62 if (match_at_left) {
67 *loc = '\0'; 63 *loc = '\0';
68 s = string; 64 match = pmatch(pattern, string);
69 } else 65 *loc = c;
70 s = loc; 66 } else {
71 match = pmatch(pattern, s); 67 match = pmatch(pattern, loc);
72 *loc = c; 68 }
73
74 if (match) 69 if (match)
75 return loc; 70 return loc;
76
77 loc--; 71 loc--;
78 } 72 }
79 73