From 4fd99925617be65f19c2a026610041c86777f8a2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:31:40 +0100 Subject: [PATCH 1/3] Fix OSS-Fuzz #403308724 Because simple hooks can be nested without starting a new context, we need to restore the old property info in case of nested hooks. Closes GH-18074. --- NEWS | 1 + .../property_hooks/oss_fuzz_403308724.phpt | 30 +++++++++++++++++++ Zend/zend_compile.c | 4 +-- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/property_hooks/oss_fuzz_403308724.phpt diff --git a/NEWS b/NEWS index 805363ed24807..f912002aebdbf 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,7 @@ PHP NEWS (Arnaud) . Fixed bug GH-15367 (dl() of module with aliased class crashes in shutdown). (Arnaud) + . Fixed OSS-Fuzz #403308724. (nielsdos) - DBA: . Fixed assertion violation when opening the same file with dba_open diff --git a/Zend/tests/property_hooks/oss_fuzz_403308724.phpt b/Zend/tests/property_hooks/oss_fuzz_403308724.phpt new file mode 100644 index 0000000000000..b27b08dd703b6 --- /dev/null +++ b/Zend/tests/property_hooks/oss_fuzz_403308724.phpt @@ -0,0 +1,30 @@ +--TEST-- +OSS-Fuzz #403308724 +--FILE-- + 1; } +} + +class Test extends Base { + public $y { + get => [new class { + public $inner {get => __PROPERTY__;} + }, parent::$y::get()]; + } +} + +$test = new Test; +$y = $test->y; +var_dump($y); +var_dump($y[0]->inner); +?> +--EXPECT-- +array(2) { + [0]=> + object(class@anonymous)#2 (0) { + } + [1]=> + int(1) +} +string(5) "inner" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ef75b45ad0528..832dedc421042 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8645,7 +8645,7 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f /* FIXME: This is a dirty fix to maintain ABI compatibility. We don't * have an actual property info yet, but we really only need the name * anyway. We should convert this to a zend_string. */ - ZEND_ASSERT(!CG(context).active_property_info); + const zend_property_info *old_active_property_info = CG(context).active_property_info; zend_property_info dummy_prop_info = { .name = name }; CG(context).active_property_info = &dummy_prop_info; @@ -8742,7 +8742,7 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f zend_compile_attributes(&info->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, 0); } - CG(context).active_property_info = NULL; + CG(context).active_property_info = old_active_property_info; } } /* }}} */ From 45fc03c190002f0a76fda604b0d7703ec87b0b1f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 15 Mar 2025 19:35:14 +0100 Subject: [PATCH 2/3] Fix mysql test date flakiness Separate date() calls can lead to diverging results. Closes GH-18080 --- ...mysqli_fetch_all_data_types_variation.phpt | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt b/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt index 69fc427001fd0..594980ec0f829 100644 --- a/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt +++ b/ext/mysqli/tests/fetch/mysqli_fetch_all_data_types_variation.phpt @@ -122,22 +122,27 @@ func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", "99999999.99", "99999999. func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", NULL, NULL, 400); // don't care about date() strict TZ warnings... -func_mysqli_fetch_all($link, $engine, "DATE", @date('Y-m-d'), @date('Y-m-d'), 410); -func_mysqli_fetch_all($link, $engine, "DATE NOT NULL", @date('Y-m-d'), @date('Y-m-d'), 420); +$date = @date('Y-m-d'); +$datetime = @date('Y-m-d H:i:s'); +$time = @date('H:i:s'); +$year = @date('Y'); + +func_mysqli_fetch_all($link, $engine, "DATE", $date, $date, 410); +func_mysqli_fetch_all($link, $engine, "DATE NOT NULL", $date, $date, 420); func_mysqli_fetch_all($link, $engine, "DATE", NULL, NULL, 430); -func_mysqli_fetch_all($link, $engine, "DATETIME", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 440); -func_mysqli_fetch_all($link, $engine, "DATETIME NOT NULL", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 450); +func_mysqli_fetch_all($link, $engine, "DATETIME", $datetime, $datetime, 440); +func_mysqli_fetch_all($link, $engine, "DATETIME NOT NULL", $datetime, $datetime, 450); func_mysqli_fetch_all($link, $engine, "DATETIME", NULL, NULL, 460); -func_mysqli_fetch_all($link, $engine, "TIMESTAMP", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 470); +func_mysqli_fetch_all($link, $engine, "TIMESTAMP", $datetime, $datetime, 470); -func_mysqli_fetch_all($link, $engine, "TIME", @date('H:i:s'), @date('H:i:s'), 480); -func_mysqli_fetch_all($link, $engine, "TIME NOT NULL", @date('H:i:s'), @date('H:i:s'), 490); +func_mysqli_fetch_all($link, $engine, "TIME", $time, $time, 480); +func_mysqli_fetch_all($link, $engine, "TIME NOT NULL", $time, $time, 490); func_mysqli_fetch_all($link, $engine, "TIME", NULL, NULL, 500); -func_mysqli_fetch_all($link, $engine, "YEAR", @date('Y'), @date('Y'), 510); -func_mysqli_fetch_all($link, $engine, "YEAR NOT NULL", @date('Y'), @date('Y'), 520); +func_mysqli_fetch_all($link, $engine, "YEAR", $year, $year, 510); +func_mysqli_fetch_all($link, $engine, "YEAR NOT NULL", $year, $year, 520); func_mysqli_fetch_all($link, $engine, "YEAR", NULL, NULL, 530); $string255 = func_mysqli_fetch_array_make_string(255); From 38e553e4182437111432841651cca1c6ce2a8632 Mon Sep 17 00:00:00 2001 From: Katherine456719 Date: Sat, 15 Mar 2025 23:24:06 +0200 Subject: [PATCH 3/3] Fix GH-18082: Memory leaks in fuzzer SAPI error paths Closes GH-18081. --- NEWS | 4 ++++ sapi/fuzzer/fuzzer-json.c | 11 +++++------ sapi/fuzzer/fuzzer-mbregex.c | 9 +++++---- sapi/fuzzer/fuzzer-unserialize.c | 7 ++++--- sapi/fuzzer/fuzzer-unserializehash.c | 8 ++++---- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index 8c9400b4a66c3..59b66e85f84f9 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,10 @@ PHP NEWS - Embed: . Fixed bug GH-8533 (Unable to link dynamic libphp on Mac). (Kévin Dunglas) +- Fuzzer: + . Fixed bug GH-18081 (Memory leaks in error paths of fuzzer SAPI). + (Lung-Alexandra) + - Mbstring: . Fixed bug GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes). (nielsdos) diff --git a/sapi/fuzzer/fuzzer-json.c b/sapi/fuzzer/fuzzer-json.c index 4335598bc3caa..f5c00d77d9942 100644 --- a/sapi/fuzzer/fuzzer-json.c +++ b/sapi/fuzzer/fuzzer-json.c @@ -15,8 +15,6 @@ +----------------------------------------------------------------------+ */ - - #include "fuzzer.h" #include "Zend/zend.h" @@ -31,14 +29,15 @@ #include "ext/json/php_json_parser.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - char *data = malloc(Size+1); - memcpy(data, Data, Size); - data[Size] = '\0'; - if (fuzzer_request_startup() == FAILURE) { + if (fuzzer_request_startup() == FAILURE){ return 0; } + char *data = malloc(Size + 1); + memcpy(data, Data, Size); + data[Size] = '\0'; + for (int option = 0; option <=1; ++option) { zval result; php_json_parser parser; diff --git a/sapi/fuzzer/fuzzer-mbregex.c b/sapi/fuzzer/fuzzer-mbregex.c index 970a7b5baeedb..afcd2b5c1ba7e 100644 --- a/sapi/fuzzer/fuzzer-mbregex.c +++ b/sapi/fuzzer/fuzzer-mbregex.c @@ -30,15 +30,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { #ifdef HAVE_MBREGEX - char *args[2]; - char *data = malloc(Size+1); - memcpy(data, Data, Size); - data[Size] = '\0'; if (fuzzer_request_startup() == FAILURE) { return 0; } + char *args[2]; + char *data = malloc(Size+1); + memcpy(data, Data, Size); + data[Size] = '\0'; + fuzzer_setup_dummy_frame(); args[0] = data; diff --git a/sapi/fuzzer/fuzzer-unserialize.c b/sapi/fuzzer/fuzzer-unserialize.c index ff26e5b1e8da3..d58b35ca32bd1 100644 --- a/sapi/fuzzer/fuzzer-unserialize.c +++ b/sapi/fuzzer/fuzzer-unserialize.c @@ -30,14 +30,15 @@ #include "ext/standard/php_var.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - unsigned char *orig_data = malloc(Size+1); - memcpy(orig_data, Data, Size); - orig_data[Size] = '\0'; if (fuzzer_request_startup() == FAILURE) { return 0; } + unsigned char *orig_data = malloc(Size+1); + memcpy(orig_data, Data, Size); + orig_data[Size] = '\0'; + fuzzer_setup_dummy_frame(); { diff --git a/sapi/fuzzer/fuzzer-unserializehash.c b/sapi/fuzzer/fuzzer-unserializehash.c index 5d29eb5fb8c61..03c64dcbca017 100644 --- a/sapi/fuzzer/fuzzer-unserializehash.c +++ b/sapi/fuzzer/fuzzer-unserializehash.c @@ -34,15 +34,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t FullSize) { } ++Start; + if (fuzzer_request_startup() == FAILURE) { + return 0; + } + size_t Size = (Data + FullSize) - Start; unsigned char *orig_data = malloc(Size+1); memcpy(orig_data, Start, Size); orig_data[Size] = '\0'; - if (fuzzer_request_startup() == FAILURE) { - return 0; - } - fuzzer_setup_dummy_frame(); {