Skip to content

Commit 998bce1

Browse files
committed
Show enum cases in errors
Closes GH-14496
1 parent a82d864 commit 998bce1

File tree

7 files changed

+63
-17
lines changed

7 files changed

+63
-17
lines changed

Zend/tests/enum_in_stack_trace.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Enum case is shown in stack trace
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
}
9+
10+
function test($enum) {
11+
throw new Exception();
12+
}
13+
14+
test(Foo::Bar);
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught Exception in %s:%d
19+
Stack trace:
20+
#0 %s(%d): test(Foo::Bar)
21+
#1 {main}
22+
thrown in %s on line %d

Zend/tests/match/unmatched_enum.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Match errors show unmatched enum case
3+
--FILE--
4+
<?php
5+
6+
enum Foo {
7+
case Bar;
8+
case Baz;
9+
}
10+
11+
try {
12+
match (Foo::Bar) {
13+
Foo::Baz => 42,
14+
};
15+
} catch (Error $e) {
16+
echo $e->getMessage(), "\n";
17+
}
18+
19+
?>
20+
--EXPECT--
21+
Unhandled match case Foo::Bar

Zend/zend_exceptions.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,7 @@ static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
501501

502502
ZVAL_DEREF(arg);
503503

504-
if (Z_TYPE_P(arg) <= IS_STRING) {
505-
smart_str_append_scalar(str, arg, EG(exception_string_param_max_len));
504+
if (smart_str_append_zval(str, arg, EG(exception_string_param_max_len)) == SUCCESS) {
506505
smart_str_appends(str, ", ");
507506
} else {
508507
switch (Z_TYPE_P(arg)) {

Zend/zend_execute.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -873,14 +873,10 @@ ZEND_COLD zend_never_inline void zend_magic_get_property_type_inconsistency_erro
873873
ZEND_COLD void zend_match_unhandled_error(const zval *value)
874874
{
875875
smart_str msg = {0};
876-
877-
if (Z_TYPE_P(value) <= IS_STRING) {
878-
smart_str_append_scalar(&msg, value, EG(exception_string_param_max_len));
879-
} else {
876+
if (smart_str_append_zval(&msg, value, EG(exception_string_param_max_len)) != SUCCESS) {
880877
smart_str_appendl(&msg, "of type ", sizeof("of type ")-1);
881878
smart_str_appends(&msg, zend_zval_type_name(value));
882879
}
883-
884880
smart_str_0(&msg);
885881

886882
zend_throw_exception_ex(

Zend/zend_smart_str.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <zend.h>
1818
#include "zend_smart_str.h"
1919
#include "zend_smart_string.h"
20+
#include "zend_enum.h"
2021

2122
#define SMART_STR_OVERHEAD (ZEND_MM_OVERHEAD + _ZSTR_HEADER_SIZE + 1)
2223
#define SMART_STR_START_SIZE 256
@@ -221,3 +222,17 @@ ZEND_API void ZEND_FASTCALL smart_str_append_scalar(smart_str *dest, const zval
221222
EMPTY_SWITCH_DEFAULT_CASE();
222223
}
223224
}
225+
226+
ZEND_API zend_result ZEND_FASTCALL smart_str_append_zval(smart_str *dest, const zval *value, size_t truncate)
227+
{
228+
if (Z_TYPE_P(value) <= IS_STRING) {
229+
smart_str_append_scalar(dest, value, truncate);
230+
} else if (Z_TYPE_P(value) == IS_OBJECT && (Z_OBJCE_P(value)->ce_flags & ZEND_ACC_ENUM)) {
231+
smart_str_append(dest, Z_OBJCE_P(value)->name);
232+
smart_str_appends(dest, "::");
233+
smart_str_append(dest, Z_STR_P(zend_enum_fetch_case_name(Z_OBJ_P(value))));
234+
} else {
235+
return FAILURE;
236+
}
237+
return SUCCESS;
238+
}

Zend/zend_smart_str.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ ZEND_API void smart_str_append_printf(smart_str *dest, const char *format, ...)
3434
ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
3535
ZEND_API void ZEND_FASTCALL smart_str_append_escaped_truncated(smart_str *str, const zend_string *value, size_t length);
3636
ZEND_API void ZEND_FASTCALL smart_str_append_scalar(smart_str *str, const zval *value, size_t truncate);
37+
ZEND_API zend_result ZEND_FASTCALL smart_str_append_zval(smart_str *dest, const zval *value, size_t truncate);
3738
END_EXTERN_C()
3839

3940
static zend_always_inline size_t smart_str_alloc(smart_str *str, size_t len, bool persistent) {

ext/reflection/php_reflection.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -647,8 +647,8 @@ static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) {
647647
}
648648

649649
static int format_default_value(smart_str *str, zval *value) {
650-
if (Z_TYPE_P(value) <= IS_STRING) {
651-
smart_str_append_scalar(str, value, SIZE_MAX);
650+
if (smart_str_append_zval(str, value, SIZE_MAX) == SUCCESS) {
651+
/* Nothing to do. */
652652
} else if (Z_TYPE_P(value) == IS_ARRAY) {
653653
zend_string *str_key;
654654
zend_long num_key;
@@ -675,14 +675,6 @@ static int format_default_value(smart_str *str, zval *value) {
675675
format_default_value(str, zv);
676676
} ZEND_HASH_FOREACH_END();
677677
smart_str_appendc(str, ']');
678-
} else if (Z_TYPE_P(value) == IS_OBJECT) {
679-
/* This branch may only be reached for default properties, which don't support arbitrary objects. */
680-
zend_object *obj = Z_OBJ_P(value);
681-
zend_class_entry *class = obj->ce;
682-
ZEND_ASSERT(class->ce_flags & ZEND_ACC_ENUM);
683-
smart_str_append(str, class->name);
684-
smart_str_appends(str, "::");
685-
smart_str_append(str, Z_STR_P(zend_enum_fetch_case_name(obj)));
686678
} else {
687679
ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST);
688680
zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");

0 commit comments

Comments
 (0)