From 9b43e29d9b55eafb4e063a0b2d817356f5b908b5 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 9 Aug 2019 17:43:50 +0300 Subject: Fixed handling of references in nested data of objects with destructor --- Zend/tests/gc_041.phpt | 35 +++++++++++++++++++++++++++++++++++ Zend/zend_gc.c | 26 ++++++++++++++------------ 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 Zend/tests/gc_041.phpt diff --git a/Zend/tests/gc_041.phpt b/Zend/tests/gc_041.phpt new file mode 100644 index 0000000000..7400e23756 --- /dev/null +++ b/Zend/tests/gc_041.phpt @@ -0,0 +1,35 @@ +--TEST-- +GC 041: Handling of references in nested data of objects with destructor +--INI-- +zend.enable_gc = 1 +--FILE-- +nested = []; +$o->nested[] =& $o->nested; +$o->ryat = $o; +$x =& $o->chtg; +unset($o); +gc_collect_cycles(); +var_dump($x); +?> +--EXPECT-- +object(ryat)#1 (3) { + ["ryat"]=> + *RECURSION* + ["chtg"]=> + *RECURSION* + ["nested"]=> + &array(1) { + [0]=> + *RECURSION* + } +} \ No newline at end of file diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 55f7271e3f..d98598cc48 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -953,11 +953,9 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff zval *zv; tail_call: - if (root || - (GC_ADDRESS(GC_INFO(ref)) != 0 && - GC_REF_GET_COLOR(ref) == GC_BLACK)) { - GC_TRACE_REF(ref, "removing from buffer"); + do { if (root) { + GC_TRACE_REF(ref, "removing from buffer"); if (EXPECTED(GC_ADDRESS(GC_INFO(root->ref)) < GC_ROOT_BUFFER_MAX_ENTRIES)) { gc_remove_from_roots(root); } else { @@ -965,8 +963,18 @@ tail_call: } GC_INFO(ref) = 0; root = NULL; - } else { + } else if (GC_ADDRESS(GC_INFO(ref)) != 0 + && GC_REF_GET_COLOR(ref) == GC_BLACK) { + GC_TRACE_REF(ref, "removing from buffer"); GC_REMOVE_FROM_BUFFER(ref); + } else if (GC_TYPE(ref) == IS_REFERENCE) { + if (Z_REFCOUNTED(((zend_reference*)ref)->val)) { + ref = Z_COUNTED(((zend_reference*)ref)->val); + goto tail_call; + } + return; + } else { + return; } if (GC_TYPE(ref) == IS_OBJECT) { @@ -1004,12 +1012,6 @@ tail_call: } } else if (GC_TYPE(ref) == IS_ARRAY) { ht = (zend_array*)ref; - } else if (GC_TYPE(ref) == IS_REFERENCE) { - if (Z_REFCOUNTED(((zend_reference*)ref)->val)) { - ref = Z_COUNTED(((zend_reference*)ref)->val); - goto tail_call; - } - return; } else { return; } @@ -1045,7 +1047,7 @@ tail_call: } ref = Z_COUNTED_P(zv); goto tail_call; - } + } while (0); } ZEND_API int zend_gc_collect_cycles(void) -- cgit v1.2.1