aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2018-12-14 13:44:14 +0800
committerBen Hutchings <ben@decadent.org.uk>2020-03-28 21:42:55 +0000
commit2993257551260450b6471d0650bec6e859cafed4 (patch)
tree9692fb6f3661b7dd40b775aa9fa64b6e9bb86030
parent5c65fe97c9c00feb5ed10598dcd51ef7399be7ff (diff)
downloadklibc-2993257551260450b6471d0650bec6e859cafed4.tar.gz
[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@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@gondor.apana.org.au> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--usr/dash/eval.c16
1 files changed, 6 insertions, 10 deletions
diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 5074aa94344c8..bba0e7f88ea4b 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;
}