[klibc] [klibc:update-dash] dash: eval: avoid leaking memory associated with redirections

klibc-bot for Herbert Xu herbert at gondor.apana.org.au
Sat Mar 28 14:49:38 PDT 2020


Commit-ID:  2993257551260450b6471d0650bec6e859cafed4
Gitweb:     http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=2993257551260450b6471d0650bec6e859cafed4
Author:     Herbert Xu <herbert at gondor.apana.org.au>
AuthorDate: Fri, 14 Dec 2018 13:44:14 +0800
Committer:  Ben Hutchings <ben at decadent.org.uk>
CommitDate: Sat, 28 Mar 2020 21:42:55 +0000

[klibc] dash: eval: avoid leaking memory associated with redirections

[ dash commit 2bc6caace3b08024955ed57fc993d91067f883a1 ]

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 at frippery.org>

I have simplified evaltree so that it simply sets the stack mark
unconditionally.  This allows us to remove the stack marks in the
functions called by evaltree.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben at decadent.org.uk>

---
 usr/dash/eval.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 5074aa94..bba0e7f8 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -200,8 +200,12 @@ evaltree(union node *n, int flags)
 {
 	int checkexit = 0;
 	int (*evalfn)(union node *, int);
+	struct stackmark smark;
 	unsigned isor;
 	int status = 0;
+
+	setstackmark(&smark);
+
 	if (n == NULL) {
 		TRACE(("evaltree(NULL) called\n"));
 		goto out;
@@ -317,6 +321,8 @@ exexit:
 		exraise(EXEXIT);
 	}
 
+	popstackmark(&smark);
+
 	return exitstatus;
 }
 
@@ -396,14 +402,12 @@ evalfor(union node *n, int flags)
 	struct arglist arglist;
 	union node *argp;
 	struct strlist *sp;
-	struct stackmark smark;
 	int status;
 
 	errlinno = lineno = n->nfor.linno;
 	if (funcline)
 		lineno -= funcline - 1;
 
-	setstackmark(&smark);
 	arglist.lastp = &arglist.list;
 	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
@@ -420,7 +424,6 @@ evalfor(union node *n, int flags)
 			break;
 	}
 	loopnest--;
-	popstackmark(&smark);
 
 	return status;
 }
@@ -433,14 +436,12 @@ evalcase(union node *n, int flags)
 	union node *cp;
 	union node *patp;
 	struct arglist arglist;
-	struct stackmark smark;
 	int status = 0;
 
 	errlinno = lineno = n->ncase.linno;
 	if (funcline)
 		lineno -= funcline - 1;
 
-	setstackmark(&smark);
 	arglist.lastp = &arglist.list;
 	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
 	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
@@ -459,8 +460,6 @@ evalcase(union node *n, int flags)
 		}
 	}
 out:
-	popstackmark(&smark);
-
 	return status;
 }
 
@@ -717,7 +716,6 @@ evalcommand(union node *cmd, int flags)
 	struct localvar_list *localvar_stop;
 	struct parsefile *file_stop;
 	struct redirtab *redir_stop;
-	struct stackmark smark;
 	union node *argp;
 	struct arglist arglist;
 	struct arglist varlist;
@@ -746,7 +744,6 @@ evalcommand(union node *cmd, int flags)
 
 	/* First expand the arguments. */
 	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
-	setstackmark(&smark);
 	file_stop = parsefile;
 	back_exitstatus = 0;
 
@@ -925,7 +922,6 @@ out:
 		 * However I implemented that within libedit itself.
 		 */
 		setvar("_", lastarg, 0);
-	popstackmark(&smark);
 
 	return status;
 }


More information about the klibc mailing list