Merge branch 'PHP-8.2'

* PHP-8.2:
  Fix NUL byte in exception string terminating Exception::__toString()
This commit is contained in:
Ilija Tovilo 2023-03-19 10:51:05 +01:00
commit 2ec0134ee2
No known key found for this signature in database
GPG key ID: A4F5D403F118200A
3 changed files with 35 additions and 11 deletions

10
Zend/tests/gh10810.phpt Normal file
View file

@ -0,0 +1,10 @@
--TEST--
GH-10810: Fix NUL byte terminating Exception::__toString()
--FILE--
<?php
echo new \Exception("Hello\0World");
?>
--EXPECTF--
Exception: Hello%0World in %s:%d
Stack trace:
#0 {main}

View file

@ -671,24 +671,36 @@ ZEND_METHOD(Exception, __toString)
} }
if ((Z_OBJCE_P(exception) == zend_ce_type_error || Z_OBJCE_P(exception) == zend_ce_argument_count_error) && strstr(ZSTR_VAL(message), ", called in ")) { if ((Z_OBJCE_P(exception) == zend_ce_type_error || Z_OBJCE_P(exception) == zend_ce_argument_count_error) && strstr(ZSTR_VAL(message), ", called in ")) {
zend_string *real_message = zend_strpprintf(0, "%s and defined", ZSTR_VAL(message)); zval message_zv;
ZVAL_STR(&message_zv, message);
zend_string *real_message = zend_strpprintf_unchecked(0, "%Z and defined", &message_zv);
zend_string_release_ex(message, 0); zend_string_release_ex(message, 0);
message = real_message; message = real_message;
} }
zend_string *tmp_trace = (Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace))
? zend_string_copy(Z_STR(trace))
: ZSTR_INIT_LITERAL("#0 {main}\n", false);
zval name_zv, trace_zv, file_zv, prev_str_zv;
ZVAL_STR(&name_zv, Z_OBJCE_P(exception)->name);
ZVAL_STR(&trace_zv, tmp_trace);
ZVAL_STR(&file_zv, file);
ZVAL_STR(&prev_str_zv, prev_str);
if (ZSTR_LEN(message) > 0) { if (ZSTR_LEN(message) > 0) {
str = zend_strpprintf(0, "%s: %s in %s:" ZEND_LONG_FMT zval message_zv;
"\nStack trace:\n%s%s%s", ZVAL_STR(&message_zv, message);
ZSTR_VAL(Z_OBJCE_P(exception)->name), ZSTR_VAL(message), ZSTR_VAL(file), line,
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n", str = zend_strpprintf_unchecked(0, "%Z: %Z in %Z:" ZEND_LONG_FMT "\nStack trace:\n%Z%s%Z",
ZSTR_LEN(prev_str) ? "\n\nNext " : "", ZSTR_VAL(prev_str)); &name_zv, &message_zv, &file_zv, line,
&trace_zv, ZSTR_LEN(prev_str) ? "\n\nNext " : "", &prev_str_zv);
} else { } else {
str = zend_strpprintf(0, "%s in %s:" ZEND_LONG_FMT str = zend_strpprintf_unchecked(0, "%Z in %Z:" ZEND_LONG_FMT "\nStack trace:\n%Z%s%Z",
"\nStack trace:\n%s%s%s", &name_zv, &file_zv, line,
ZSTR_VAL(Z_OBJCE_P(exception)->name), ZSTR_VAL(file), line, &trace_zv, ZSTR_LEN(prev_str) ? "\n\nNext " : "", &prev_str_zv);
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
ZSTR_LEN(prev_str) ? "\n\nNext " : "", ZSTR_VAL(prev_str));
} }
zend_string_release_ex(tmp_trace, false);
zend_string_release_ex(prev_str, 0); zend_string_release_ex(prev_str, 0);
zend_string_release_ex(message, 0); zend_string_release_ex(message, 0);

View file

@ -149,6 +149,8 @@ END_EXTERN_C()
#define ZSTR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap) #define ZSTR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap)
#define ZSTR_INIT_LITERAL(s, persistent) (zend_string_init((s), strlen(s), (persistent)))
/*---*/ /*---*/
static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s) static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s)