From 4befeec38a8ce5880f74a0c7578ef0b1f60ad555 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 13 Jul 2026 14:30:19 -0700 Subject: [PATCH 1/2] Add regression tests for `ReflectionEnum::__toString()` with null bytes So that when the output is fixed the changes can be confirmed in tests --- .../gh22681/ReflectionEnum_backed_value.phpt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt diff --git a/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt b/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt new file mode 100644 index 000000000000..8131a3adafed --- /dev/null +++ b/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt @@ -0,0 +1,61 @@ +--TEST-- +GH-22681: null bytes in backed value truncate ReflectionEnum::__toString() +--FILE-- +getBackingValue() ); +?> +--EXPECTF-- +Enum [ enum Demo: string implements UnitEnum, BackedEnum ] { + @@ %s %d-%d + + - Enum cases [1] { + Case DEMO = F + } + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [3] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + + Method [ static public method from ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ static ] + } + + Method [ static public method tryFrom ] { + + - Parameters [1] { + Parameter #0 [ string|int $value ] + } + - Return [ ?static ] + } + } + + - Properties [2] { + Property [ public protected(set) readonly string $name ] + Property [ public protected(set) readonly string $value ] + } + + - Methods [0] { + } +} +string(4) "F%0oo" From d100d51bfcff43ae817f5017e93b1f9d14a4fce6 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 13 Jul 2026 14:34:10 -0700 Subject: [PATCH 2/2] GH-22681: avoid truncation on null bytes in `ReflectionEnum::__toString()` --- ext/reflection/php_reflection.c | 8 ++++++-- .../tests/gh22681/ReflectionEnum_backed_value.phpt | 2 +- .../tests/gh22681/ReflectionEnum_case_doc_comment.phpt | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index a3e996b654c1..bf7fde62d499 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -677,7 +677,9 @@ static void _enum_case_string(smart_str *str, const zend_string *name, zend_clas } if (c->doc_comment) { - smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(c->doc_comment)); + smart_str_appends(str, indent); + smart_str_append(str, c->doc_comment); + smart_str_appendc(str, '\n'); } smart_str_append_printf(str, "%sCase %s", indent, ZSTR_VAL(name)); if (c->ce->enum_backing_type == IS_UNDEF) { @@ -691,7 +693,9 @@ static void _enum_case_string(smart_str *str, const zend_string *name, zend_clas zval *enum_val = zend_enum_fetch_case_value(Z_OBJ(c->value)); zend_string *tmp_value_str; zend_string *value_str = zval_get_tmp_string(enum_val, &tmp_value_str); - smart_str_append_printf(str, " = %s\n", ZSTR_VAL(value_str)); + smart_str_appends(str, " = "); + smart_str_append(str, value_str); + smart_str_appendc(str, '\n'); zend_tmp_string_release(tmp_value_str); } } diff --git a/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt b/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt index 8131a3adafed..f28c39daa100 100644 --- a/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt +++ b/ext/reflection/tests/gh22681/ReflectionEnum_backed_value.phpt @@ -16,7 +16,7 @@ Enum [ enum Demo: string implements UnitEnum, BackedEnum ] { @@ %s %d-%d - Enum cases [1] { - Case DEMO = F + Case DEMO = F%0oo } - Constants [0] { diff --git a/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt b/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt index 68bde0bed637..3945ad8639e7 100644 --- a/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt +++ b/ext/reflection/tests/gh22681/ReflectionEnum_case_doc_comment.phpt @@ -20,7 +20,7 @@ Enum [ enum Demo implements UnitEnum ] { @@ %s(%d) : eval()'d code %d-%d - Enum cases [1] { - /** F + /** F%0oo */ Case C }