From 25de02b81c5d127db837ec6146b74f5b7822e478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 22 Oct 2025 08:41:21 +0200 Subject: [PATCH 1/2] uri: Improve type safety for `php_uri_parser_rfc3986_userinfo_*()` (#20244) The signature for these functions does not need to match a specific function pointer signature, thus there is no need for a `void*` to take the uri. --- ext/uri/uri_parser_rfc3986.c | 4 ++-- ext/uri/uri_parser_rfc3986.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c index 30707fde1302..a24fb467bf34 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -149,7 +149,7 @@ static zend_result php_uri_parser_rfc3986_scheme_write(void *uri, zval *value, z } } -ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(php_uri_parser_rfc3986_uris *uri, php_uri_component_read_mode read_mode, zval *retval) { const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); @@ -162,7 +162,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(void *ur return SUCCESS; } -zend_result php_uri_parser_rfc3986_userinfo_write(void *uri, zval *value, zval *errors) +zend_result php_uri_parser_rfc3986_userinfo_write(php_uri_parser_rfc3986_uris *uri, zval *value, zval *errors) { UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; diff --git a/ext/uri/uri_parser_rfc3986.h b/ext/uri/uri_parser_rfc3986.h index fbbfefb30af6..4d88478b6063 100644 --- a/ext/uri/uri_parser_rfc3986.h +++ b/ext/uri/uri_parser_rfc3986.h @@ -23,8 +23,8 @@ PHPAPI extern const php_uri_parser php_uri_parser_rfc3986; typedef struct php_uri_parser_rfc3986_uris php_uri_parser_rfc3986_uris; -zend_result php_uri_parser_rfc3986_userinfo_read(void *uri, php_uri_component_read_mode read_mode, zval *retval); -zend_result php_uri_parser_rfc3986_userinfo_write(void *uri, zval *value, zval *errors); +zend_result php_uri_parser_rfc3986_userinfo_read(php_uri_parser_rfc3986_uris *uri, php_uri_component_read_mode read_mode, zval *retval); +zend_result php_uri_parser_rfc3986_userinfo_write(php_uri_parser_rfc3986_uris *uri, zval *value, zval *errors); php_uri_parser_rfc3986_uris *php_uri_parser_rfc3986_parse_ex(const char *uri_str, size_t uri_str_len, const php_uri_parser_rfc3986_uris *uriparser_base_url, bool silent); From 572652e5def9a541d55f2e66dd48eb0e0d5a24b1 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois <2144837+alexandre-daubois@users.noreply.github.com> Date: Wed, 22 Oct 2025 10:01:35 +0200 Subject: [PATCH 2/2] Fix GH-20217: ReflectionClass::isIterable() should return false for classes with property hooks (#20241) --- NEWS | 4 ++ ext/reflection/php_reflection.c | 3 +- .../ReflectionClass_isIterable_gh20217.phpt | 38 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 ext/reflection/tests/ReflectionClass_isIterable_gh20217.phpt diff --git a/NEWS b/NEWS index 7d24c95d5b99..ebf82ed1be6d 100644 --- a/NEWS +++ b/NEWS @@ -67,6 +67,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 f79d8a5181dd..e718b1815fb3 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 000000000000..f64fc1efcd41 --- /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