diff --git a/NEWS b/NEWS index 0eb3d46ee0527..924a7b5418575 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,10 @@ PHP NEWS - Random: . Fix Randomizer::__serialize() w.r.t. INDIRECTs. (nielsdos) +- Reflection: + . Fixed bug GH-20217 (ReflectionClass::isIterable() incorrectly returns true + for classes with property hooks). (alexandre-daubois) + - SimpleXML: . Partially fixed bug GH-16317 (SimpleXML does not allow __debugInfo() overrides to work). (nielsdos) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index f79d8a5181dda..e718b1815fb36 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -5696,7 +5696,8 @@ ZEND_METHOD(ReflectionClass, isIterable) RETURN_FALSE; } - RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable)); + RETURN_BOOL((ce->get_iterator && ce->get_iterator != zend_hooked_object_get_iterator) + || instanceof_function(ce, zend_ce_traversable)); } /* }}} */ diff --git a/ext/reflection/tests/ReflectionClass_isIterable_gh20217.phpt b/ext/reflection/tests/ReflectionClass_isIterable_gh20217.phpt new file mode 100644 index 0000000000000..f64fc1efcd414 --- /dev/null +++ b/ext/reflection/tests/ReflectionClass_isIterable_gh20217.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-20217 (ReflectionClass::isIterable() should return false for classes with property hooks) +--FILE-- + 'virtual'; + } +} + +class IterableClassWithPropertyHooks implements IteratorAggregate +{ + public string $name { + get => 'virtual'; + } + + public function getIterator(): Traversable + { + return new ArrayIterator([]); + } +} + +$classes = [ + 'ClassWithPropertyHooks' => false, + 'IterableClassWithPropertyHooks' => true, +]; + +foreach ($classes as $className => $expected) { + $status = (new ReflectionClass($className)->isIterable() === $expected) ? 'PASS' : 'FAIL'; + echo "$className: $status\n"; +} + +?> +--EXPECT-- +ClassWithPropertyHooks: PASS +IterableClassWithPropertyHooks: PASS