diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-10 16:19:39 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-10 16:19:39 +0000 |
commit | 76d50418b37e59c4b474137ffa2eba4d3f7dbbb8 (patch) | |
tree | 111c924c34b6b81669ef8fc609584ea6506dcb67 /shell/hush.c | |
parent | 3fe4f986a055d0bc942dcda0c2fea3ef68e341d7 (diff) | |
download | busybox-w32-76d50418b37e59c4b474137ffa2eba4d3f7dbbb8.tar.gz busybox-w32-76d50418b37e59c4b474137ffa2eba4d3f7dbbb8.tar.bz2 busybox-w32-76d50418b37e59c4b474137ffa2eba4d3f7dbbb8.zip |
hush: fix a memory leak in NOMMU case
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/shell/hush.c b/shell/hush.c index b80468f58..d7b9c39ec 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -516,8 +516,12 @@ static int free_pipe(struct pipe *pi, int indent); | |||
516 | /* really run the final data structures: */ | 516 | /* really run the final data structures: */ |
517 | static int setup_redirects(struct child_prog *prog, int squirrel[]); | 517 | static int setup_redirects(struct child_prog *prog, int squirrel[]); |
518 | static int run_list(struct pipe *pi); | 518 | static int run_list(struct pipe *pi); |
519 | static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN; | 519 | #if BB_MMU |
520 | static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN; | 520 | #define pseudo_exec_argv(ptrs2free, argv) pseudo_exec_argv(argv) |
521 | #define pseudo_exec(ptrs2free, child) pseudo_exec(child) | ||
522 | #endif | ||
523 | static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN; | ||
524 | static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN; | ||
521 | static int run_pipe(struct pipe *pi); | 525 | static int run_pipe(struct pipe *pi); |
522 | /* extended glob support: */ | 526 | /* extended glob support: */ |
523 | static char **globhack(const char *src, char **strings); | 527 | static char **globhack(const char *src, char **strings); |
@@ -619,6 +623,18 @@ static void free_strings(char **strings) | |||
619 | } | 623 | } |
620 | 624 | ||
621 | 625 | ||
626 | #if !BB_MMU | ||
627 | #define EXTRA_PTRS 5 /* 1 for NULL, 1 for args, 3 for paranoid reasons */ | ||
628 | static char **alloc_ptrs(char **argv) | ||
629 | { | ||
630 | char **v = argv; | ||
631 | while (*v) | ||
632 | v++; | ||
633 | return xzalloc((v - argv + EXTRA_PTRS) * sizeof(v[0])); | ||
634 | } | ||
635 | #endif | ||
636 | |||
637 | |||
622 | /* Function prototypes for builtins */ | 638 | /* Function prototypes for builtins */ |
623 | static int builtin_cd(char **argv); | 639 | static int builtin_cd(char **argv); |
624 | static int builtin_echo(char **argv); | 640 | static int builtin_echo(char **argv); |
@@ -891,9 +907,14 @@ static int builtin_exec(char **argv) | |||
891 | { | 907 | { |
892 | if (argv[1] == NULL) | 908 | if (argv[1] == NULL) |
893 | return EXIT_SUCCESS; /* bash does this */ | 909 | return EXIT_SUCCESS; /* bash does this */ |
910 | { | ||
911 | #if !BB_MMU | ||
912 | char **ptrs2free = alloc_ptrs(argv); | ||
913 | #endif | ||
894 | // FIXME: if exec fails, bash does NOT exit! We do... | 914 | // FIXME: if exec fails, bash does NOT exit! We do... |
895 | pseudo_exec_argv(argv + 1); | 915 | pseudo_exec_argv(ptrs2free, argv + 1); |
896 | /* never returns */ | 916 | /* never returns */ |
917 | } | ||
897 | } | 918 | } |
898 | 919 | ||
899 | /* built-in 'exit' handler */ | 920 | /* built-in 'exit' handler */ |
@@ -1421,7 +1442,7 @@ static void restore_redirects(int squirrel[]) | |||
1421 | * XXX no exit() here. If you don't exec, use _exit instead. | 1442 | * XXX no exit() here. If you don't exec, use _exit instead. |
1422 | * The at_exit handlers apparently confuse the calling process, | 1443 | * The at_exit handlers apparently confuse the calling process, |
1423 | * in particular stdin handling. Not sure why? -- because of vfork! (vda) */ | 1444 | * in particular stdin handling. Not sure why? -- because of vfork! (vda) */ |
1424 | static void pseudo_exec_argv(char **argv) | 1445 | static void pseudo_exec_argv(char **ptrs2free, char **argv) |
1425 | { | 1446 | { |
1426 | int i, rcode; | 1447 | int i, rcode; |
1427 | char *p; | 1448 | char *p; |
@@ -1430,8 +1451,10 @@ static void pseudo_exec_argv(char **argv) | |||
1430 | for (i = 0; is_assignment(argv[i]); i++) { | 1451 | for (i = 0; is_assignment(argv[i]); i++) { |
1431 | debug_printf_exec("pid %d environment modification: %s\n", | 1452 | debug_printf_exec("pid %d environment modification: %s\n", |
1432 | getpid(), argv[i]); | 1453 | getpid(), argv[i]); |
1433 | // FIXME: vfork case?? | ||
1434 | p = expand_string_to_string(argv[i]); | 1454 | p = expand_string_to_string(argv[i]); |
1455 | #if !BB_MMU | ||
1456 | *ptrs2free++ = p; | ||
1457 | #endif | ||
1435 | putenv(p); | 1458 | putenv(p); |
1436 | } | 1459 | } |
1437 | argv += i; | 1460 | argv += i; |
@@ -1442,6 +1465,9 @@ static void pseudo_exec_argv(char **argv) | |||
1442 | _exit(EXIT_SUCCESS); | 1465 | _exit(EXIT_SUCCESS); |
1443 | 1466 | ||
1444 | argv = expand_strvec_to_strvec(argv); | 1467 | argv = expand_strvec_to_strvec(argv); |
1468 | #if !BB_MMU | ||
1469 | *ptrs2free++ = (char*) argv; | ||
1470 | #endif | ||
1445 | 1471 | ||
1446 | /* | 1472 | /* |
1447 | * Check if the command matches any of the builtins. | 1473 | * Check if the command matches any of the builtins. |
@@ -1485,13 +1511,13 @@ static void pseudo_exec_argv(char **argv) | |||
1485 | 1511 | ||
1486 | /* Called after [v]fork() in run_pipe() | 1512 | /* Called after [v]fork() in run_pipe() |
1487 | */ | 1513 | */ |
1488 | static void pseudo_exec(struct child_prog *child) | 1514 | static void pseudo_exec(char **ptrs2free, struct child_prog *child) |
1489 | { | 1515 | { |
1490 | // FIXME: buggy wrt NOMMU! Must not modify any global data | 1516 | // FIXME: buggy wrt NOMMU! Must not modify any global data |
1491 | // until it does exec/_exit, but currently it does | 1517 | // until it does exec/_exit, but currently it does |
1492 | // (puts malloc'ed stuff into environment) | 1518 | // (puts malloc'ed stuff into environment) |
1493 | if (child->argv) | 1519 | if (child->argv) |
1494 | pseudo_exec_argv(child->argv); | 1520 | pseudo_exec_argv(ptrs2free, child->argv); |
1495 | 1521 | ||
1496 | if (child->group) { | 1522 | if (child->group) { |
1497 | #if !BB_MMU | 1523 | #if !BB_MMU |
@@ -1880,10 +1906,16 @@ static int run_pipe(struct pipe *pi) | |||
1880 | nextin = 0; | 1906 | nextin = 0; |
1881 | 1907 | ||
1882 | for (i = 0; i < pi->num_progs; i++) { | 1908 | for (i = 0; i < pi->num_progs; i++) { |
1909 | #if !BB_MMU | ||
1910 | char **ptrs2free = NULL; | ||
1911 | #endif | ||
1883 | child = &(pi->progs[i]); | 1912 | child = &(pi->progs[i]); |
1884 | if (child->argv) | 1913 | if (child->argv) { |
1885 | debug_printf_exec(": pipe member '%s' '%s'...\n", child->argv[0], child->argv[1]); | 1914 | debug_printf_exec(": pipe member '%s' '%s'...\n", child->argv[0], child->argv[1]); |
1886 | else | 1915 | #if !BB_MMU |
1916 | ptrs2free = alloc_ptrs(child->argv); | ||
1917 | #endif | ||
1918 | } else | ||
1887 | debug_printf_exec(": pipe member with no argv\n"); | 1919 | debug_printf_exec(": pipe member with no argv\n"); |
1888 | 1920 | ||
1889 | /* pipes are inserted between pairs of commands */ | 1921 | /* pipes are inserted between pairs of commands */ |
@@ -1925,9 +1957,11 @@ static int run_pipe(struct pipe *pi) | |||
1925 | set_jobctrl_sighandler(SIG_DFL); | 1957 | set_jobctrl_sighandler(SIG_DFL); |
1926 | set_misc_sighandler(SIG_DFL); | 1958 | set_misc_sighandler(SIG_DFL); |
1927 | signal(SIGCHLD, SIG_DFL); | 1959 | signal(SIGCHLD, SIG_DFL); |
1928 | pseudo_exec(child); /* does not return */ | 1960 | pseudo_exec(ptrs2free, child); /* does not return */ |
1929 | } | 1961 | } |
1930 | 1962 | #if !BB_MMU | |
1963 | free_strings(ptrs2free); | ||
1964 | #endif | ||
1931 | if (child->pid < 0) { /* [v]fork failed */ | 1965 | if (child->pid < 0) { /* [v]fork failed */ |
1932 | /* Clearly indicate, was it fork or vfork */ | 1966 | /* Clearly indicate, was it fork or vfork */ |
1933 | bb_perror_msg(BB_MMU ? "fork" : "vfork"); | 1967 | bb_perror_msg(BB_MMU ? "fork" : "vfork"); |