Skip to content

Commit 40540b7

Browse files
committed
Fix ref source removal on object destruction
1 parent c89b5ba commit 40540b7

File tree

3 files changed

+71
-7
lines changed

3 files changed

+71
-7
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Typed property assignment by ref with variable name
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public int $prop;
8+
}
9+
10+
$name = new class {
11+
public function __toString() {
12+
return 'prop';
13+
}
14+
};
15+
16+
$test = new Test;
17+
$ref = "foobar";
18+
try {
19+
$test->$name =& $ref;
20+
} catch (TypeError $e) {
21+
echo $e->getMessage(), "\n";
22+
}
23+
var_dump($test);
24+
25+
?>
26+
--EXPECT--
27+
Typed property Test::$prop must be int, string used
28+
object(Test)#2 (1) {
29+
["prop"]=>
30+
NULL
31+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Edge cases relating to reference source tracking
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public int $prop = 42;
8+
}
9+
class B extends A {
10+
}
11+
12+
$b = new B;
13+
$r =& $b->prop;
14+
unset($b);
15+
$r = "foo"; // ok
16+
17+
class A2 {
18+
private int $prop = 42;
19+
20+
public function &getRef() {
21+
return $this->prop;
22+
}
23+
}
24+
class B2 extends A2 {
25+
public $prop;
26+
}
27+
28+
$b2 = new B2;
29+
$r2 =& $b2->getRef();
30+
unset($b2);
31+
$r2 = "foo"; // ok
32+
33+
?>
34+
===DONE===
35+
--EXPECT--
36+
===DONE===

Zend/zend_objects.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,10 @@ ZEND_API void zend_object_std_dtor(zend_object *object)
5959
do {
6060
if (Z_REFCOUNTED_P(p)) {
6161
if (UNEXPECTED(Z_ISREF_P(p))) {
62-
zend_property_info *prop_info;
63-
ZEND_REF_FOREACH_TYPE_SOURCES(Z_REF_P(p), prop_info) {
64-
if (prop_info->ce == object->ce && p == OBJ_PROP(object, prop_info->offset)) {
65-
ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(p), prop_info);
66-
break; /* stop iteration here, the array might be realloc()'ed */
67-
}
68-
} ZEND_REF_FOREACH_TYPE_SOURCES_END();
62+
zend_property_info *prop_info = zend_get_property_info_for_slot(object, p);
63+
if (prop_info->type) {
64+
ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(p), prop_info);
65+
}
6966
}
7067
i_zval_ptr_dtor(p);
7168
}

0 commit comments

Comments
 (0)