From c9f5702aaa3d1380a7ff2d11b0985b78694fb81a Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Wed, 10 Jun 2026 19:58:51 +0200 Subject: [PATCH 1/2] Preserve class-name case in ReflectionClass::getProperty() When given a "Class::property" argument, getProperty() lowercased the class part before looking it up, so the "Class ... does not exist" exception printed the lowercased name and autoloaders received it in lowercase, breaking case-sensitive (PSR-4) autoloaders. Pass the class name to zend_lookup_class() as given - it lowercases internally for the class-table lookup - matching what ReflectionMethod and ReflectionProperty already do. --- ext/reflection/php_reflection.c | 4 +--- .../ReflectionClass_getProperty_003.phpt | 2 +- .../ReflectionClass_getProperty_004.phpt | 2 +- ...onClass_getProperty_case_preservation.phpt | 22 +++++++++++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index af565ed53a32..eff61659d078 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4635,9 +4635,7 @@ ZEND_METHOD(ReflectionClass, getProperty) str_name = ZSTR_VAL(name); if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) { classname_len = tmp - ZSTR_VAL(name); - classname = zend_string_alloc(classname_len, 0); - zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len); - ZSTR_VAL(classname)[classname_len] = '\0'; + classname = zend_string_init(ZSTR_VAL(name), classname_len, 0); str_name_len = ZSTR_LEN(name) - (classname_len + 2); str_name = tmp + 2; diff --git a/ext/reflection/tests/ReflectionClass_getProperty_003.phpt b/ext/reflection/tests/ReflectionClass_getProperty_003.phpt index c47f9e4fffd7..8be2f4bf85b6 100644 --- a/ext/reflection/tests/ReflectionClass_getProperty_003.phpt +++ b/ext/reflection/tests/ReflectionClass_getProperty_003.phpt @@ -244,4 +244,4 @@ Fully qualified property name X::$privC does not specify a base class of C --- (Reflecting on X::doesNotExist) --- Fully qualified property name X::$doesNotExist does not specify a base class of C --- (Reflecting on doesNotexist::doesNotExist) --- -Class "doesnotexist" does not exist +Class "doesNotexist" does not exist diff --git a/ext/reflection/tests/ReflectionClass_getProperty_004.phpt b/ext/reflection/tests/ReflectionClass_getProperty_004.phpt index 32e2d7876f6d..6a4f44ee5977 100644 --- a/ext/reflection/tests/ReflectionClass_getProperty_004.phpt +++ b/ext/reflection/tests/ReflectionClass_getProperty_004.phpt @@ -248,4 +248,4 @@ Fully qualified property name X::$privC does not specify a base class of C --- (Reflecting on X::doesNotExist) --- Fully qualified property name X::$doesNotExist does not specify a base class of C --- (Reflecting on doesNotexist::doesNotExist) --- -Class "doesnotexist" does not exist +Class "doesNotexist" does not exist diff --git a/ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt b/ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt new file mode 100644 index 000000000000..7503483cd0c3 --- /dev/null +++ b/ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt @@ -0,0 +1,22 @@ +--TEST-- +ReflectionClass::getProperty() preserves the case of the class name in errors and autoloading +--FILE-- +getProperty("Some\\MixedCase::p"); +} catch (ReflectionException $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Autoloading Some\MixedCase +Class "Some\MixedCase" does not exist From 108faa96766995e65ea6627c481f5be8c2cfebb1 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Wed, 10 Jun 2026 20:51:39 +0200 Subject: [PATCH 2/2] test: removed redundant test --- ...onClass_getProperty_case_preservation.phpt | 22 ------------------- tests/classes/autoload_016.phpt | 4 ++-- 2 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt diff --git a/ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt b/ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt deleted file mode 100644 index 7503483cd0c3..000000000000 --- a/ext/reflection/tests/ReflectionClass_getProperty_case_preservation.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -ReflectionClass::getProperty() preserves the case of the class name in errors and autoloading ---FILE-- -getProperty("Some\\MixedCase::p"); -} catch (ReflectionException $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECT-- -Autoloading Some\MixedCase -Class "Some\MixedCase" does not exist diff --git a/tests/classes/autoload_016.phpt b/tests/classes/autoload_016.phpt index 13454d018cdd..c6e7a2b37682 100644 --- a/tests/classes/autoload_016.phpt +++ b/tests/classes/autoload_016.phpt @@ -16,5 +16,5 @@ $rc->getProperty("UndefC::p"); } ?> --EXPECT-- -In autoload: string(6) "undefc" -Class "undefc" does not exist +In autoload: string(6) "UndefC" +Class "UndefC" does not exist