Skip to content

Commit 877b3ba

Browse files
committed
Mark object non-lazy before deleting info in zend_lazy_object_realize()
1 parent b156471 commit 877b3ba

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-20657: GC during zend_lazy_object_realize()
3+
--CREDITS--
4+
vi3tL0u1s
5+
--FILE--
6+
<?php
7+
8+
class C {
9+
public $a;
10+
}
11+
12+
$reflector = new ReflectionClass(C::class);
13+
14+
for ($i = 0; $i < 10000; $i++) {
15+
$obj = $reflector->newLazyGhost(function ($obj) {});
16+
17+
// Add to roots
18+
$obj2 = $obj;
19+
unset($obj2);
20+
21+
// Initialize all props to mark object non-lazy. Also create a cycle.
22+
$reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, $obj);
23+
}
24+
25+
var_dump($obj);
26+
27+
?>
28+
--EXPECTF--
29+
object(C)#%d (1) {
30+
["a"]=>
31+
*RECURSION*
32+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
GH-20657 002: GC during zend_lazy_object_realize() - reset as lazy during realize()
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $a;
8+
}
9+
10+
class D {
11+
public $self;
12+
public function __construct() {
13+
$this->self = $this;
14+
}
15+
public function __destruct() {
16+
global $obj, $reflector;
17+
$reflector->resetAsLazyGhost($obj, function () {});
18+
}
19+
}
20+
21+
new D();
22+
23+
$reflector = new ReflectionClass(C::class);
24+
25+
for ($i = 0; $i < 10000; $i++) {
26+
$obj = $reflector->newLazyGhost(function ($obj) {});
27+
28+
// Add to roots
29+
$obj2 = $obj;
30+
unset($obj2);
31+
32+
// Initialize all props to mark object non-lazy. Also create a cycle.
33+
$reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, $obj);
34+
}
35+
36+
var_dump($obj);
37+
38+
?>
39+
--EXPECTF--
40+
object(C)#%d (1) {
41+
["a"]=>
42+
*RECURSION*
43+
}

Zend/zend_lazy_objects.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,15 +678,14 @@ void zend_lazy_object_realize(zend_object *obj)
678678
ZEND_ASSERT(zend_object_is_lazy(obj));
679679
ZEND_ASSERT(!zend_lazy_object_initialized(obj));
680680

681-
zend_lazy_object_del_info(obj);
682-
683681
#if ZEND_DEBUG
684682
for (int i = 0; i < obj->ce->default_properties_count; i++) {
685683
ZEND_ASSERT(!(Z_PROP_FLAG_P(&obj->properties_table[i]) & IS_PROP_LAZY));
686684
}
687685
#endif
688686

689687
OBJ_EXTRA_FLAGS(obj) &= ~(IS_OBJ_LAZY_UNINITIALIZED | IS_OBJ_LAZY_PROXY);
688+
zend_lazy_object_del_info(obj);
690689
}
691690

692691
ZEND_API HashTable *zend_lazy_object_get_properties(zend_object *object)

0 commit comments

Comments
 (0)