Skip to content

Commit 978e2b1

Browse files
committed
Prevent by-ref func arg fetch from using a cached name/class offset
1 parent 17e783e commit 978e2b1

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
@@ -7956,6 +7956,17 @@ static zval *_reflection_write_property(zend_object *object, zend_string *name,
79567956
}
79577957
/* }}} */
79587958

7959+
static zval *_reflection_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
7960+
{
7961+
/* Don't cache the offset of read-only properties: a by-reference fetch
7962+
* sharing the cache slot (FETCH_OBJ_FUNC_ARG) would skip get_property_ptr_ptr. */
7963+
if (reflection_is_read_only_property(object, name)) {
7964+
cache_slot = NULL;
7965+
}
7966+
7967+
return zend_std_read_property(object, name, type, cache_slot, rv);
7968+
}
7969+
79597970
static zval *_reflection_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
79607971
{
79617972
if (reflection_is_read_only_property(object, name)) {
@@ -8187,6 +8198,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
81878198
reflection_object_handlers.offset = offsetof(reflection_object, zo);
81888199
reflection_object_handlers.free_obj = reflection_free_objects_storage;
81898200
reflection_object_handlers.clone_obj = NULL;
8201+
reflection_object_handlers.read_property = _reflection_read_property;
81908202
reflection_object_handlers.write_property = _reflection_write_property;
81918203
reflection_object_handlers.get_property_ptr_ptr = _reflection_get_property_ptr_ptr;
81928204
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)