diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-12-17 20:02:46 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-12-17 20:02:46 -0800 |
commit | f0493b337617d403dc572975784f1a54c741a76e (patch) | |
tree | db537c546fe1b37cbcbcf48fe774086963331f06 | |
parent | a937384ebf3e387c81897189e42c87a574b937fb (diff) | |
download | txr-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.c | 3 |
1 files changed, 3 insertions, 0 deletions
@@ -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 */ |