mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Merge branch 'PHP-8.3'
* PHP-8.3: Fix GH-11078: PHP Fatal error triggers pointer being freed was not allocated and malloc: double free for ptr errors
This commit is contained in:
@@ -774,6 +774,38 @@ static ZEND_FUNCTION(zend_test_set_fmode)
|
||||
}
|
||||
#endif
|
||||
|
||||
static ZEND_FUNCTION(zend_test_cast_fread)
|
||||
{
|
||||
zval *stream_zv;
|
||||
php_stream *stream;
|
||||
FILE *fp;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_RESOURCE(stream_zv);
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_stream_from_zval(stream, stream_zv);
|
||||
|
||||
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t size = 10240; /* Must be large enough to trigger the issue */
|
||||
char *buf = malloc(size);
|
||||
bool bail = false;
|
||||
zend_try {
|
||||
(void) !fread(buf, 1, size, fp);
|
||||
} zend_catch {
|
||||
bail = true;
|
||||
} zend_end_try();
|
||||
|
||||
free(buf);
|
||||
|
||||
if (bail) {
|
||||
zend_bailout();
|
||||
}
|
||||
}
|
||||
|
||||
static zend_object *zend_test_class_new(zend_class_entry *class_type)
|
||||
{
|
||||
zend_object *obj = zend_objects_new(class_type);
|
||||
|
||||
@@ -281,6 +281,9 @@ function zend_test_override_libxml_global_state(): void {}
|
||||
#if defined(PHP_WIN32)
|
||||
function zend_test_set_fmode(bool $binary): void {}
|
||||
#endif
|
||||
|
||||
/** @param resource $stream */
|
||||
function zend_test_cast_fread($stream): void {}
|
||||
}
|
||||
|
||||
namespace ZendTestNS {
|
||||
|
||||
8
ext/zend_test/test_arginfo.h
generated
8
ext/zend_test/test_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 35c11b9781669cff5ad72aa78b9b3732f7b827f1 */
|
||||
* Stub hash: 810a94e09724a27d46c99495593da999cfc46243 */
|
||||
|
||||
ZEND_STATIC_ASSERT(PHP_VERSION_ID >= 80000, "test_arginfo.h only supports PHP version ID 80000 or newer, "
|
||||
"but it is included on an older PHP version");
|
||||
@@ -158,6 +158,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_set_fmode, 0, 1, IS_VO
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_cast_fread, 0, 1, IS_VOID, 0)
|
||||
ZEND_ARG_INFO(0, stream)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled
|
||||
|
||||
#define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return
|
||||
@@ -283,6 +287,7 @@ static ZEND_FUNCTION(zend_test_is_pcre_bundled);
|
||||
#if defined(PHP_WIN32)
|
||||
static ZEND_FUNCTION(zend_test_set_fmode);
|
||||
#endif
|
||||
static ZEND_FUNCTION(zend_test_cast_fread);
|
||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_func);
|
||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
|
||||
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func);
|
||||
@@ -379,6 +384,7 @@ static const zend_function_entry ext_functions[] = {
|
||||
#if defined(PHP_WIN32)
|
||||
ZEND_FE(zend_test_set_fmode, arginfo_zend_test_set_fmode)
|
||||
#endif
|
||||
ZEND_FE(zend_test_cast_fread, arginfo_zend_test_cast_fread)
|
||||
#if (PHP_VERSION_ID >= 80400)
|
||||
ZEND_RAW_FENTRY(ZEND_NS_NAME("ZendTestNS2", "namespaced_func"), zif_ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func, 0, NULL, NULL)
|
||||
#else
|
||||
|
||||
34
ext/zend_test/tests/gh11078.phpt
Normal file
34
ext/zend_test/tests/gh11078.phpt
Normal file
@@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
GH-11078 (PHP Fatal error triggers pointer being freed was not allocated and malloc: double free for ptr errors)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv('USE_ZEND_ALLOC') === '0') die('skip Zend MM disabled');
|
||||
if (PHP_OS_FAMILY === 'Windows') die('skip Windows does not support generic stream casting');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
const MEM = 32 * 1024 * 1024;
|
||||
ini_set('memory_limit', MEM);
|
||||
|
||||
class CrashingFifo {
|
||||
public $context;
|
||||
|
||||
function stream_open($path, $mode, $options, &$opened_path): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
function stream_read(int $count): false|string|null {
|
||||
return str_repeat('x', MEM);
|
||||
}
|
||||
}
|
||||
|
||||
stream_register_wrapper('fifo', CrashingFifo::class);
|
||||
$readStream = fopen('fifo://1', 'r');
|
||||
zend_test_cast_fread($readStream);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Allowed memory size of %d bytes exhausted %s
|
||||
@@ -46,7 +46,14 @@ typedef struct {
|
||||
|
||||
FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t *funcs)
|
||||
{
|
||||
return funopen(cookie, funcs->reader, funcs->writer, funcs->seeker, funcs->closer);
|
||||
FILE *file = funopen(cookie, funcs->reader, funcs->writer, funcs->seeker, funcs->closer);
|
||||
if (file) {
|
||||
/* Buffering of FILE handles is stateful.
|
||||
* A bailout during these can corrupt the state of the FILE handle
|
||||
* and cause memory corruption errors. See GH-11078. */
|
||||
setvbuf(file, NULL, _IONBF, 0);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
# define HAVE_FOPENCOOKIE 1
|
||||
# define PHP_EMULATE_FOPENCOOKIE 1
|
||||
|
||||
Reference in New Issue
Block a user