php-src/main
Niels Dossche bc558bf7a3
Fix GH-11078: PHP Fatal error triggers pointer being freed was not allocated and malloc: double free for ptr errors
Although the issue was demonstrated using Curl, the issue is purely in
the streams layer of PHP.

Full analysis is written in GH-11078 [1], but here is the brief version:
Here's what actually happens:
1) We're creating a FILE handle from a stream using the casting mechanism.
   This will create a cookie-based FILE handle using funopen.
2) We're reading stream data using fread from the userspace stream. This will
   temporarily set a buffer into a field _bf.base [2]. This buffer is now equal
   to the upload buffer that Curl allocated and note that that buffer is owned
   by Curl.
3) The fatal error occurs and we bail out from the fread function, notice how
   the reset code is never executed and so the buffer will still point to
   Curl's upload buffer instead of FILE's own buffer [3].
4) The resources are destroyed, this includes our opened stream and because the
   FILE handle is cached, it gets destroyed as well.
   In fact, the stream code calls through fclose on purpose in this case.
5) The fclose code frees the _bs.base buffer [4].
   However, this is not the buffer that FILE owns but the one that Curl owns
   because it isn't reset properly due to the bailout!
6) The objects are getting destroyed, and so the curl free logic is invoked.
   When Curl tries to gracefully clean up, it tries to free the buffer.
   But that buffer is actually already freed mistakingly by the C library!

This also explains why we can't reproduce it on Linux: this bizarre buffer
swapping only happens on macOS and BSD, not on Linux.

To solve this, we switch to an unbuffered mode for cookie-based FILEs.
This avoids any stateful problems related to buffers especially when the
bailout mechanism triggers. As streams have their own buffering
mechanism, I don't expect this to impact performance.

[1] https://github.com/php/php-src/issues/11078#issuecomment-2155616843
[2] 5e566be7a7/stdio/FreeBSD/fread.c (L102-L103)
[3] 5e566be7a7/stdio/FreeBSD/fread.c (L117)
[4] 5e566be7a7/stdio/FreeBSD/fclose.c (L66-L67)

Closes GH-14524.
2024-06-10 19:38:21 +02:00
..
streams Fix GH-11078: PHP Fatal error triggers pointer being freed was not allocated and malloc: double free for ptr errors 2024-06-10 19:38:21 +02:00
build-defs.h.in Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
explicit_bzero.c Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
fastcgi.c Fix undefined behaviour in fastcgi.c (#14269) 2024-05-19 22:54:06 +02:00
fastcgi.h Mark various functions with void arguments. 2021-05-12 14:55:53 +01:00
fopen_wrappers.c Fix GH-10692: PHP crashes on Windows when an inexistent filename is executed 2023-02-25 14:32:55 +00:00
fopen_wrappers.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
getopt.c Fixed some spaces used instead of tabs 2021-06-29 11:30:26 +02:00
http_status_codes.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
internal_functions_win32.c Implement Random Extension 2022-07-19 10:27:38 +01:00
internal_functions.c.in Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
main.c Fix GH-13931: Applying zero offset to null pointer in Zend/zend_opcode.c 2024-04-15 19:39:05 +02:00
network.c Merge branch 'PHP-8.1' into PHP-8.2 2023-09-24 15:19:02 +01:00
output.c Replace memcmp() with zend_string functions (#8216) 2022-03-31 16:27:58 +02:00
php_compat.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_content_types.c Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_content_types.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_getopt.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_globals.h Fix GH-8086: Introduce mail.mixed_lf_and_crlf INI 2023-01-19 19:05:39 +00:00
php_ini_builder.c sapi/*: move duplicate "--define" code to library 2022-04-18 16:52:08 +02:00
php_ini_builder.h sapi/*: move duplicate "--define" code to library 2022-04-18 16:52:08 +02:00
php_ini.c Initialise zend_stat_t to fix MSAN build 2022-05-22 16:06:27 +01:00
php_ini.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_main.h Minor refactoring of main/main.c and TSRM (#8608) 2022-05-24 08:34:55 +01:00
php_memory_streams.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_network.h Merge branch 'PHP-8.0' into PHP-8.1 2022-10-22 10:44:06 +02:00
php_odbc_utils.c Quote when adding to connection string in (PDO_)ODBC 2022-05-27 16:56:44 +02:00
php_odbc_utils.h Quote when adding to connection string in (PDO_)ODBC 2022-05-27 16:56:44 +02:00
php_open_temporary_file.c Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_open_temporary_file.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_output.h Remove unnecessary PHP_FUNCTION() declarations (#7472) 2021-09-07 10:04:00 +02:00
php_reentrancy.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_scandir.c Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_scandir.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
php_streams.h Fix stream fclose_stdiocast_flush_in_progress type 2023-11-22 20:39:30 -06:00
php_syslog.c Fix strict prototype for php_closelog 2022-06-19 22:56:44 +01:00
php_syslog.h Fix strict prototype for php_closelog 2022-06-19 22:56:44 +01:00
php_ticks.c Fix GH-10737: PHP 8.1.16 segfaults on line 597 of sapi/apache2handler/sapi_apache2.c 2023-04-08 16:34:07 +02:00
php_ticks.h Fix GH-10737: PHP 8.1.16 segfaults on line 597 of sapi/apache2handler/sapi_apache2.c 2023-04-08 16:34:07 +02:00
php_variables.c Merge branch 'PHP-8.1' into PHP-8.2 2024-04-09 23:49:31 -05:00
php_variables.h Fix bug #75712: getenv in php-fpm should not read $_ENV, $_SERVER 2024-02-04 11:58:18 +00:00
php_version.h PHP-8.2 is now for PHP 8.2.21-dev 2024-05-21 14:32:07 -04:00
php.h Replace reallocarray with safe_perealloc 2022-09-29 15:15:40 +02:00
reentrancy.c Implement Random Extension 2022-07-19 10:27:38 +01:00
rfc1867.c Merge branch 'PHP-8.1' into PHP-8.2 2023-02-14 11:00:20 +00:00
rfc1867.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
safe_bcmp.c Fix comment for php_safe_bcmp (#10306) 2023-01-12 23:30:36 +01:00
SAPI.c Merge branch 'PHP-8.1' 2022-08-29 22:34:48 +01:00
SAPI.h Merge branch 'PHP-8.1' 2022-08-29 22:34:48 +01:00
snprintf.c Bring minimum precision inline with spprintf 2023-01-30 19:00:42 +00:00
snprintf.h Remove FORMAT_CONV_MAX_PRECISION 2021-08-02 15:59:26 +02:00
spprintf.c Use memrchr() when available 2021-11-24 16:13:34 +03:00
spprintf.h Update http->https in license (#6945) 2021-05-06 12:16:35 +02:00
strlcat.c strlcpy/strlcat update to last openbsd version. 2022-04-28 15:09:55 +02:00
strlcpy.c strlcpy/strlcat update to last openbsd version. 2022-04-28 15:09:55 +02:00