diff --git a/Zend/tests/enum_in_stack_trace.phpt b/Zend/tests/enum_in_stack_trace.phpt new file mode 100644 index 00000000000..05045f164ee --- /dev/null +++ b/Zend/tests/enum_in_stack_trace.phpt @@ -0,0 +1,22 @@ +--TEST-- +Enum case is shown in stack trace +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception in %s:%d +Stack trace: +#0 %s(%d): test(Foo::Bar) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/match/unmatched_enum.phpt b/Zend/tests/match/unmatched_enum.phpt new file mode 100644 index 00000000000..93f368a316b --- /dev/null +++ b/Zend/tests/match/unmatched_enum.phpt @@ -0,0 +1,21 @@ +--TEST-- +Match errors show unmatched enum case +--FILE-- + 42, + }; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Unhandled match case Foo::Bar diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 2c6a432096d..4af4ec2cfc0 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -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)) { diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index facd7239c74..3eb2930205e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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( diff --git a/Zend/zend_smart_str.c b/Zend/zend_smart_str.c index a1018273732..ade137a4bb6 100644 --- a/Zend/zend_smart_str.c +++ b/Zend/zend_smart_str.c @@ -17,6 +17,7 @@ #include #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; +} diff --git a/Zend/zend_smart_str.h b/Zend/zend_smart_str.h index e271835e41d..affbb5c50ac 100644 --- a/Zend/zend_smart_str.h +++ b/Zend/zend_smart_str.h @@ -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) { diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 88f2253e98a..f4386babef8 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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), "");