diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-06-05 19:59:37 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-06-05 19:59:37 -0700 |
commit | f64eaa8c6839247c4e3023d244fdc328fd455e8d (patch) | |
tree | 4a9a52e4c56eee31ff330c40cb0e8be381c3c067 /eval.c | |
parent | c6d3a92f68f91ef3fee09e8d2051ae066162482d (diff) | |
download | txr-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.c | 11 |
1 files changed, 5 insertions, 6 deletions
@@ -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)); |