aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-16 14:35:57 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-16 14:35:57 +0000
commitccce59d5622dd32101e396580f7a148dfb3cb2d8 (patch)
tree86ac723e88dd0756a808d3b8e7981c0acd45fe56 /shell
parent32d8423e63258b8a0d0a30b8c52397d02489cad4 (diff)
downloadbusybox-w32-ccce59d5622dd32101e396580f7a148dfb3cb2d8.tar.gz
busybox-w32-ccce59d5622dd32101e396580f7a148dfb3cb2d8.tar.bz2
busybox-w32-ccce59d5622dd32101e396580f7a148dfb3cb2d8.zip
hush: fixing fallout from last big glob fix:
fix segfault; identify where we leak memory function old new delta expand_strvec_to_strvec 353 336 -17
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c160
1 files changed, 80 insertions, 80 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 7c5a44274..0e1976443 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -148,6 +148,11 @@ static const char *indenter(int i)
148 * Leak hunting. Use hush_leaktool.sh for post-processing. 148 * Leak hunting. Use hush_leaktool.sh for post-processing.
149 */ 149 */
150#ifdef FOR_HUSH_LEAKTOOL 150#ifdef FOR_HUSH_LEAKTOOL
151/* suppress "warning: no previous prototype..." */
152void *xxmalloc(int lineno, size_t size);
153void *xxrealloc(int lineno, void *ptr, size_t size);
154char *xxstrdup(int lineno, const char *str);
155void xxfree(void *ptr);
151void *xxmalloc(int lineno, size_t size) 156void *xxmalloc(int lineno, size_t size)
152{ 157{
153 void *ptr = xmalloc((size + 0xff) & ~0xff); 158 void *ptr = xmalloc((size + 0xff) & ~0xff);
@@ -2474,72 +2479,6 @@ static int run_and_free_list(struct pipe *pi)
2474 return rcode; 2479 return rcode;
2475} 2480}
2476 2481
2477/* Remove non-backslashed backslashes and add to "strings" vector.
2478 * XXX broken if the last character is '\\', check that before calling.
2479 */
2480static char **add_unq_string_to_strings(char **strings, const char *src)
2481{
2482 int cnt;
2483 const char *s;
2484 char *v, *dest;
2485
2486 for (cnt = 1, s = src; s && *s; s++) {
2487 if (*s == '\\') s++;
2488 cnt++;
2489 }
2490 v = dest = xmalloc(cnt);
2491 for (s = src; s && *s; s++, dest++) {
2492 if (*s == '\\') s++;
2493 *dest = *s;
2494 }
2495 *dest = '\0';
2496
2497 return add_string_to_strings(strings, v);
2498}
2499
2500/* XXX broken if the last character is '\\', check that before calling */
2501static int glob_needed(const char *s)
2502{
2503 for (; *s; s++) {
2504 if (*s == '\\')
2505 s++;
2506 if (strchr("*[?", *s))
2507 return 1;
2508 }
2509 return 0;
2510}
2511
2512static int xglob(char ***pglob, const char *pattern)
2513{
2514 if (glob_needed(pattern)) {
2515 glob_t globdata;
2516 int gr;
2517
2518 memset(&globdata, 0, sizeof(globdata));
2519 gr = glob(pattern, 0, NULL, &globdata);
2520 debug_printf("glob returned %d\n", gr);
2521 if (gr == GLOB_NOSPACE)
2522 bb_error_msg_and_die("out of memory during glob");
2523 if (gr == GLOB_NOMATCH) {
2524 globfree(&globdata);
2525 goto literal;
2526 }
2527 if (gr != 0) { /* GLOB_ABORTED ? */
2528 bb_error_msg("glob(3) error %d", gr);
2529 }
2530 if (globdata.gl_pathv && globdata.gl_pathv[0])
2531 *pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv);
2532 globfree(&globdata);
2533 return gr;
2534 }
2535
2536 literal:
2537 /* quote removal, or more accurately, backslash removal */
2538 *pglob = add_unq_string_to_strings(*pglob, pattern);
2539 debug_print_strings("after xglob", *pglob);
2540 return 0;
2541}
2542
2543/* expand_strvec_to_strvec() takes a list of strings, expands 2482/* expand_strvec_to_strvec() takes a list of strings, expands
2544 * all variable references within and returns a pointer to 2483 * all variable references within and returns a pointer to
2545 * a list of expanded strings, possibly with larger number 2484 * a list of expanded strings, possibly with larger number
@@ -2596,7 +2535,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2596 o_debug_list("expand_vars_to_list[0]", output, n); 2535 o_debug_list("expand_vars_to_list[0]", output, n);
2597 2536
2598 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { 2537 while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
2538#if ENABLE_HUSH_TICK
2599 o_string subst_result = NULL_O_STRING; 2539 o_string subst_result = NULL_O_STRING;
2540#endif
2600 2541
2601 o_addQstr(output, arg, p - arg); 2542 o_addQstr(output, arg, p - arg);
2602 o_debug_list("expand_vars_to_list[1]", output, n); 2543 o_debug_list("expand_vars_to_list[1]", output, n);
@@ -2661,10 +2602,12 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2661 } 2602 }
2662 } 2603 }
2663 break; 2604 break;
2605#if ENABLE_HUSH_TICK
2664 case '`': { 2606 case '`': {
2665 struct in_str input; 2607 struct in_str input;
2666 *p = '\0'; 2608 *p = '\0';
2667 arg++; 2609 arg++;
2610//TODO: can we just stuff it into "output" directly?
2668 //bb_error_msg("SUBST '%s' first_ch %x", arg, first_ch); 2611 //bb_error_msg("SUBST '%s' first_ch %x", arg, first_ch);
2669 setup_string_in_str(&input, arg); 2612 setup_string_in_str(&input, arg);
2670 process_command_subs(&subst_result, &input, NULL); 2613 process_command_subs(&subst_result, &input, NULL);
@@ -2672,6 +2615,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2672 val = subst_result.data; 2615 val = subst_result.data;
2673 goto store_val; 2616 goto store_val;
2674 } 2617 }
2618#endif
2675 default: 2619 default:
2676 *p = '\0'; 2620 *p = '\0';
2677 arg[0] = first_ch & 0x7f; 2621 arg[0] = first_ch & 0x7f;
@@ -2696,7 +2640,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2696 o_addQstr(output, val, strlen(val)); 2640 o_addQstr(output, val, strlen(val));
2697 } 2641 }
2698 2642
2643#if ENABLE_HUSH_TICK
2699 o_free(&subst_result); 2644 o_free(&subst_result);
2645#endif
2700 arg = ++p; 2646 arg = ++p;
2701 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ 2647 } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
2702 2648
@@ -2731,33 +2677,87 @@ static char **expand_variables(char **argv, char or_mask)
2731 2677
2732 /* output.data (malloced in one block) gets returned in "list" */ 2678 /* output.data (malloced in one block) gets returned in "list" */
2733 list = o_finalize_list(&output, n); 2679 list = o_finalize_list(&output, n);
2680 return list;
2681}
2734 2682
2735#ifdef DEBUG_EXPAND 2683/* Remove non-backslashed backslashes and add to "strings" vector.
2736 { 2684 * XXX broken if the last character is '\\', check that before calling.
2737 int m = 0; 2685 */
2738 while (m <= n) { 2686static char **add_unq_string_to_strings(char **strings, const char *src)
2739 debug_printf_expand("list[%d]=%p '%s'\n", m, list[m], list[m]); 2687{
2740 m++; 2688 int cnt;
2689 const char *s;
2690 char *v, *dest;
2691
2692 for (cnt = 1, s = src; s && *s; s++) {
2693 if (*s == '\\') s++;
2694 cnt++;
2695 }
2696 v = dest = xmalloc(cnt);
2697 for (s = src; s && *s; s++, dest++) {
2698 if (*s == '\\') s++;
2699 *dest = *s;
2700 }
2701 *dest = '\0';
2702
2703 return add_string_to_strings(strings, v);
2704}
2705
2706/* XXX broken if the last character is '\\', check that before calling */
2707static int glob_needed(const char *s)
2708{
2709 for (; *s; s++) {
2710 if (*s == '\\')
2711 s++;
2712 if (strchr("*[?", *s))
2713 return 1;
2714 }
2715 return 0;
2716}
2717
2718static void xglob(char ***pglob, const char *pattern)
2719{
2720 if (glob_needed(pattern)) {
2721 glob_t globdata;
2722 int gr;
2723
2724 memset(&globdata, 0, sizeof(globdata));
2725 gr = glob(pattern, 0, NULL, &globdata);
2726 debug_printf("glob returned %d\n", gr);
2727 if (gr == GLOB_NOSPACE)
2728 bb_error_msg_and_die("out of memory during glob");
2729 if (gr == GLOB_NOMATCH) {
2730 globfree(&globdata);
2731 goto literal;
2741 } 2732 }
2733 if (gr != 0) { /* GLOB_ABORTED ? */
2734 bb_error_msg("glob(3) error %d on '%s'", gr, pattern);
2735//TODO: testcase for bad glob pattern behavior
2736 }
2737 if (globdata.gl_pathv && globdata.gl_pathv[0])
2738 *pglob = add_strings_to_strings(1, *pglob, globdata.gl_pathv);
2739 globfree(&globdata);
2740 return;
2742 } 2741 }
2743#endif 2742
2744 return list; 2743 literal:
2744 /* quote removal, or more accurately, backslash removal */
2745 *pglob = add_unq_string_to_strings(*pglob, pattern);
2746 debug_print_strings("after xglob", *pglob);
2745} 2747}
2746 2748
2749//LEAK is here: callers expect result to be free()able, but we
2750//actually require free_strings(). free() leaks strings.
2747static char **expand_strvec_to_strvec(char **argv) 2751static char **expand_strvec_to_strvec(char **argv)
2748{ 2752{
2749 char **exp; 2753 char **exp;
2750 char **res = NULL; 2754 char **res = xzalloc(sizeof(res[0]));
2751 2755
2752 debug_print_strings("expand_strvec_to_strvec: pre expand", argv); 2756 debug_print_strings("expand_strvec_to_strvec: pre expand", argv);
2753 exp = argv = expand_variables(argv, 0); 2757 exp = argv = expand_variables(argv, 0);
2754 debug_print_strings("expand_strvec_to_strvec: post expand", argv); 2758 debug_print_strings("expand_strvec_to_strvec: post expand", argv);
2755 while (*argv) { 2759 while (*argv) {
2756 int r = xglob(&res, *argv); 2760 xglob(&res, *argv++);
2757 if (r)
2758 bb_error_msg("xglob returned %d on '%s'", r, *argv);
2759//TODO: testcase for bad glob pattern behavior
2760 argv++;
2761 } 2761 }
2762 free(exp); 2762 free(exp);
2763 debug_print_strings("expand_strvec_to_strvec: res", res); 2763 debug_print_strings("expand_strvec_to_strvec: res", res);