From f64eaa8c6839247c4e3023d244fdc328fd455e8d Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 5 Jun 2020 19:59:37 -0700 Subject: mapcar/maprod: fix stack overflow regression. The recent refactoring of the mapping functions to use stack-allocated iterators has a bug. args_decl occurs inside a loop. But args_decl uses alloca, which doesn't dispose of the memory when the block scope terminates. * eval.c (map_common, prod_common): Move the declaration of args_fun outside of the loop, so that it is allocated just once. The loop just stuffs fresh sets of values into the arguments. --- eval.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/eval.c b/eval.c index a928db95..81b75a3f 100644 --- a/eval.c +++ b/eval.c @@ -5287,6 +5287,8 @@ static val map_common(val self, val fun, struct args *lists, cnum i, idx, argc = args_count(lists); seq_iter_t *iter_array = coerce(seq_iter_t *, alloca(argc * sizeof *iter_array)); + args_decl(args_fun, max(argc, ARGS_MIN)); + args_fun->fill = argc; list_collect_decl (out, otail); for (i = 0, idx = 0; i < argc; i++) @@ -5297,9 +5299,6 @@ static val map_common(val self, val fun, struct args *lists, for (;;) { val fun_ret; - args_decl(args_fun, max(argc, ARGS_MIN)); - - args_fun->fill = argc; for (i = 0; i < argc; i++) { val elem; @@ -5420,20 +5419,20 @@ static val prod_common(val fun, struct args *lists, list_collect_decl (out, ptail); args_decl(args_reset, max(argc, ARGS_MIN)); args_decl(args_work, max(argc, ARGS_MIN)); + args_decl(args_fun, max(argc, ARGS_MIN)); args_copy(args_reset, lists); args_normalize_exact(args_reset, argc); - args_work->fill = args_reset->fill; + args_work->fill = argc; + args_fun->fill = argc; for (i = 0; i < argc; i++) if (!iter_more((args_work->arg[i] = iter_begin(args_reset->arg[i])))) goto out; for (;;) { - args_decl(args_fun, max(argc, ARGS_MIN)); for (i = 0; i < argc; i++) args_fun->arg[i] = iter_item(args_work->arg[i]); - args_fun->fill = argc; ptail = collect_fn(ptail, generic_funcall(fun, args_fun)); -- cgit v1.2.3