svn commit: trunk/busybox/shell

vda at busybox.net vda at busybox.net
Tue Jun 10 16:19:43 UTC 2008


Author: vda
Date: 2008-06-10 09:19:39 -0700 (Tue, 10 Jun 2008)
New Revision: 22281

Log:
hush: fix a memory leak in NOMMU case



Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2008-06-10 11:38:53 UTC (rev 22280)
+++ trunk/busybox/shell/hush.c	2008-06-10 16:19:39 UTC (rev 22281)
@@ -516,8 +516,12 @@
 /*  really run the final data structures: */
 static int setup_redirects(struct child_prog *prog, int squirrel[]);
 static int run_list(struct pipe *pi);
-static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN;
-static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN;
+#if BB_MMU
+#define pseudo_exec_argv(ptrs2free, argv)  pseudo_exec_argv(argv)
+#define      pseudo_exec(ptrs2free, child)      pseudo_exec(child)
+#endif
+static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN;
+static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN;
 static int run_pipe(struct pipe *pi);
 /*   extended glob support: */
 static char **globhack(const char *src, char **strings);
@@ -619,6 +623,18 @@
 }
 
 
+#if !BB_MMU
+#define EXTRA_PTRS 5 /* 1 for NULL, 1 for args, 3 for paranoid reasons */
+static char **alloc_ptrs(char **argv)
+{
+	char **v = argv;
+	while (*v)
+		v++;
+	return xzalloc((v - argv + EXTRA_PTRS) * sizeof(v[0]));
+}
+#endif
+
+
 /* Function prototypes for builtins */
 static int builtin_cd(char **argv);
 static int builtin_echo(char **argv);
@@ -891,9 +907,14 @@
 {
 	if (argv[1] == NULL)
 		return EXIT_SUCCESS; /* bash does this */
+	{
+#if !BB_MMU
+		char **ptrs2free = alloc_ptrs(argv);
+#endif
 // FIXME: if exec fails, bash does NOT exit! We do...
-	pseudo_exec_argv(argv + 1);
-	/* never returns */
+		pseudo_exec_argv(ptrs2free, argv + 1);
+		/* never returns */
+	}
 }
 
 /* built-in 'exit' handler */
@@ -1421,7 +1442,7 @@
  * XXX no exit() here.  If you don't exec, use _exit instead.
  * The at_exit handlers apparently confuse the calling process,
  * in particular stdin handling.  Not sure why? -- because of vfork! (vda) */
-static void pseudo_exec_argv(char **argv)
+static void pseudo_exec_argv(char **ptrs2free, char **argv)
 {
 	int i, rcode;
 	char *p;
@@ -1430,8 +1451,10 @@
 	for (i = 0; is_assignment(argv[i]); i++) {
 		debug_printf_exec("pid %d environment modification: %s\n",
 				getpid(), argv[i]);
-// FIXME: vfork case??
 		p = expand_string_to_string(argv[i]);
+#if !BB_MMU
+		*ptrs2free++ = p;
+#endif
 		putenv(p);
 	}
 	argv += i;
@@ -1442,6 +1465,9 @@
 		_exit(EXIT_SUCCESS);
 
 	argv = expand_strvec_to_strvec(argv);
+#if !BB_MMU
+	*ptrs2free++ = (char*) argv;
+#endif
 
 	/*
 	 * Check if the command matches any of the builtins.
@@ -1485,13 +1511,13 @@
 
 /* Called after [v]fork() in run_pipe()
  */
-static void pseudo_exec(struct child_prog *child)
+static void pseudo_exec(char **ptrs2free, struct child_prog *child)
 {
 // FIXME: buggy wrt NOMMU! Must not modify any global data
 // until it does exec/_exit, but currently it does
 // (puts malloc'ed stuff into environment)
 	if (child->argv)
-		pseudo_exec_argv(child->argv);
+		pseudo_exec_argv(ptrs2free, child->argv);
 
 	if (child->group) {
 #if !BB_MMU
@@ -1880,10 +1906,16 @@
 	nextin = 0;
 
 	for (i = 0; i < pi->num_progs; i++) {
+#if !BB_MMU
+		char **ptrs2free = NULL;
+#endif
 		child = &(pi->progs[i]);
-		if (child->argv)
+		if (child->argv) {
 			debug_printf_exec(": pipe member '%s' '%s'...\n", child->argv[0], child->argv[1]);
-		else
+#if !BB_MMU
+			ptrs2free = alloc_ptrs(child->argv);
+#endif
+		} else
 			debug_printf_exec(": pipe member with no argv\n");
 
 		/* pipes are inserted between pairs of commands */
@@ -1925,9 +1957,11 @@
 			set_jobctrl_sighandler(SIG_DFL);
 			set_misc_sighandler(SIG_DFL);
 			signal(SIGCHLD, SIG_DFL);
-			pseudo_exec(child); /* does not return */
+			pseudo_exec(ptrs2free, child); /* does not return */
 		}
-
+#if !BB_MMU
+		free_strings(ptrs2free);
+#endif
 		if (child->pid < 0) { /* [v]fork failed */
 			/* Clearly indicate, was it fork or vfork */
 			bb_perror_msg(BB_MMU ? "fork" : "vfork");




More information about the busybox-cvs mailing list