Description
Description
The following code:
<?php
throw new \Exception("Hello\0World");
Resulted in this output:
Fatal error: Uncaught Exception: Hello in /tmp/preview:3
Stack trace:
#0 {main}
thrown in /tmp/preview on line 3
But I expected this output instead:
Fatal error: Uncaught Exception: HelloWorld in /tmp/preview:3
Stack trace:
#0 {main}
thrown in /tmp/preview on line 3
or
Fatal error: Uncaught Exception: Hello\x00World in /tmp/preview:3
Stack trace:
#0 {main}
thrown in /tmp/preview on line 3
Notes
Thanks to this strange behavior, I discovered that Zend strings are perfectly able to handle the \0
character.
But to call the function zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
, some callers may convert a zend string to a raw C string, losing the actual size. Then, the newly created zend string will stop at the first \0
, loosing the end of the string.
I didn't found any risk with this bug, since sensitive functions seem to look explicitly for this kind of abuse. Just to notice that some error messages may be truncated if they contain this null byte.
Here are some other examples:
<?php
call_user_func("Hello\0World");
$str = "Hello\0World";
new $str;
assert(false, "Hello\0World");
💡 It may be relevant to prefer the function zend_throw_exception_zstr
when possible, to prevent to lose the actual length of the zend string.
Thanks for your amazing work 🙂 👍
PHP Version
PHP 8.0, 8.1, 8.2
Operating System
No response