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 | 79eb41038860a4014d2e620add84b9b5d61be724 (patch) | |
tree | 4a9a52e4c56eee31ff330c40cb0e8be381c3c067 | |
parent | 4d07a024953528b5a44cfa0e5ffd6622428d5a4f (diff) | |
download | txr-79eb41038860a4014d2e620add84b9b5d61be724.tar.gz txr-79eb41038860a4014d2e620add84b9b5d61be724.tar.bz2 txr-79eb41038860a4014d2e620add84b9b5d61be724.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.
-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)); |