Skip to content

Commit

Permalink
Reflection: show the type of object constants used as default properties
Browse files Browse the repository at this point in the history
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`, `__CLASS__`, or `...`.

Instead, if the default value is an object (`IS_OBJECT`), show the type of that
object.

Add test cases for each of the `callable`, `__CLASS__`, and `...` cases to
confirm that they all now properly show the type of the constant.

Closes gh-15902
  • Loading branch information
DanielEScherzer committed Oct 17, 2024
1 parent 41af933 commit 033eec7
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 5 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ PHP NEWS
- PHPDBG:
. Fixed bug GH-16174 (Empty string is an invalid expression for ev). (cmb)

- Reflection:
. Fixed bug GH-15902 (Core dumped in ext/reflection/php_reflection.c).
(DanielEScherzer)

- Session:
. Fixed bug GH-16385 (Unexpected null returned by session_set_cookie_params).
(nielsdos)
Expand Down
16 changes: 11 additions & 5 deletions ext/reflection/php_reflection.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,13 +639,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), "");
Expand Down
36 changes: 36 additions & 0 deletions ext/reflection/tests/gh15902/ReflectionClass-callable.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
ReflectionClass object default property - used to say "callable"
--FILE--
<?php

class C {
public stdClass $a = FOO;
}
define('FOO', new stdClass);

new C;

$reflector = new ReflectionClass(C::class);
var_dump( (string)$reflector );
?>
--EXPECTF--
string(%d) "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] {
}
}
"
37 changes: 37 additions & 0 deletions ext/reflection/tests/gh15902/ReflectionClass-class.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
ReflectionClass object default property - used to say "__CLASS__"
--FILE--
<?php

class C {
public stdClass $a = FOO;
}
$reflector = new ReflectionClass(C::class);

define('FOO', new stdClass);
new C;

var_dump( (string)$reflector );

?>
--EXPECTF--
string(%d) "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] {
}
}
"
19 changes: 19 additions & 0 deletions ext/reflection/tests/gh15902/ReflectionProperty-callable.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
ReflectionProperty object default - used to say "callable"
--FILE--
<?php

class C {
public stdClass $a = FOO;
}
define('FOO', new stdClass);

new C;

$reflector = new ReflectionProperty(C::class, 'a');
var_dump( (string)$reflector );

?>
--EXPECTF--
string(%d) "Property [ public stdClass $a = object(stdClass) ]
"
19 changes: 19 additions & 0 deletions ext/reflection/tests/gh15902/ReflectionProperty-class.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
ReflectionProperty object default - used to say "__CLASS__"
--FILE--
<?php

class C {
public stdClass $a = FOO;
}
$reflector = new ReflectionProperty(C::class, 'a');

define('FOO', new stdClass);
new C;

var_dump( (string)$reflector );

?>
--EXPECTF--
string(%d) "Property [ public stdClass $a = object(stdClass) ]
"

0 comments on commit 033eec7

Please sign in to comment.