From b89e0ef305b3261c9b7ecfca0a975c3678cfcdd1 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Fri, 15 May 2026 20:10:17 +0200 Subject: [PATCH] Fix GH-22000: Unwrap references in ReflectionProperty::isReadable() (#22025) --- ext/reflection/php_reflection.c | 5 +++ ext/reflection/tests/gh22000.phpt | 61 +++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 ext/reflection/tests/gh22000.phpt diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 94d8bb7d149c..d15445d8d35d 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -6731,6 +6731,11 @@ ZEND_METHOD(ReflectionProperty, isReadable) zval member; ZVAL_STR(&member, ref->unmangled_name); zend_call_known_instance_method_with_1_params(ce->__isset, obj, return_value, &member); + + if (Z_TYPE_P(return_value) == IS_REFERENCE) { + zend_unwrap_reference(return_value); + } + *guard &= ~ZEND_GUARD_PROPERTY_ISSET; OBJ_RELEASE(obj); return; diff --git a/ext/reflection/tests/gh22000.phpt b/ext/reflection/tests/gh22000.phpt new file mode 100644 index 000000000000..aee4863e9b7d --- /dev/null +++ b/ext/reflection/tests/gh22000.phpt @@ -0,0 +1,61 @@ +--TEST-- +GH-22000 - Ensure __isset returning a reference is supported by ReflectionProperty::isReadable() +--FILE-- +b); + unset($this->c); + } + + public function __isset($name) { + return $name === 'b'; + } + + public function __get($name) {} +} + +class TestClass2 { + public int $d; + public int $e; + public int $f; + + public function __construct() { + unset($this->e); + unset($this->f); + } + + public function &__isset($name) { + return $name === 'f'; + } + + public function __get($name) {} +} + + +function test($class) { + $rc = new ReflectionClass($class); + foreach ($rc->getProperties() as $rp) { + echo $rp->getName() . ' from global:'; + var_dump($rp->isReadable(null, new $class)); + } +} + +test('TestClass1'); +test('TestClass2'); +?> +--EXPECTF-- +a from global:bool(true) +b from global:bool(true) +c from global:bool(false) +d from global:bool(false) +e from global: +Notice: Only variable references should be returned by reference in %s on line %d +bool(false) +f from global: +Notice: Only variable references should be returned by reference in %s on line %d +bool(true)