aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-05-22 06:20:26 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-05-22 06:20:26 +0200
commite85248afa23434b78e48fe09b57eea5f6657410d (patch)
tree8e4ddbead7f630a6cf3f5e224fb05952818b76a2 /shell/hush.c
parent8a33679694b0fdf459d69868f85c081cab5687cb (diff)
downloadbusybox-w32-e85248afa23434b78e48fe09b57eea5f6657410d.tar.gz
busybox-w32-e85248afa23434b78e48fe09b57eea5f6657410d.tar.bz2
busybox-w32-e85248afa23434b78e48fe09b57eea5f6657410d.zip
hush: fix segfault in ${?:N:M}
function old new delta expand_vars_to_list 2374 2409 +35 builtin_umask 132 133 +1 builtin_exit 47 48 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 37/0) Total: 37 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c81
1 files changed, 47 insertions, 34 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 7645a34a4..08e63785d 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -179,9 +179,13 @@
179 179
180#define ERR_PTR ((void*)(long)1) 180#define ERR_PTR ((void*)(long)1)
181 181
182#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 182#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
183 183
184#define SPECIAL_VAR_SYMBOL 3 184#define _SPECIAL_VARS_STR "_*@$!?#"
185#define SPECIAL_VARS_STR ("_*@$!?#" + 1)
186#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
187
188#define SPECIAL_VAR_SYMBOL 3
185 189
186struct variable; 190struct variable;
187 191
@@ -2472,21 +2476,6 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2472 2476
2473 switch (first_ch & 0x7f) { 2477 switch (first_ch & 0x7f) {
2474 /* Highest bit in first_ch indicates that var is double-quoted */ 2478 /* Highest bit in first_ch indicates that var is double-quoted */
2475 case '$': /* pid */
2476 val = utoa(G.root_pid);
2477 break;
2478 case '!': /* bg pid */
2479 val = G.last_bg_pid ? utoa(G.last_bg_pid) : (char*)"";
2480 break;
2481 case '?': /* exitcode */
2482 val = utoa(G.last_exitcode);
2483 break;
2484 case '#': /* argc */
2485 if (arg[1] != SPECIAL_VAR_SYMBOL)
2486 /* actually, it's a ${#var} */
2487 goto case_default;
2488 val = utoa(G.global_argc ? G.global_argc-1 : 0);
2489 break;
2490 case '*': 2479 case '*':
2491 case '@': 2480 case '@':
2492 i = 1; 2481 i = 1;
@@ -2581,27 +2570,35 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2581 break; 2570 break;
2582 } 2571 }
2583#endif 2572#endif
2584 default: /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */ 2573 default: { /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */
2585 case_default: { 2574 char *var;
2586 char *var = arg; 2575 char first_char;
2587 char exp_len; /* '#' if it's ${#var} */
2588 char exp_op; 2576 char exp_op;
2589 char exp_save = exp_save; /* for compiler */ 2577 char exp_save = exp_save; /* for compiler */
2590 char *exp_saveptr = exp_saveptr; /* points to expansion operator */ 2578 char *exp_saveptr; /* points to expansion operator */
2591 char *exp_word = exp_word; /* for compiler */ 2579 char *exp_word = exp_word; /* for compiler */
2592 2580
2581 var = arg;
2593 *p = '\0'; 2582 *p = '\0';
2594 arg[0] = first_ch & 0x7f; 2583 exp_saveptr = arg[1] ? strchr("%#:-=+?", arg[1]) : NULL;
2595 2584 first_char = arg[0] = first_ch & 0x7f;
2596 /* prepare for expansions */
2597 exp_op = 0; 2585 exp_op = 0;
2598 exp_len = var[0]; 2586
2599 if (exp_len == '#') { 2587 if (first_char == '#' && arg[1] && !exp_saveptr) {
2600 /* handle length expansion ${#var} */ 2588 /* handle length expansion ${#var} */
2601 var++; 2589 var++;
2590 exp_op = 'L';
2602 } else { 2591 } else {
2603 /* maybe handle parameter expansion */ 2592 /* maybe handle parameter expansion */
2604 exp_saveptr = var + strcspn(var, "%#:-=+?"); 2593 if (exp_saveptr /* if 2nd char is one of expansion operators */
2594 && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */
2595 ) {
2596 /* ${?:0}, ${#[:]%0} etc */
2597 exp_saveptr = var + 1;
2598 } else {
2599 /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
2600 exp_saveptr = var+1 + strcspn(var+1, "%#:-=+?");
2601 }
2605 exp_op = exp_save = *exp_saveptr; 2602 exp_op = exp_save = *exp_saveptr;
2606 if (exp_op) { 2603 if (exp_op) {
2607 exp_word = exp_saveptr + 1; 2604 exp_word = exp_saveptr + 1;
@@ -2616,7 +2613,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2616 } 2613 }
2617 } 2614 }
2618 *exp_saveptr = '\0'; 2615 *exp_saveptr = '\0';
2619 } 2616 } /* else: it's not an expansion op, but bare ${var} */
2620 } 2617 }
2621 2618
2622 /* lookup the variable in question */ 2619 /* lookup the variable in question */
@@ -2626,11 +2623,27 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2626 if (i < G.global_argc) 2623 if (i < G.global_argc)
2627 val = G.global_argv[i]; 2624 val = G.global_argv[i];
2628 /* else val remains NULL: $N with too big N */ 2625 /* else val remains NULL: $N with too big N */
2629 } else 2626 } else {
2630 val = get_local_var_value(var); 2627 switch (var[0]) {
2628 case '$': /* pid */
2629 val = utoa(G.root_pid);
2630 break;
2631 case '!': /* bg pid */
2632 val = G.last_bg_pid ? utoa(G.last_bg_pid) : (char*)"";
2633 break;
2634 case '?': /* exitcode */
2635 val = utoa(G.last_exitcode);
2636 break;
2637 case '#': /* argc */
2638 val = utoa(G.global_argc ? G.global_argc-1 : 0);
2639 break;
2640 default:
2641 val = get_local_var_value(var);
2642 }
2643 }
2631 2644
2632 /* handle any expansions */ 2645 /* handle any expansions */
2633 if (exp_len == '#') { 2646 if (exp_op == 'L') {
2634 debug_printf_expand("expand: length(%s)=", val); 2647 debug_printf_expand("expand: length(%s)=", val);
2635 val = utoa(val ? strlen(val) : 0); 2648 val = utoa(val ? strlen(val) : 0);
2636 debug_printf_expand("%s\n", val); 2649 debug_printf_expand("%s\n", val);
@@ -2761,7 +2774,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
2761 } 2774 }
2762 } 2775 }
2763 } 2776 }
2764 } 2777 } /* one of "-=+?" */
2765 2778
2766 *exp_saveptr = exp_save; 2779 *exp_saveptr = exp_save;
2767 } /* if (exp_op) */ 2780 } /* if (exp_op) */
@@ -6031,7 +6044,7 @@ static int handle_dollar(o_string *as_string,
6031 * or even ${?+subst} - operator acting on a special variable, 6044 * or even ${?+subst} - operator acting on a special variable,
6032 * or the beginning of variable name. 6045 * or the beginning of variable name.
6033 */ 6046 */
6034 if (!strchr("$!?#*@_", ch) && !isalnum(ch)) { /* not one of those */ 6047 if (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) { /* not one of those */
6035 bad_dollar_syntax: 6048 bad_dollar_syntax:
6036 syntax_error_unterm_str("${name}"); 6049 syntax_error_unterm_str("${name}");
6037 debug_printf_parse("handle_dollar return 1: unterminated ${name}\n"); 6050 debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");