Skip to content

Commit d672537

Browse files
committed
Prevent by-ref func arg fetch from using a cached name/class offset
1 parent 2413663 commit d672537

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

‎ext/reflection/php_reflection.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7968,6 +7968,17 @@ static zval *_reflection_write_property(zend_object *object, zend_string *name,
79687968
}
79697969
/* }}} */
79707970

7971+
static zval *_reflection_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
7972+
{
7973+
/* Don't cache the offset of read-only properties: a by-reference fetch
7974+
* sharing the cache slot (FETCH_OBJ_FUNC_ARG) would skip get_property_ptr_ptr. */
7975+
if (reflection_is_read_only_property(object, name)) {
7976+
cache_slot = NULL;
7977+
}
7978+
7979+
return zend_std_read_property(object, name, type, cache_slot, rv);
7980+
}
7981+
79717982
static zval *_reflection_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
79727983
{
79737984
if (reflection_is_read_only_property(object, name)) {
@@ -8122,6 +8133,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
81228133
reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
81238134
reflection_object_handlers.free_obj = reflection_free_objects_storage;
81248135
reflection_object_handlers.clone_obj = NULL;
8136+
reflection_object_handlers.read_property = _reflection_read_property;
81258137
reflection_object_handlers.write_property = _reflection_write_property;
81268138
reflection_object_handlers.get_property_ptr_ptr = _reflection_get_property_ptr_ptr;
81278139
reflection_object_handlers.get_gc = reflection_get_gc;

‎ext/reflection/tests/gh24147.phpt‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class B {
77
public string $x;
88
}
99

10+
function byVal($x) {}
11+
function byRef(&$x) { $x .= 'Z'; }
12+
1013
$prop = new ReflectionProperty('B', 'x');
1114

1215
try {
@@ -28,12 +31,21 @@ try {
2831
echo $e->getMessage(), "\n";
2932
}
3033

34+
foreach (['byVal', 'byRef'] as $fn) {
35+
try {
36+
$fn($prop->class);
37+
} catch (ReflectionException $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
}
41+
3142
var_dump($prop->class, $prop->name);
3243

3344
?>
3445
--EXPECT--
3546
Cannot set read-only property ReflectionProperty::$class
3647
Cannot set read-only property ReflectionProperty::$name
3748
Cannot set read-only property ReflectionProperty::$name
49+
Cannot set read-only property ReflectionProperty::$class
3850
string(1) "B"
3951
string(1) "x"

0 commit comments

Comments
 (0)