hush: fix SEGV in % expansion
No binary (build failed)
—
(log yok)
| @@ -1990,12 +1990,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |
| * (expansion of right-hand side of assignment == 1-element expand. | |
| * It will also do no globbing, and thus we must not backslash-quote!) */ | |
| - | char first_ch, ored_ch; |
| - | int i; |
| - | const char *val; |
| - | char *dyn_val, *p; |
| + | char ored_ch; |
| + | char *p; |
| - | dyn_val = NULL; |
| ored_ch = 0; | |
| 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) | |
| debug_print_list("expand_vars_to_list[0]", output, n); | |
| while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { | |
| + | char first_ch; |
| + | int i; |
| + | char *dyn_val = NULL; |
| + | const char *val = NULL; |
| #if ENABLE_HUSH_TICK | |
| o_string subst_result = NULL_O_STRING; | |
| #endif | |
| @@ -2021,7 +2022,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |
| if ((first_ch & 0x7f) != '@') | |
| ored_ch |= first_ch; | |
| - | val = NULL; |
| switch (first_ch & 0x7f) { | |
| /* Highest bit in first_ch indicates that var is double-quoted */ | |
| case '$': /* pid */ | |
| @@ -2194,16 +2194,16 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |
| if (exp_op == '%' || exp_op == '#') { | |
| if (val) { | |
| /* we need to do a pattern match */ | |
| - | bool zero; |
| + | bool match_at_left; |
| char *loc; | |
| - | scan_t scan = pick_scan(exp_op, *exp_word, &zero); |
| + | scan_t scan = pick_scan(exp_op, *exp_word, &match_at_left); |
| if (exp_op == *exp_word) /* ## or %% */ | |
| ++exp_word; | |
| val = dyn_val = xstrdup(val); | |
| - | loc = scan(dyn_val, exp_word, zero); |
| - | if (zero) |
| + | loc = scan(dyn_val, exp_word, match_at_left); |
| + | if (match_at_left) /* # or ## */ |
| val = loc; | |
| - | else |
| + | else if (loc) /* % or %% and match was found */ |
| *loc = '\0'; | |
| } | |
| } else { | |
| @@ -2263,11 +2263,11 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) | |
| } | |
| } /* default: */ | |
| } /* switch (char after <SPECIAL_VAR_SYMBOL>) */ | |
| + | |
| if (val) { | |
| o_addQstr(output, val, strlen(val)); | |
| } | |
| free(dyn_val); | |
| - | dyn_val = NULL; |
| /* Do the check to avoid writing to a const string */ | |
| if (*p != SPECIAL_VAR_SYMBOL) | |
| *p = SPECIAL_VAR_SYMBOL; | |
| @@ -63,9 +63,9 @@ hush: error in arithmetic | |
| 40 40 | |
| hush: error in arithmetic | |
| hush: divide by 0 | |
| - | hush: can't exec 'let': No such file or directory |
| + | hush: can't execute 'let': No such file or directory |
| hush: error in arithmetic | |
| - | hush: can't exec 'let': No such file or directory |
| + | hush: can't execute 'let': No such file or directory |
| abc | |
| def | |
| ghi | |
| @@ -135,4 +135,4 @@ hush: error in arithmetic | |
| 42 | |
| 42 | |
| 42 | |
| - | hush: can't exec 'a[b[c]d]=e': No such file or directory |
| + | hush: can't execute 'a[b[c]d]=e': No such file or directory |
| @@ -32,4 +32,5 @@ ababcdc | |
| ababcdcd | |
| Empty: | |
| ababcdcd}_tail | |
| + | ababcdcd |
| end | |
| @@ -43,5 +43,6 @@ echo ${var%*} | |
| echo Empty:${var%%*} | |
| echo ${var#}}_tail | |
| # UNFIXED BUG: echo ${var#\}}_tail | |
| + | echo ${var%\\*} |
| echo end | |
| @@ -11,8 +11,6 @@ | |
| * Kenneth Almquist. | |
| * | |
| * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | |
| - | * |
| - | * Original BSD copyright notice is retained at the end of this file. |
| */ | |
| #ifdef STANDALONE | |
| # include <stdbool.h> | |
| @@ -28,7 +26,7 @@ | |
| #define pmatch(a, b) !fnmatch((a), (b), 0) | |
| - | char *scanleft(char *string, char *pattern, bool zero) |
| + | char *scanleft(char *string, char *pattern, bool match_at_left) |
| { | |
| char c; | |
| char *loc = string; | |
| @@ -38,7 +36,7 @@ char *scanleft(char *string, char *pattern, bool zero) | |
| const char *s; | |
| c = *loc; | |
| - | if (zero) { |
| + | if (match_at_left) { |
| *loc = '\0'; | |
| s = string; | |
| } else | |
| @@ -55,7 +53,7 @@ char *scanleft(char *string, char *pattern, bool zero) | |
| return NULL; | |
| } | |
| - | char *scanright(char *string, char *pattern, bool zero) |
| + | char *scanright(char *string, char *pattern, bool match_at_left) |
| { | |
| char c; | |
| char *loc = string + strlen(string); | |
| @@ -65,7 +63,7 @@ char *scanright(char *string, char *pattern, bool zero) | |
| const char *s; | |
| c = *loc; | |
| - | if (zero) { |
| + | if (match_at_left) { |
| *loc = '\0'; | |
| s = string; | |
| } else | |
| @@ -88,7 +86,7 @@ int main(int argc, char *argv[]) | |
| char *string; | |
| char *op; | |
| char *pattern; | |
| - | bool zero; |
| + | bool match_at_left; |
| char *loc; | |
| int i; | |
| @@ -117,15 +115,15 @@ int main(int argc, char *argv[]) | |
| continue; | |
| } | |
| op = string + off; | |
| - | scan = pick_scan(op[0], op[1], &zero); |
| + | scan = pick_scan(op[0], op[1], &match_at_left); |
| pattern = op + 1; | |
| if (op[0] == op[1]) | |
| op[1] = '\0', ++pattern; | |
| op[0] = '\0'; | |
| - | loc = scan(string, pattern, zero); |
| + | loc = scan(string, pattern, match_at_left); |
| - | if (zero) { |
| + | if (match_at_left) { |
| printf("'%s'\n", loc); | |
| } else { | |
| *loc = '\0'; | |
| @@ -2,12 +2,12 @@ | |
| PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |
| - | typedef char *(*scan_t)(char *string, char *match, bool zero); |
| + | typedef char *(*scan_t)(char *string, char *match, bool match_at_left); |
| - | char *scanleft(char *string, char *match, bool zero); |
| - | char *scanright(char *string, char *match, bool zero); |
| + | char *scanleft(char *string, char *match, bool match_at_left); |
| + | char *scanright(char *string, char *match, bool match_at_left); |
| - | static inline scan_t pick_scan(char op1, char op2, bool *zero) |
| + | static inline scan_t pick_scan(char op1, char op2, bool *match_at_left) |
| { | |
| /* # - scanleft | |
| * ## - scanright | |
| @@ -15,10 +15,10 @@ static inline scan_t pick_scan(char op1, char op2, bool *zero) | |
| * %% - scanleft | |
| */ | |
| if (op1 == '#') { | |
| - | *zero = true; |
| + | *match_at_left = true; |
| return op1 == op2 ? scanright : scanleft; | |
| } else { | |
| - | *zero = false; |
| + | *match_at_left = false; |
| return op1 == op2 ? scanleft : scanright; | |
| } | |
| } | |