From aadd30168a2a63b5237fcb92dbf7c7cf159649dc Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Wed, 12 Feb 2025 18:42:57 -0800 Subject: [PATCH 1/2] Reflection: show the type of object constants used as default properties When a property default is based on a global constant, show the type of the default. Previously, `format_default_value()` assumed that non-scalar and non-array defaults were always going to be `IS_CONSTANT_AST` pointers, and when the AST expression had been evaluated and produced an object, depending on when the `ReflectionClass` or `ReflectionProperty` instance had been created, the default was shown as one of `callable` or `__CLASS__`. Instead, if the default value is an object (`IS_OBJECT`), show the type of that object. Add test cases for both of the `callable` and `__CLASS__` cases to confirm that they now properly show the type of the constant. Closes GH-15902 --- NEWS | 4 ++ ext/reflection/php_reflection.c | 16 +++++--- .../gh15902/ReflectionClass-callable.phpt | 37 ++++++++++++++++++ .../tests/gh15902/ReflectionClass-class.phpt | 38 +++++++++++++++++++ .../gh15902/ReflectionProperty-callable.phpt | 20 ++++++++++ .../gh15902/ReflectionProperty-class.phpt | 20 ++++++++++ 6 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 ext/reflection/tests/gh15902/ReflectionClass-callable.phpt create mode 100644 ext/reflection/tests/gh15902/ReflectionClass-class.phpt create mode 100644 ext/reflection/tests/gh15902/ReflectionProperty-callable.phpt create mode 100644 ext/reflection/tests/gh15902/ReflectionProperty-class.phpt diff --git a/NEWS b/NEWS index 20913d4a51d3..f00ae938bca1 100644 --- a/NEWS +++ b/NEWS @@ -38,6 +38,10 @@ PHP NEWS - PHPDBG: . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) +- Reflection: + . Fixed bug GH-15902 (Core dumped in ext/reflection/php_reflection.c). + (DanielEScherzer) + - SimpleXML: . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). (nielsdos) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 9f9615aba54a..6eb6b2d81474 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -643,13 +643,19 @@ static int format_default_value(smart_str *str, zval *value) { } ZEND_HASH_FOREACH_END(); smart_str_appendc(str, ']'); } else if (Z_TYPE_P(value) == IS_OBJECT) { - /* This branch may only be reached for default properties, which don't support arbitrary objects. */ + /* This branch may only be reached for default properties; show enum names, + or the type of non-enums (GH-15902) */ zend_object *obj = Z_OBJ_P(value); zend_class_entry *class = obj->ce; - ZEND_ASSERT(class->ce_flags & ZEND_ACC_ENUM); - smart_str_append(str, class->name); - smart_str_appends(str, "::"); - smart_str_append(str, Z_STR_P(zend_enum_fetch_case_name(obj))); + if (class->ce_flags & ZEND_ACC_ENUM) { + smart_str_append(str, class->name); + smart_str_appends(str, "::"); + smart_str_append(str, Z_STR_P(zend_enum_fetch_case_name(obj))); + } else { + smart_str_appends(str, "object("); + smart_str_append(str, class->name); + smart_str_appends(str, ")"); + } } else { ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST); zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), ""); diff --git a/ext/reflection/tests/gh15902/ReflectionClass-callable.phpt b/ext/reflection/tests/gh15902/ReflectionClass-callable.phpt new file mode 100644 index 000000000000..0ed02dd837c9 --- /dev/null +++ b/ext/reflection/tests/gh15902/ReflectionClass-callable.phpt @@ -0,0 +1,37 @@ +--TEST-- +ReflectionClass object default property - used to say "callable" +--INI-- +opcache.enable_cli=0 +--FILE-- + +--EXPECTF-- +Class [ class C ] { + @@ %sReflectionClass-callable.php %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [1] { + Property [ public stdClass $a = object(stdClass) ] + } + + - Methods [0] { + } +} diff --git a/ext/reflection/tests/gh15902/ReflectionClass-class.phpt b/ext/reflection/tests/gh15902/ReflectionClass-class.phpt new file mode 100644 index 000000000000..cb03cdd383fe --- /dev/null +++ b/ext/reflection/tests/gh15902/ReflectionClass-class.phpt @@ -0,0 +1,38 @@ +--TEST-- +ReflectionClass object default property - used to say "__CLASS__" +--INI-- +opcache.enable_cli=0 +--FILE-- + +--EXPECTF-- +Class [ class C ] { + @@ %sReflectionClass-class.php %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [1] { + Property [ public stdClass $a = object(stdClass) ] + } + + - Methods [0] { + } +} diff --git a/ext/reflection/tests/gh15902/ReflectionProperty-callable.phpt b/ext/reflection/tests/gh15902/ReflectionProperty-callable.phpt new file mode 100644 index 000000000000..b88d52721fce --- /dev/null +++ b/ext/reflection/tests/gh15902/ReflectionProperty-callable.phpt @@ -0,0 +1,20 @@ +--TEST-- +ReflectionProperty object default - used to say "callable" +--INI-- +opcache.enable_cli=0 +--FILE-- + +--EXPECTF-- +Property [ public stdClass $a = object(stdClass) ] diff --git a/ext/reflection/tests/gh15902/ReflectionProperty-class.phpt b/ext/reflection/tests/gh15902/ReflectionProperty-class.phpt new file mode 100644 index 000000000000..021df4fe87be --- /dev/null +++ b/ext/reflection/tests/gh15902/ReflectionProperty-class.phpt @@ -0,0 +1,20 @@ +--TEST-- +ReflectionProperty object default - used to say "__CLASS__" +--INI-- +opcache.enable_cli=0 +--FILE-- + +--EXPECTF-- +Property [ public stdClass $a = object(stdClass) ] From 16ba1cc925defe9e7d1c676772139930ff3b5e5d Mon Sep 17 00:00:00 2001 From: DanielEScherzer Date: Fri, 14 Feb 2025 11:32:43 -0800 Subject: [PATCH 2/2] update comment [skip ci] --- ext/reflection/php_reflection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 6eb6b2d81474..16f00bc4da7f 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -643,8 +643,9 @@ static int format_default_value(smart_str *str, zval *value) { } ZEND_HASH_FOREACH_END(); smart_str_appendc(str, ']'); } else if (Z_TYPE_P(value) == IS_OBJECT) { - /* This branch may only be reached for default properties; show enum names, - or the type of non-enums (GH-15902) */ + /* This branch is reached if the constant AST was already evaluated and + * resulted in an object; show enum names, or the type of non-enums + * (GH-15902) */ zend_object *obj = Z_OBJ_P(value); zend_class_entry *class = obj->ce; if (class->ce_flags & ZEND_ACC_ENUM) {