]> granicus.if.org Git - php/commitdiff
Handle reallocated root buffer during GC destroy phase (v2)
authorTyson Andre <tysonandre775@hotmail.com>
Wed, 20 Nov 2019 00:12:56 +0000 (19:12 -0500)
committerTyson Andre <tysonandre775@hotmail.com>
Sat, 23 Nov 2019 15:45:20 +0000 (10:45 -0500)
We no longer protect GC during the destroy phase, so we need to
deal with buffer reallocation.

Note that the implementation of spl_SplObjectStorage_free_storage
will call the destructor of SplObjectStorage, and free the instance properties,
which I think is what caused the root buffer to be reallocated.
(`current` is a pointer for an index within the root buffer?)

This fixes bug #78811 for me.

Closes GH-4935

Zend/zend_gc.c

index c36f4e7ced40f4ee2a52cd12cd1b8c378976bf86..7cecd534108336859eb1b787364282ee1710a8c3 100644 (file)
@@ -1561,6 +1561,8 @@ ZEND_API int zend_gc_collect_cycles(void)
                                        EG(objects_store).object_buckets[obj->handle] = SET_OBJ_INVALID(obj);
                                        GC_TYPE_INFO(obj) = IS_NULL |
                                                (GC_TYPE_INFO(obj) & ~GC_TYPE_MASK);
+                                       /* Modify current before calling free_obj (bug #78811: free_obj() can cause the root buffer (with current) to be reallocated.) */
+                                       current->ref = GC_MAKE_GARBAGE(((char*)obj) - obj->handlers->offset);
                                        if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
                                                GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
                                                GC_ADDREF(obj);
@@ -1569,7 +1571,6 @@ ZEND_API int zend_gc_collect_cycles(void)
                                        }
 
                                        ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(obj->handle);
-                                       current->ref = GC_MAKE_GARBAGE(((char*)obj) - obj->handlers->offset);
                                } else if (GC_TYPE(p) == IS_ARRAY) {
                                        zend_array *arr = (zend_array*)p;