diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-26 11:25:19 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-26 11:25:19 +0000 |
commit | 5b7589eb27e748a3d281c0341219cf7435e8b4f1 (patch) | |
tree | b9565d8d331207ed37a3b9c0f654b500839d8ef6 | |
parent | 80e57eb7d525803bb776e8294483141756b2b2ef (diff) | |
download | busybox-w32-5b7589eb27e748a3d281c0341219cf7435e8b4f1.tar.gz busybox-w32-5b7589eb27e748a3d281c0341219cf7435e8b4f1.tar.bz2 busybox-w32-5b7589eb27e748a3d281c0341219cf7435e8b4f1.zip |
hush: fix SEGV in % expansion
function old new delta
expand_variables 2203 2217 +14
-rw-r--r-- | shell/hush.c | 24 | ||||
-rw-r--r-- | shell/hush_test/hush-arith/arith.right | 6 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/var_posix1.right | 1 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/var_posix1.tests | 1 | ||||
-rw-r--r-- | shell/match.c | 18 | ||||
-rw-r--r-- | shell/match.h | 12 |
6 files changed, 31 insertions, 31 deletions
diff --git a/shell/hush.c b/shell/hush.c index fcbd96c4d..2ad8ebacb 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1990,12 +1990,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
1990 | * (expansion of right-hand side of assignment == 1-element expand. | 1990 | * (expansion of right-hand side of assignment == 1-element expand. |
1991 | * It will also do no globbing, and thus we must not backslash-quote!) */ | 1991 | * It will also do no globbing, and thus we must not backslash-quote!) */ |
1992 | 1992 | ||
1993 | char first_ch, ored_ch; | 1993 | char ored_ch; |
1994 | int i; | 1994 | char *p; |
1995 | const char *val; | ||
1996 | char *dyn_val, *p; | ||
1997 | 1995 | ||
1998 | dyn_val = NULL; | ||
1999 | ored_ch = 0; | 1996 | ored_ch = 0; |
2000 | 1997 | ||
2001 | debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg); | 1998 | debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg); |
@@ -2004,6 +2001,10 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2004 | debug_print_list("expand_vars_to_list[0]", output, n); | 2001 | debug_print_list("expand_vars_to_list[0]", output, n); |
2005 | 2002 | ||
2006 | while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { | 2003 | while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { |
2004 | char first_ch; | ||
2005 | int i; | ||
2006 | char *dyn_val = NULL; | ||
2007 | const char *val = NULL; | ||
2007 | #if ENABLE_HUSH_TICK | 2008 | #if ENABLE_HUSH_TICK |
2008 | o_string subst_result = NULL_O_STRING; | 2009 | o_string subst_result = NULL_O_STRING; |
2009 | #endif | 2010 | #endif |
@@ -2021,7 +2022,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2021 | if ((first_ch & 0x7f) != '@') | 2022 | if ((first_ch & 0x7f) != '@') |
2022 | ored_ch |= first_ch; | 2023 | ored_ch |= first_ch; |
2023 | 2024 | ||
2024 | val = NULL; | ||
2025 | switch (first_ch & 0x7f) { | 2025 | switch (first_ch & 0x7f) { |
2026 | /* Highest bit in first_ch indicates that var is double-quoted */ | 2026 | /* Highest bit in first_ch indicates that var is double-quoted */ |
2027 | case '$': /* pid */ | 2027 | case '$': /* pid */ |
@@ -2194,16 +2194,16 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2194 | if (exp_op == '%' || exp_op == '#') { | 2194 | if (exp_op == '%' || exp_op == '#') { |
2195 | if (val) { | 2195 | if (val) { |
2196 | /* we need to do a pattern match */ | 2196 | /* we need to do a pattern match */ |
2197 | bool zero; | 2197 | bool match_at_left; |
2198 | char *loc; | 2198 | char *loc; |
2199 | scan_t scan = pick_scan(exp_op, *exp_word, &zero); | 2199 | scan_t scan = pick_scan(exp_op, *exp_word, &match_at_left); |
2200 | if (exp_op == *exp_word) /* ## or %% */ | 2200 | if (exp_op == *exp_word) /* ## or %% */ |
2201 | ++exp_word; | 2201 | ++exp_word; |
2202 | val = dyn_val = xstrdup(val); | 2202 | val = dyn_val = xstrdup(val); |
2203 | loc = scan(dyn_val, exp_word, zero); | 2203 | loc = scan(dyn_val, exp_word, match_at_left); |
2204 | if (zero) | 2204 | if (match_at_left) /* # or ## */ |
2205 | val = loc; | 2205 | val = loc; |
2206 | else | 2206 | else if (loc) /* % or %% and match was found */ |
2207 | *loc = '\0'; | 2207 | *loc = '\0'; |
2208 | } | 2208 | } |
2209 | } else { | 2209 | } else { |
@@ -2263,11 +2263,11 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |||
2263 | } | 2263 | } |
2264 | } /* default: */ | 2264 | } /* default: */ |
2265 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ | 2265 | } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ |
2266 | |||
2266 | if (val) { | 2267 | if (val) { |
2267 | o_addQstr(output, val, strlen(val)); | 2268 | o_addQstr(output, val, strlen(val)); |
2268 | } | 2269 | } |
2269 | free(dyn_val); | 2270 | free(dyn_val); |
2270 | dyn_val = NULL; | ||
2271 | /* Do the check to avoid writing to a const string */ | 2271 | /* Do the check to avoid writing to a const string */ |
2272 | if (*p != SPECIAL_VAR_SYMBOL) | 2272 | if (*p != SPECIAL_VAR_SYMBOL) |
2273 | *p = SPECIAL_VAR_SYMBOL; | 2273 | *p = SPECIAL_VAR_SYMBOL; |
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index 8cde0ee53..83155fb03 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right | |||
@@ -63,9 +63,9 @@ hush: error in arithmetic | |||
63 | 40 40 | 63 | 40 40 |
64 | hush: error in arithmetic | 64 | hush: error in arithmetic |
65 | hush: divide by 0 | 65 | hush: divide by 0 |
66 | hush: can't exec 'let': No such file or directory | 66 | hush: can't execute 'let': No such file or directory |
67 | hush: error in arithmetic | 67 | hush: error in arithmetic |
68 | hush: can't exec 'let': No such file or directory | 68 | hush: can't execute 'let': No such file or directory |
69 | abc | 69 | abc |
70 | def | 70 | def |
71 | ghi | 71 | ghi |
@@ -135,4 +135,4 @@ hush: error in arithmetic | |||
135 | 42 | 135 | 42 |
136 | 42 | 136 | 42 |
137 | 42 | 137 | 42 |
138 | hush: can't exec 'a[b[c]d]=e': No such file or directory | 138 | hush: can't execute 'a[b[c]d]=e': No such file or directory |
diff --git a/shell/hush_test/hush-vars/var_posix1.right b/shell/hush_test/hush-vars/var_posix1.right index 47d52a6c2..e6cba2758 100644 --- a/shell/hush_test/hush-vars/var_posix1.right +++ b/shell/hush_test/hush-vars/var_posix1.right | |||
@@ -32,4 +32,5 @@ ababcdc | |||
32 | ababcdcd | 32 | ababcdcd |
33 | Empty: | 33 | Empty: |
34 | ababcdcd}_tail | 34 | ababcdcd}_tail |
35 | ababcdcd | ||
35 | end | 36 | end |
diff --git a/shell/hush_test/hush-vars/var_posix1.tests b/shell/hush_test/hush-vars/var_posix1.tests index 3069360e1..c1f64094d 100755 --- a/shell/hush_test/hush-vars/var_posix1.tests +++ b/shell/hush_test/hush-vars/var_posix1.tests | |||
@@ -43,5 +43,6 @@ echo ${var%*} | |||
43 | echo Empty:${var%%*} | 43 | echo Empty:${var%%*} |
44 | echo ${var#}}_tail | 44 | echo ${var#}}_tail |
45 | # UNFIXED BUG: echo ${var#\}}_tail | 45 | # UNFIXED BUG: echo ${var#\}}_tail |
46 | echo ${var%\\*} | ||
46 | 47 | ||
47 | echo end | 48 | echo end |
diff --git a/shell/match.c b/shell/match.c index 47038d667..a7101ef7e 100644 --- a/shell/match.c +++ b/shell/match.c | |||
@@ -11,8 +11,6 @@ | |||
11 | * Kenneth Almquist. | 11 | * Kenneth Almquist. |
12 | * | 12 | * |
13 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | 13 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
14 | * | ||
15 | * Original BSD copyright notice is retained at the end of this file. | ||
16 | */ | 14 | */ |
17 | #ifdef STANDALONE | 15 | #ifdef STANDALONE |
18 | # include <stdbool.h> | 16 | # include <stdbool.h> |
@@ -28,7 +26,7 @@ | |||
28 | 26 | ||
29 | #define pmatch(a, b) !fnmatch((a), (b), 0) | 27 | #define pmatch(a, b) !fnmatch((a), (b), 0) |
30 | 28 | ||
31 | char *scanleft(char *string, char *pattern, bool zero) | 29 | char *scanleft(char *string, char *pattern, bool match_at_left) |
32 | { | 30 | { |
33 | char c; | 31 | char c; |
34 | char *loc = string; | 32 | char *loc = string; |
@@ -38,7 +36,7 @@ char *scanleft(char *string, char *pattern, bool zero) | |||
38 | const char *s; | 36 | const char *s; |
39 | 37 | ||
40 | c = *loc; | 38 | c = *loc; |
41 | if (zero) { | 39 | if (match_at_left) { |
42 | *loc = '\0'; | 40 | *loc = '\0'; |
43 | s = string; | 41 | s = string; |
44 | } else | 42 | } else |
@@ -55,7 +53,7 @@ char *scanleft(char *string, char *pattern, bool zero) | |||
55 | return NULL; | 53 | return NULL; |
56 | } | 54 | } |
57 | 55 | ||
58 | char *scanright(char *string, char *pattern, bool zero) | 56 | char *scanright(char *string, char *pattern, bool match_at_left) |
59 | { | 57 | { |
60 | char c; | 58 | char c; |
61 | char *loc = string + strlen(string); | 59 | char *loc = string + strlen(string); |
@@ -65,7 +63,7 @@ char *scanright(char *string, char *pattern, bool zero) | |||
65 | const char *s; | 63 | const char *s; |
66 | 64 | ||
67 | c = *loc; | 65 | c = *loc; |
68 | if (zero) { | 66 | if (match_at_left) { |
69 | *loc = '\0'; | 67 | *loc = '\0'; |
70 | s = string; | 68 | s = string; |
71 | } else | 69 | } else |
@@ -88,7 +86,7 @@ int main(int argc, char *argv[]) | |||
88 | char *string; | 86 | char *string; |
89 | char *op; | 87 | char *op; |
90 | char *pattern; | 88 | char *pattern; |
91 | bool zero; | 89 | bool match_at_left; |
92 | char *loc; | 90 | char *loc; |
93 | 91 | ||
94 | int i; | 92 | int i; |
@@ -117,15 +115,15 @@ int main(int argc, char *argv[]) | |||
117 | continue; | 115 | continue; |
118 | } | 116 | } |
119 | op = string + off; | 117 | op = string + off; |
120 | scan = pick_scan(op[0], op[1], &zero); | 118 | scan = pick_scan(op[0], op[1], &match_at_left); |
121 | pattern = op + 1; | 119 | pattern = op + 1; |
122 | if (op[0] == op[1]) | 120 | if (op[0] == op[1]) |
123 | op[1] = '\0', ++pattern; | 121 | op[1] = '\0', ++pattern; |
124 | op[0] = '\0'; | 122 | op[0] = '\0'; |
125 | 123 | ||
126 | loc = scan(string, pattern, zero); | 124 | loc = scan(string, pattern, match_at_left); |
127 | 125 | ||
128 | if (zero) { | 126 | if (match_at_left) { |
129 | printf("'%s'\n", loc); | 127 | printf("'%s'\n", loc); |
130 | } else { | 128 | } else { |
131 | *loc = '\0'; | 129 | *loc = '\0'; |
diff --git a/shell/match.h b/shell/match.h index 3fc4de340..90597ee54 100644 --- a/shell/match.h +++ b/shell/match.h | |||
@@ -2,12 +2,12 @@ | |||
2 | 2 | ||
3 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 3 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
4 | 4 | ||
5 | typedef char *(*scan_t)(char *string, char *match, bool zero); | 5 | typedef char *(*scan_t)(char *string, char *match, bool match_at_left); |
6 | 6 | ||
7 | char *scanleft(char *string, char *match, bool zero); | 7 | char *scanleft(char *string, char *match, bool match_at_left); |
8 | char *scanright(char *string, char *match, bool zero); | 8 | char *scanright(char *string, char *match, bool match_at_left); |
9 | 9 | ||
10 | static inline scan_t pick_scan(char op1, char op2, bool *zero) | 10 | static inline scan_t pick_scan(char op1, char op2, bool *match_at_left) |
11 | { | 11 | { |
12 | /* # - scanleft | 12 | /* # - scanleft |
13 | * ## - scanright | 13 | * ## - scanright |
@@ -15,10 +15,10 @@ static inline scan_t pick_scan(char op1, char op2, bool *zero) | |||
15 | * %% - scanleft | 15 | * %% - scanleft |
16 | */ | 16 | */ |
17 | if (op1 == '#') { | 17 | if (op1 == '#') { |
18 | *zero = true; | 18 | *match_at_left = true; |
19 | return op1 == op2 ? scanright : scanleft; | 19 | return op1 == op2 ? scanright : scanleft; |
20 | } else { | 20 | } else { |
21 | *zero = false; | 21 | *match_at_left = false; |
22 | return op1 == op2 ? scanleft : scanright; | 22 | return op1 == op2 ? scanleft : scanright; |
23 | } | 23 | } |
24 | } | 24 | } |