diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | Zend/tests/generators/bug76427.phpt | 24 | ||||
-rw-r--r-- | Zend/zend_gc.c | 4 | ||||
-rw-r--r-- | Zend/zend_generators.c | 3 | ||||
-rw-r--r-- | Zend/zend_objects_API.c | 4 | ||||
-rw-r--r-- | Zend/zend_objects_API.h | 4 |
6 files changed, 33 insertions, 7 deletions
@@ -3,6 +3,7 @@ PHP NEWS ?? ??? ????, PHP 7.3.0alpha2 - Core: + . Fixed bug #76427 (Segfault in zend_objects_store_put). (Laruence) . Fixed bug #76422 (ftruncate fails on files > 2GB). (Anatol) - EXIF: diff --git a/Zend/tests/generators/bug76427.phpt b/Zend/tests/generators/bug76427.phpt new file mode 100644 index 0000000000..09ec61a340 --- /dev/null +++ b/Zend/tests/generators/bug76427.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #76427 (Segfault in zend_objects_store_put) +--FILE-- +<?php +$func = function () { + yield 2; +}; + +$a = new stdclass(); +$b = new stdclass(); +$a->b = $b; +$b->a = $a; + +$func = $a->func = $func(); + +unset($b); +unset($a); +unset($func); + +var_dump(gc_collect_cycles()); + +?> +--EXPECT-- +int(4) diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index a6c3741d56..40402a5a7d 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -1401,8 +1401,8 @@ ZEND_API int zend_gc_collect_cycles(void) GC_DELREF(obj); } } - SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[obj->handle], EG(objects_store).free_list_head); - EG(objects_store).free_list_head = obj->handle; + + 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; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 90e5529f00..f4dd33b95c 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -145,7 +145,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished } /* Free closure object */ - if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) { + if ((EX_CALL_INFO() & ZEND_CALL_CLOSURE) && + EXPECTED(GC_TYPE(ZEND_CLOSURE_OBJECT(EX(func))) == IS_OBJECT)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 633abccabb..0be4651cd6 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -150,10 +150,6 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_put(zend_object *object) EG(objects_store).object_buckets[handle] = object; } -#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle) \ - SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle], EG(objects_store).free_list_head); \ - EG(objects_store).free_list_head = handle; - ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ */ { /* Make sure we hold a reference count during the destructor call diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index 6fac2b535e..08cefb8ba6 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -37,6 +37,10 @@ (o) = (zend_object*)((((zend_uintptr_t)(n)) << 1) | OBJ_BUCKET_INVALID); \ } while (0) +#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(h) do { \ + SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[(h)], EG(objects_store).free_list_head); \ + EG(objects_store).free_list_head = (h); \ + } while (0) #define OBJ_RELEASE(obj) zend_object_release(obj) |