Skip to content

Commit 172c719

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed handling of references in nested data of objects with destructor
2 parents 8edf59c + 4ebf527 commit 172c719

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
@@ -1336,16 +1336,24 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff
13361336
zval *zv;
13371337

13381338
tail_call:
1339-
if (root ||
1340-
(GC_REF_ADDRESS(ref) != 0 &&
1341-
GC_REF_CHECK_COLOR(ref, GC_BLACK))) {
1342-
GC_TRACE_REF(ref, "removing from buffer");
1339+
do {
13431340
if (root) {
1341+
GC_TRACE_REF(ref, "removing from buffer");
13441342
gc_remove_from_roots(root);
13451343
GC_REF_SET_INFO(ref, 0);
13461344
root = NULL;
1347-
} else {
1345+
} else if (GC_REF_ADDRESS(ref) != 0
1346+
&& GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
1347+
GC_TRACE_REF(ref, "removing from buffer");
13481348
GC_REMOVE_FROM_BUFFER(ref);
1349+
} else if (GC_TYPE(ref) == IS_REFERENCE) {
1350+
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
1351+
ref = Z_COUNTED(((zend_reference*)ref)->val);
1352+
goto tail_call;
1353+
}
1354+
return;
1355+
} else {
1356+
return;
13491357
}
13501358

13511359
if (GC_TYPE(ref) == IS_OBJECT) {
@@ -1379,12 +1387,6 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff
13791387
}
13801388
} else if (GC_TYPE(ref) == IS_ARRAY) {
13811389
ht = (zend_array*)ref;
1382-
} else if (GC_TYPE(ref) == IS_REFERENCE) {
1383-
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
1384-
ref = Z_COUNTED(((zend_reference*)ref)->val);
1385-
goto tail_call;
1386-
}
1387-
return;
13881390
} else {
13891391
return;
13901392
}
@@ -1420,7 +1422,7 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buff
14201422
}
14211423
ref = Z_COUNTED_P(zv);
14221424
goto tail_call;
1423-
}
1425+
} while (0);
14241426
}
14251427

14261428
ZEND_API int zend_gc_collect_cycles(void)

0 commit comments

Comments
 (0)