klibc-bot for Herbert Xu
2020-Mar-28 21:49 UTC
[klibc] [klibc:update-dash] dash: eval: avoid leaking memory associated with redirections
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; }
Reasonably Related Threads
- [klibc:update-dash] eval: Return status in eval functions
- [klibc:update-dash] dash: eval: Return status in eval functions
- [klibc:update-dash] eval: Restore input files in evalcommand
- [klibc:update-dash] dash: eval: Restore input files in evalcommand
- [klibc:update-dash] dash: eval: Replace with listsetvar with mklocal/setvareq