summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-10 16:19:39 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-10 16:19:39 +0000
commit76d50418b37e59c4b474137ffa2eba4d3f7dbbb8 (patch)
tree111c924c34b6b81669ef8fc609584ea6506dcb67 /shell/hush.c
parent3fe4f986a055d0bc942dcda0c2fea3ef68e341d7 (diff)
downloadbusybox-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.c58
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: */
517static int setup_redirects(struct child_prog *prog, int squirrel[]); 517static int setup_redirects(struct child_prog *prog, int squirrel[]);
518static int run_list(struct pipe *pi); 518static int run_list(struct pipe *pi);
519static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN; 519#if BB_MMU
520static 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
523static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN;
524static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN;
521static int run_pipe(struct pipe *pi); 525static int run_pipe(struct pipe *pi);
522/* extended glob support: */ 526/* extended glob support: */
523static char **globhack(const char *src, char **strings); 527static 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 */
628static 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 */
623static int builtin_cd(char **argv); 639static int builtin_cd(char **argv);
624static int builtin_echo(char **argv); 640static 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) */
1424static void pseudo_exec_argv(char **argv) 1445static 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 */
1488static void pseudo_exec(struct child_prog *child) 1514static 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");