summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-06-05 19:59:37 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-06-05 19:59:37 -0700
commitf64eaa8c6839247c4e3023d244fdc328fd455e8d (patch)
tree4a9a52e4c56eee31ff330c40cb0e8be381c3c067 /eval.c
parentc6d3a92f68f91ef3fee09e8d2051ae066162482d (diff)
downloadtxr-f64eaa8c6839247c4e3023d244fdc328fd455e8d.tar.gz
txr-f64eaa8c6839247c4e3023d244fdc328fd455e8d.tar.bz2
txr-f64eaa8c6839247c4e3023d244fdc328fd455e8d.zip
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.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c11
1 files 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));