diff mbox series

eval: avoid leaking memory associated with redirections

Message ID 5bf6aabc.5IrNAw91xx5SQEm6%rmy@frippery.org (mailing list archive)
State Superseded
Delegated to: Herbert Xu
Headers show
Series eval: avoid leaking memory associated with redirections | expand

Commit Message

Ron Yorston Nov. 22, 2018, 1:10 p.m. UTC
The following constructs result in ever-increasing memory usage:

   while true; do { true; } </dev/null; done
   while true; do ( true; ) </dev/null; done

For comparison, bash displays static memory usage in both cases.

This issue was reported for BusyBox ash which is derived from dash:

   https://bugs.busybox.net/show_bug.cgi?id=7748

Signed-off-by: Ron Yorston <rmy@frippery.org>
---
 src/eval.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff mbox series

Patch

diff --git a/src/eval.c b/src/eval.c
index 546ee1b..9f117ea 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -202,6 +202,7 @@  evaltree(union node *n, int flags)
 	int (*evalfn)(union node *, int);
 	unsigned isor;
 	int status = 0;
+	struct stackmark smark;
 	if (n == NULL) {
 		TRACE(("evaltree(NULL) called\n"));
 		goto out;
@@ -227,6 +228,7 @@  evaltree(union node *n, int flags)
 		status = !evaltree(n->nnot.com, EV_TESTED);
 		goto setstatus;
 	case NREDIR:
+		setstackmark(&smark);
 		errlinno = lineno = n->nredir.linno;
 		if (funcline)
 			lineno -= funcline - 1;
@@ -236,6 +238,7 @@  evaltree(union node *n, int flags)
 			 evaltree(n->nredir.n, flags & EV_TESTED);
 		if (n->nredir.redirect)
 			popredir(0);
+		popstackmark(&smark);
 		goto setstatus;
 	case NCMD:
 #ifdef notyet
@@ -476,11 +479,13 @@  evalsubshell(union node *n, int flags)
 	struct job *jp;
 	int backgnd = (n->type == NBACKGND);
 	int status;
+	struct stackmark smark;
 
 	errlinno = lineno = n->nredir.linno;
 	if (funcline)
 		lineno -= funcline - 1;
 
+	setstackmark(&smark);
 	expredir(n->nredir.redirect);
 	if (!backgnd && flags & EV_EXIT && !have_traps())
 		goto nofork;
@@ -500,6 +505,7 @@  nofork:
 	if (! backgnd)
 		status = waitforjob(jp);
 	INTON;
+	popstackmark(&smark);
 	return status;
 }