summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-12-17 20:02:46 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-12-17 20:02:46 -0800
commitf0493b337617d403dc572975784f1a54c741a76e (patch)
treedb537c546fe1b37cbcbcf48fe774086963331f06
parenta937384ebf3e387c81897189e42c87a574b937fb (diff)
downloadtxr-f0493b337617d403dc572975784f1a54c741a76e.tar.gz
txr-f0493b337617d403dc572975784f1a54c741a76e.tar.bz2
txr-f0493b337617d403dc572975784f1a54c741a76e.zip
iter-reset: gc problem.
* lib.c (iter_reset): When we reinitialize the iterator, it can allocate a new secondary object, e.g. using hash_begin, which is stored into the iterator. This is potentially a wrong-way assignment in terms of GC generations and so we must call mut(iter) to indicate that the object has been suspiciously mutated. We only do this if the iterator has a mark function. If it doesn't have one, then it isn't wrapping a heap object, and so doesn't have this issue. (seq_reset): This has the same issue, and the fix is the same. Since ths function is obsolescent, we don't bother doing the si->ops->mark check; we optimize for code size instead.
-rw-r--r--lib.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index 15909c6c..dca7474d 100644
--- a/lib.c
+++ b/lib.c
@@ -1183,6 +1183,7 @@ val seq_reset(val iter, val obj)
struct seq_iter *si = coerce(struct seq_iter *,
cobj_handle(self, iter, seq_iter_cls));
seq_iter_init(self, si, obj);
+ mut(iter);
return iter;
}
@@ -1350,6 +1351,8 @@ val iter_reset(val iter, val obj)
{
struct seq_iter *si = coerce(struct seq_iter *, iter->co.handle);
seq_iter_init_with_info(self, si, sinf, 0);
+ if (si->ops->mark)
+ mut(iter);
return iter;
}
/* fallthrough */