Skip to content

Commit 9b43e29

Browse files
committed
Fixed handling of references in nested data of objects with destructor
1 parent 6b1cc12 commit 9b43e29

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

Zend/tests/gc_041.phpt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GC 041: Handling of references in nested data of objects with destructor
3+
--INI--
4+
zend.enable_gc = 1
5+
--FILE--
6+
<?php
7+
class ryat {
8+
var $ryat;
9+
var $chtg;
10+
var $nested;
11+
function __destruct() {
12+
$GLOBALS['x'] = $this;
13+
}
14+
}
15+
$o = new ryat;
16+
$o->nested = [];
17+
$o->nested[] =& $o->nested;
18+
$o->ryat = $o;
19+
$x =& $o->chtg;
20+
unset($o);
21+
gc_collect_cycles();
22+
var_dump($x);
23+
?>
24+
--EXPECT--
25+
object(ryat)#1 (3) {
26+
["ryat"]=>
27+
*RECURSION*
28+
["chtg"]=>
29+
*RECURSION*
30+
["nested"]=>
31+
&array(1) {
32+
[0]=>
33+
*RECURSION*
34+
}
35+
}

Zend/zend_gc.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -953,20 +953,28 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff
953953
zval *zv;
954954

955955
tail_call:
956-
if (root ||
957-
(GC_ADDRESS(GC_INFO(ref)) != 0 &&
958-
GC_REF_GET_COLOR(ref) == GC_BLACK)) {
959-
GC_TRACE_REF(ref, "removing from buffer");
956+
do {
960957
if (root) {
958+
GC_TRACE_REF(ref, "removing from buffer");
961959
if (EXPECTED(GC_ADDRESS(GC_INFO(root->ref)) < GC_ROOT_BUFFER_MAX_ENTRIES)) {
962960
gc_remove_from_roots(root);
963961
} else {
964962
gc_remove_from_additional_roots(root);
965963
}
966964
GC_INFO(ref) = 0;
967965
root = NULL;
968-
} else {
966+
} else if (GC_ADDRESS(GC_INFO(ref)) != 0
967+
&& GC_REF_GET_COLOR(ref) == GC_BLACK) {
968+
GC_TRACE_REF(ref, "removing from buffer");
969969
GC_REMOVE_FROM_BUFFER(ref);
970+
} else if (GC_TYPE(ref) == IS_REFERENCE) {
971+
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
972+
ref = Z_COUNTED(((zend_reference*)ref)->val);
973+
goto tail_call;
974+
}
975+
return;
976+
} else {
977+
return;
970978
}
971979

972980
if (GC_TYPE(ref) == IS_OBJECT) {
@@ -1004,12 +1012,6 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff
10041012
}
10051013
} else if (GC_TYPE(ref) == IS_ARRAY) {
10061014
ht = (zend_array*)ref;
1007-
} else if (GC_TYPE(ref) == IS_REFERENCE) {
1008-
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
1009-
ref = Z_COUNTED(((zend_reference*)ref)->val);
1010-
goto tail_call;
1011-
}
1012-
return;
10131015
} else {
10141016
return;
10151017
}
@@ -1045,7 +1047,7 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff
10451047
}
10461048
ref = Z_COUNTED_P(zv);
10471049
goto tail_call;
1048-
}
1050+
} while (0);
10491051
}
10501052

10511053
ZEND_API int zend_gc_collect_cycles(void)

0 commit comments

Comments
 (0)