[php-src] master: Merge branch 'PHP-8.5'

Ilia Alshanetsky <[email protected]> Fri, 31 Jul 2026 16:05:41 +0000
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-07-31T12:02:52-04:00

Commit: https://github.com/php/php-src/commit/7c55b0d2906e14889b3fa8038e002dee5970a59d
Raw diff: https://github.com/php/php-src/commit/7c55b0d2906e14889b3fa8038e002dee5970a59d.diff

Merge branch 'PHP-8.5'

* PHP-8.5:
  Parse qualified reflection names with a length-aware search

Master already carries the const declarations the backport introduces, so
the resolution keeps them and takes only the two zend_memnstr() calls.

Changed paths:
  A  ext/reflection/tests/ReflectionClass_getProperty_anonymous_class.phpt
  A  ext/reflection/tests/ReflectionMethod_createFromMethodName_anonymous_class.phpt
  M  ext/reflection/php_reflection.c


Diff:

diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 42ab6dcd8ae5..2bd8018ab6a1 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -3200,7 +3200,7 @@ static void instantiate_reflection_method(INTERNAL_FUNCTION_PARAMETERS, bool is_
 		const char *tmp;
 		const char *name = ZSTR_VAL(arg1_str);
 
-		if ((tmp = strstr(name, "::")) == NULL) {
+		if ((tmp = zend_memnstr(name, "::", 2, name + ZSTR_LEN(arg1_str))) == NULL) {
 			zend_argument_error(reflection_exception_ptr, 1, "must be a valid method name");
 			RETURN_THROWS();
 		}
@@ -4566,7 +4566,7 @@ ZEND_METHOD(ReflectionClass, getProperty)
 	}
 	const char *str_name = ZSTR_VAL(name);
 	const char *tmp;
-	if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
+	if ((tmp = zend_memnstr(ZSTR_VAL(name), "::", 2, ZSTR_VAL(name) + ZSTR_LEN(name))) != NULL) {
 		size_t classname_len = tmp - ZSTR_VAL(name);
 		zend_string *classname = zend_string_init(ZSTR_VAL(name), classname_len, false);
 		size_t str_name_len = ZSTR_LEN(name) - (classname_len + 2);
diff --git a/ext/reflection/tests/ReflectionClass_getProperty_anonymous_class.phpt b/ext/reflection/tests/ReflectionClass_getProperty_anonymous_class.phpt
new file mode 100644
index 000000000000..67169000b4e0
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_getProperty_anonymous_class.phpt
@@ -0,0 +1,21 @@
+--TEST--
+ReflectionClass::getProperty() with a qualified anonymous class name
+--FILE--
+<?php
+
+$obj = new class {
+    public $p = 42;
+};
+
+$reflector = new ReflectionClass($obj);
+$name = $reflector->getName();
+var_dump(str_contains($name, "\0"));
+
+$p = $reflector->getProperty($name . '::p');
+var_dump($p->getName(), $p->getValue($obj));
+
+?>
+--EXPECT--
+bool(true)
+string(1) "p"
+int(42)
diff --git a/ext/reflection/tests/ReflectionMethod_createFromMethodName_anonymous_class.phpt b/ext/reflection/tests/ReflectionMethod_createFromMethodName_anonymous_class.phpt
new file mode 100644
index 000000000000..a3ddf9bcd81b
--- /dev/null
+++ b/ext/reflection/tests/ReflectionMethod_createFromMethodName_anonymous_class.phpt
@@ -0,0 +1,20 @@
+--TEST--
+ReflectionMethod::createFromMethodName() with an anonymous class name
+--FILE--
+<?php
+
+$obj = new class {
+    public function m() { return 42; }
+};
+
+$name = (new ReflectionClass($obj))->getName();
+var_dump(str_contains($name, "\0"));
+
+$m = ReflectionMethod::createFromMethodName($name . '::m');
+var_dump($m->getName(), $m->invoke($obj));
+
+?>
+--EXPECT--
+bool(true)
+string(1) "m"
+int(42)