Show enum cases in errors

Closes GH-14496
This commit is contained in:
Ilija Tovilo 2024-06-07 12:42:35 +02:00
parent a82d86479c
commit 998bce117c
No known key found for this signature in database
GPG Key ID: 5050C66BFCD1015A
7 changed files with 63 additions and 17 deletions

View File

@ -0,0 +1,22 @@
--TEST--
Enum case is shown in stack trace
--FILE--
<?php
enum Foo {
case Bar;
}
function test($enum) {
throw new Exception();
}
test(Foo::Bar);
?>
--EXPECTF--
Fatal error: Uncaught Exception in %s:%d
Stack trace:
#0 %s(%d): test(Foo::Bar)
#1 {main}
thrown in %s on line %d

View File

@ -0,0 +1,21 @@
--TEST--
Match errors show unmatched enum case
--FILE--
<?php
enum Foo {
case Bar;
case Baz;
}
try {
match (Foo::Bar) {
Foo::Baz => 42,
};
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Unhandled match case Foo::Bar

View File

@ -501,8 +501,7 @@ static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
ZVAL_DEREF(arg);
if (Z_TYPE_P(arg) <= IS_STRING) {
smart_str_append_scalar(str, arg, EG(exception_string_param_max_len));
if (smart_str_append_zval(str, arg, EG(exception_string_param_max_len)) == SUCCESS) {
smart_str_appends(str, ", ");
} else {
switch (Z_TYPE_P(arg)) {

View File

@ -873,14 +873,10 @@ ZEND_COLD zend_never_inline void zend_magic_get_property_type_inconsistency_erro
ZEND_COLD void zend_match_unhandled_error(const zval *value)
{
smart_str msg = {0};
if (Z_TYPE_P(value) <= IS_STRING) {
smart_str_append_scalar(&msg, value, EG(exception_string_param_max_len));
} else {
if (smart_str_append_zval(&msg, value, EG(exception_string_param_max_len)) != SUCCESS) {
smart_str_appendl(&msg, "of type ", sizeof("of type ")-1);
smart_str_appends(&msg, zend_zval_type_name(value));
}
smart_str_0(&msg);
zend_throw_exception_ex(

View File

@ -17,6 +17,7 @@
#include <zend.h>
#include "zend_smart_str.h"
#include "zend_smart_string.h"
#include "zend_enum.h"
#define SMART_STR_OVERHEAD (ZEND_MM_OVERHEAD + _ZSTR_HEADER_SIZE + 1)
#define SMART_STR_START_SIZE 256
@ -221,3 +222,17 @@ ZEND_API void ZEND_FASTCALL smart_str_append_scalar(smart_str *dest, const zval
EMPTY_SWITCH_DEFAULT_CASE();
}
}
ZEND_API zend_result ZEND_FASTCALL smart_str_append_zval(smart_str *dest, const zval *value, size_t truncate)
{
if (Z_TYPE_P(value) <= IS_STRING) {
smart_str_append_scalar(dest, value, truncate);
} else if (Z_TYPE_P(value) == IS_OBJECT && (Z_OBJCE_P(value)->ce_flags & ZEND_ACC_ENUM)) {
smart_str_append(dest, Z_OBJCE_P(value)->name);
smart_str_appends(dest, "::");
smart_str_append(dest, Z_STR_P(zend_enum_fetch_case_name(Z_OBJ_P(value))));
} else {
return FAILURE;
}
return SUCCESS;
}

View File

@ -34,6 +34,7 @@ ZEND_API void smart_str_append_printf(smart_str *dest, const char *format, ...)
ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
ZEND_API void ZEND_FASTCALL smart_str_append_escaped_truncated(smart_str *str, const zend_string *value, size_t length);
ZEND_API void ZEND_FASTCALL smart_str_append_scalar(smart_str *str, const zval *value, size_t truncate);
ZEND_API zend_result ZEND_FASTCALL smart_str_append_zval(smart_str *dest, const zval *value, size_t truncate);
END_EXTERN_C()
static zend_always_inline size_t smart_str_alloc(smart_str *str, size_t len, bool persistent) {

View File

@ -647,8 +647,8 @@ static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) {
}
static int format_default_value(smart_str *str, zval *value) {
if (Z_TYPE_P(value) <= IS_STRING) {
smart_str_append_scalar(str, value, SIZE_MAX);
if (smart_str_append_zval(str, value, SIZE_MAX) == SUCCESS) {
/* Nothing to do. */
} else if (Z_TYPE_P(value) == IS_ARRAY) {
zend_string *str_key;
zend_long num_key;
@ -675,14 +675,6 @@ static int format_default_value(smart_str *str, zval *value) {
format_default_value(str, zv);
} 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. */
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)));
} else {
ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST);
zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");