1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

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.
Closes GH-17781.
This commit is contained in:
Daniel Scherzer
2025-02-12 18:42:57 -08:00
committed by Niels Dossche
parent 260e0e9bd3
commit ca0414e64d
6 changed files with 131 additions and 5 deletions

4
NEWS
View File

@@ -51,6 +51,10 @@ PHP NEWS
. Partially fixed bug GH-17387 (Trivial crash in phpdbg lexer). (nielsdos)
. Fix memory leak in phpdbg calling registered function. (nielsdos)
- Reflection:
. Fixed bug GH-15902 (Core dumped in ext/reflection/php_reflection.c).
(DanielEScherzer)
- Streams:
. Fixed bug GH-17650 (realloc with size 0 in user_filters.c). (nielsdos)
. Fix memory leak on overflow in _php_stream_scandir(). (nielsdos)

View File

@@ -649,13 +649,20 @@ 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 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;
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), "");

View File

@@ -0,0 +1,37 @@
--TEST--
ReflectionClass object default property - used to say "callable"
--INI--
opcache.enable_cli=0
--FILE--
<?php
class C {
public stdClass $a = FOO;
}
define('FOO', new stdClass);
new C;
$reflector = new ReflectionClass(C::class);
echo $reflector;
?>
--EXPECTF--
Class [ <user> 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] {
}
}

View File

@@ -0,0 +1,38 @@
--TEST--
ReflectionClass object default property - used to say "__CLASS__"
--INI--
opcache.enable_cli=0
--FILE--
<?php
class C {
public stdClass $a = FOO;
}
$reflector = new ReflectionClass(C::class);
define('FOO', new stdClass);
new C;
echo $reflector;
?>
--EXPECTF--
Class [ <user> 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] {
}
}

View File

@@ -0,0 +1,20 @@
--TEST--
ReflectionProperty object default - used to say "callable"
--INI--
opcache.enable_cli=0
--FILE--
<?php
class C {
public stdClass $a = FOO;
}
define('FOO', new stdClass);
new C;
$reflector = new ReflectionProperty(C::class, 'a');
echo $reflector;
?>
--EXPECTF--
Property [ public stdClass $a = object(stdClass) ]

View File

@@ -0,0 +1,20 @@
--TEST--
ReflectionProperty object default - used to say "__CLASS__"
--INI--
opcache.enable_cli=0
--FILE--
<?php
class C {
public stdClass $a = FOO;
}
$reflector = new ReflectionProperty(C::class, 'a');
define('FOO', new stdClass);
new C;
echo $reflector;
?>
--EXPECTF--
Property [ public stdClass $a = object(stdClass) ]