[PATCH] ash: fix stack overflow in evalfun()
Sanghyun Park via busybox <[email protected]> Tue, 16 Jun 2026 12:19:27 +0900
| Newsgroups | gmane.linux.busybox |
|---|---|
| Message-ID | <[email protected]> |
Recursive shell functions can repeatedly enter evalfun() until the process stack is exhausted. Track active shell function calls and raise a normal shell error when the recursion limit is reached. The counter is decremented through the existing funcdone cleanup path so errors raised from inside the function body unwind it correctly. Signed-off-by: Sanghyun Park <[email protected]> --- shell/ash.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index cda6c85..2e319cc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -481,6 +481,7 @@ struct globals_misc { int shlvl; #define rootshell (!shlvl) int errlinno; + unsigned func_depth; char *minusc; /* argument to -c option */ @@ -588,6 +589,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; #define rootpid (G_misc.rootpid ) #define shlvl (G_misc.shlvl ) #define errlinno (G_misc.errlinno ) +#define func_depth (G_misc.func_depth ) #define minusc (G_misc.minusc ) #define curdir (G_misc.curdir ) #define physdir (G_misc.physdir ) @@ -10321,6 +10323,10 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) int savefuncline; char *savefuncname; char *savetrap = NULL; + enum { MAX_ASH_FUNC_DEPTH = 1000 }; + + if (func_depth >= MAX_ASH_FUNC_DEPTH) + ash_msg_and_raise_error("function recursion limit exceeded"); if (!Eflag) { savetrap = trap[NTRAP_ERR]; @@ -10339,6 +10345,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) exception_handler = &jmploc; shellparam.malloced = 0; func->count++; + func_depth++; funcname = func->n.ndefun.text; funcline = func->n.ndefun.linno; INTON; @@ -10360,6 +10367,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) } funcline = savefuncline; lineno = savelineno; + func_depth--; freefunc(func); freeparam(&shellparam); shellparam = saveparam; -- 2.48.1