ref: ed33bc01d5f4e9a736830d706371163ab2db8e5a
parent: ad3817fcc317250f0459155b6965fa2d78524113
author: Avi Halachmi (:avih) <[email protected]>
date: Fri Jul 3 19:16:22 EDT 2020
gc: fix incorrect free of some objects When scanning an iterator object, the iterated object was marked unconditionally. Now it's marked only if it's not already marked - like all other object markings. This code was incorrect for some years, but wasn't really an issue before commit 331c5ec because marking an object twice simply used some more CPU cycles but otherwise without issues - unless there were cycles, and apparently typically/always there never were cycles with iterators, so it was hard/impossible to behave badly. However, since 331c5ec, marking an object means inserting it into a linked list where the list nodes are part of the object, therefore marking the same object twice now creates a broken linked list. A broken list means that some objects are skipped while scanned, which means they don't get marked even when they should, and as a result freed incorrectly while still referenced by other objects, resulting in random errors related to use-after-free.
--- a/jsgc.c
+++ b/jsgc.c
@@ -100,7 +100,7 @@
jsG_markproperty(J, mark, obj->properties);
if (obj->prototype && obj->prototype->gcmark != mark)
jsG_markobject(J, mark, obj->prototype);
- if (obj->type == JS_CITERATOR) {
+ if (obj->type == JS_CITERATOR && obj->u.iter.target->gcmark != mark) {
jsG_markobject(J, mark, obj->u.iter.target);
}
if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT || obj->type == JS_CEVAL) {