diff options
author | Ron Yorston <rmy@pobox.com> | 2019-02-25 08:29:38 +0000 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-02-25 18:57:59 +0100 |
commit | f55161ad27b641f6e09c6c498fa8a2bdb1112b0a (patch) | |
tree | 8ea2b3a9922ffd0b3fc8b47b7a997130e80bb7ce /shell | |
parent | e563f9e851c78f5c13cb9828ddb11ca981fd6331 (diff) | |
download | busybox-w32-f55161ad27b641f6e09c6c498fa8a2bdb1112b0a.tar.gz busybox-w32-f55161ad27b641f6e09c6c498fa8a2bdb1112b0a.tar.bz2 busybox-w32-f55161ad27b641f6e09c6c498fa8a2bdb1112b0a.zip |
ash: eval: avoid leaking memory associated with redirections. Closes 7748
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 has been fixed in dash by commit 2bc6caa. The maintainer
writes:
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.
Closes BusyBox bug 7748.
function old new delta
evaltree 606 632 +26
evalcommand 1724 1696 -28
evalcase 382 351 -31
evalfor 230 196 -34
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 26/-93) Total: -67 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 14 |
1 files changed, 4 insertions, 10 deletions
diff --git a/shell/ash.c b/shell/ash.c index a284b084d..a4394d756 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9034,8 +9034,11 @@ evaltree(union node *n, int flags) | |||
9034 | { | 9034 | { |
9035 | int checkexit = 0; | 9035 | int checkexit = 0; |
9036 | int (*evalfn)(union node *, int); | 9036 | int (*evalfn)(union node *, int); |
9037 | struct stackmark smark; | ||
9037 | int status = 0; | 9038 | int status = 0; |
9038 | 9039 | ||
9040 | setstackmark(&smark); | ||
9041 | |||
9039 | if (n == NULL) { | 9042 | if (n == NULL) { |
9040 | TRACE(("evaltree(NULL) called\n")); | 9043 | TRACE(("evaltree(NULL) called\n")); |
9041 | goto out; | 9044 | goto out; |
@@ -9149,6 +9152,7 @@ evaltree(union node *n, int flags) | |||
9149 | if (flags & EV_EXIT) | 9152 | if (flags & EV_EXIT) |
9150 | raise_exception(EXEXIT); | 9153 | raise_exception(EXEXIT); |
9151 | 9154 | ||
9155 | popstackmark(&smark); | ||
9152 | TRACE(("leaving evaltree (no interrupts)\n")); | 9156 | TRACE(("leaving evaltree (no interrupts)\n")); |
9153 | return exitstatus; | 9157 | return exitstatus; |
9154 | } | 9158 | } |
@@ -9209,14 +9213,12 @@ evalfor(union node *n, int flags) | |||
9209 | struct arglist arglist; | 9213 | struct arglist arglist; |
9210 | union node *argp; | 9214 | union node *argp; |
9211 | struct strlist *sp; | 9215 | struct strlist *sp; |
9212 | struct stackmark smark; | ||
9213 | int status = 0; | 9216 | int status = 0; |
9214 | 9217 | ||
9215 | errlinno = lineno = n->ncase.linno; | 9218 | errlinno = lineno = n->ncase.linno; |
9216 | if (funcline) | 9219 | if (funcline) |
9217 | lineno -= funcline - 1; | 9220 | lineno -= funcline - 1; |
9218 | 9221 | ||
9219 | setstackmark(&smark); | ||
9220 | arglist.list = NULL; | 9222 | arglist.list = NULL; |
9221 | arglist.lastp = &arglist.list; | 9223 | arglist.lastp = &arglist.list; |
9222 | for (argp = n->nfor.args; argp; argp = argp->narg.next) { | 9224 | for (argp = n->nfor.args; argp; argp = argp->narg.next) { |
@@ -9233,7 +9235,6 @@ evalfor(union node *n, int flags) | |||
9233 | break; | 9235 | break; |
9234 | } | 9236 | } |
9235 | loopnest--; | 9237 | loopnest--; |
9236 | popstackmark(&smark); | ||
9237 | 9238 | ||
9238 | return status; | 9239 | return status; |
9239 | } | 9240 | } |
@@ -9244,14 +9245,12 @@ evalcase(union node *n, int flags) | |||
9244 | union node *cp; | 9245 | union node *cp; |
9245 | union node *patp; | 9246 | union node *patp; |
9246 | struct arglist arglist; | 9247 | struct arglist arglist; |
9247 | struct stackmark smark; | ||
9248 | int status = 0; | 9248 | int status = 0; |
9249 | 9249 | ||
9250 | errlinno = lineno = n->ncase.linno; | 9250 | errlinno = lineno = n->ncase.linno; |
9251 | if (funcline) | 9251 | if (funcline) |
9252 | lineno -= funcline - 1; | 9252 | lineno -= funcline - 1; |
9253 | 9253 | ||
9254 | setstackmark(&smark); | ||
9255 | arglist.list = NULL; | 9254 | arglist.list = NULL; |
9256 | arglist.lastp = &arglist.list; | 9255 | arglist.lastp = &arglist.list; |
9257 | expandarg(n->ncase.expr, &arglist, EXP_TILDE); | 9256 | expandarg(n->ncase.expr, &arglist, EXP_TILDE); |
@@ -9270,8 +9269,6 @@ evalcase(union node *n, int flags) | |||
9270 | } | 9269 | } |
9271 | } | 9270 | } |
9272 | out: | 9271 | out: |
9273 | popstackmark(&smark); | ||
9274 | |||
9275 | return status; | 9272 | return status; |
9276 | } | 9273 | } |
9277 | 9274 | ||
@@ -9970,7 +9967,6 @@ evalcommand(union node *cmd, int flags) | |||
9970 | struct localvar_list *localvar_stop; | 9967 | struct localvar_list *localvar_stop; |
9971 | struct parsefile *file_stop; | 9968 | struct parsefile *file_stop; |
9972 | struct redirtab *redir_stop; | 9969 | struct redirtab *redir_stop; |
9973 | struct stackmark smark; | ||
9974 | union node *argp; | 9970 | union node *argp; |
9975 | struct arglist arglist; | 9971 | struct arglist arglist; |
9976 | struct arglist varlist; | 9972 | struct arglist varlist; |
@@ -9992,7 +9988,6 @@ evalcommand(union node *cmd, int flags) | |||
9992 | 9988 | ||
9993 | /* First expand the arguments. */ | 9989 | /* First expand the arguments. */ |
9994 | TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); | 9990 | TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); |
9995 | setstackmark(&smark); | ||
9996 | localvar_stop = pushlocalvars(); | 9991 | localvar_stop = pushlocalvars(); |
9997 | file_stop = g_parsefile; | 9992 | file_stop = g_parsefile; |
9998 | back_exitstatus = 0; | 9993 | back_exitstatus = 0; |
@@ -10275,7 +10270,6 @@ evalcommand(union node *cmd, int flags) | |||
10275 | */ | 10270 | */ |
10276 | setvar0("_", lastarg); | 10271 | setvar0("_", lastarg); |
10277 | } | 10272 | } |
10278 | popstackmark(&smark); | ||
10279 | 10273 | ||
10280 | return status; | 10274 | return status; |
10281 | } | 10275 | } |