Skip to content

Commit c0bb5b0

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Fix NUL byte in exception string terminating Exception::__toString()
2 parents e44b1a9 + b5726c2 commit c0bb5b0

File tree

4 files changed

+37
-11
lines changed

4 files changed

+37
-11
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ PHP NEWS
1717
apache). (nielsdos)
1818
. Fixed bug GH-10015 (zend_signal_handler_defer crashes on apache shutdown).
1919
(nielsdos)
20+
. Fixed bug GH-10810 (Fix NUL byte terminating Exception::__toString()).
21+
(ilutov)
2022

2123
- Date:
2224
. Fixed bug GH-10747 (Private and protected properties in serialized Date*

Zend/tests/gh10810.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
GH-10810: Fix NUL byte terminating Exception::__toString()
3+
--FILE--
4+
<?php
5+
echo new \Exception("Hello\0World");
6+
?>
7+
--EXPECTF--
8+
Exception: Hello%0World in %s:%d
9+
Stack trace:
10+
#0 {main}

Zend/zend_exceptions.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -685,24 +685,36 @@ ZEND_METHOD(Exception, __toString)
685685
}
686686

687687
if ((Z_OBJCE_P(exception) == zend_ce_type_error || Z_OBJCE_P(exception) == zend_ce_argument_count_error) && strstr(ZSTR_VAL(message), ", called in ")) {
688-
zend_string *real_message = zend_strpprintf(0, "%s and defined", ZSTR_VAL(message));
688+
zval message_zv;
689+
ZVAL_STR(&message_zv, message);
690+
zend_string *real_message = zend_strpprintf_unchecked(0, "%Z and defined", &message_zv);
689691
zend_string_release_ex(message, 0);
690692
message = real_message;
691693
}
692694

695+
zend_string *tmp_trace = (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace))
696+
? zend_string_copy(Z_STR(trace))
697+
: ZSTR_INIT_LITERAL("#0 {main}\n", false);
698+
699+
zval name_zv, trace_zv, file_zv, prev_str_zv;
700+
ZVAL_STR(&name_zv, Z_OBJCE_P(exception)->name);
701+
ZVAL_STR(&trace_zv, tmp_trace);
702+
ZVAL_STR(&file_zv, file);
703+
ZVAL_STR(&prev_str_zv, prev_str);
704+
693705
if (ZSTR_LEN(message) > 0) {
694-
str = zend_strpprintf(0, "%s: %s in %s:" ZEND_LONG_FMT
695-
"\nStack trace:\n%s%s%s",
696-
ZSTR_VAL(Z_OBJCE_P(exception)->name), ZSTR_VAL(message), ZSTR_VAL(file), line,
697-
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
698-
ZSTR_LEN(prev_str) ? "\n\nNext " : "", ZSTR_VAL(prev_str));
706+
zval message_zv;
707+
ZVAL_STR(&message_zv, message);
708+
709+
str = zend_strpprintf_unchecked(0, "%Z: %Z in %Z:" ZEND_LONG_FMT "\nStack trace:\n%Z%s%Z",
710+
&name_zv, &message_zv, &file_zv, line,
711+
&trace_zv, ZSTR_LEN(prev_str) ? "\n\nNext " : "", &prev_str_zv);
699712
} else {
700-
str = zend_strpprintf(0, "%s in %s:" ZEND_LONG_FMT
701-
"\nStack trace:\n%s%s%s",
702-
ZSTR_VAL(Z_OBJCE_P(exception)->name), ZSTR_VAL(file), line,
703-
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
704-
ZSTR_LEN(prev_str) ? "\n\nNext " : "", ZSTR_VAL(prev_str));
713+
str = zend_strpprintf_unchecked(0, "%Z in %Z:" ZEND_LONG_FMT "\nStack trace:\n%Z%s%Z",
714+
&name_zv, &file_zv, line,
715+
&trace_zv, ZSTR_LEN(prev_str) ? "\n\nNext " : "", &prev_str_zv);
705716
}
717+
zend_string_release_ex(tmp_trace, false);
706718

707719
zend_string_release_ex(prev_str, 0);
708720
zend_string_release_ex(message, 0);

Zend/zend_string.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ END_EXTERN_C()
108108

109109
#define ZSTR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap)
110110

111+
#define ZSTR_INIT_LITERAL(s, persistent) (zend_string_init((s), strlen(s), (persistent)))
112+
111113
/*---*/
112114

113115
static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s)

0 commit comments

Comments
 (0)