[PATCH] awk: fix stack overflow in evaluate()
Sanghyun Park
sanghyun.park.cnu at gmail.com
Tue Jun 16 03:16:05 UTC 2026
Recursive awk functions can keep re-entering evaluate() until the
process stack is exhausted. Track active function-call depth and report a
normal awk error once the limit is reached instead of overflowing the
stack.
Signed-off-by: Sanghyun Park <sanghyun.park.cnu at gmail.com>
---
editors/awk.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/editors/awk.c b/editors/awk.c
index dd8f4ac..f15832b 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -633,6 +633,7 @@ struct globals {
smalluint exitcode;
unsigned evaluate__seed;
+ unsigned evaluate__func_depth;
var *evaluate__fnargs;
regex_t evaluate__sreg;
@@ -703,6 +704,7 @@ static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token";
static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero";
static const char EMSG_INV_FMT[] ALIGN1 = "Invalid format specifier";
static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments";
+static const char EMSG_RECURSION[] ALIGN1 = "Recursion limit exceeded";
static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array";
static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
@@ -2988,6 +2990,7 @@ static var *evaluate(node *op, var *res)
#define fnargs (G.evaluate__fnargs)
/* seed is initialized to 1 */
#define seed (G.evaluate__seed)
+#define func_depth (G.evaluate__func_depth)
#define sreg (G.evaluate__sreg)
var *tmpvars;
@@ -3299,13 +3302,17 @@ static var *evaluate(node *op, var *res)
var *argvars, *sv_fnargs;
const char *sv_progname;
int nargs, i;
+ enum { MAX_AWK_FUNC_DEPTH = 1000 };
debug_printf_eval("FUNC\n");
if (!op->r.f->defined)
syntax_error(EMSG_UNDEF_FUNC);
+ if (func_depth >= MAX_AWK_FUNC_DEPTH)
+ syntax_error(EMSG_RECURSION);
/* The body might be empty, still has to eval the args */
+ func_depth++;
nargs = op->r.f->nargs;
argvars = nvalloc(nargs);
i = 0;
@@ -3333,6 +3340,7 @@ static var *evaluate(node *op, var *res)
g_progname = sv_progname;
fnargs = sv_fnargs;
+ func_depth--;
break;
}
@@ -3690,6 +3698,7 @@ static var *evaluate(node *op, var *res)
return res;
#undef fnargs
#undef seed
+#undef func_depth
#undef sreg
}
--
2.48.1
More information about the busybox
mailing list