From d3af7240d9a81ff729b6208958df63c109cfa811 Mon Sep 17 00:00:00 2001 From: Shivam Mathur Date: Wed, 5 Aug 2026 12:27:48 +0530 Subject: [PATCH 1/4] Fix hMailServer URL in Windows CI (#23055) --- .github/scripts/windows/test_task.bat | 5 +++-- ext/standard/tests/mail/bug80751.phpt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/scripts/windows/test_task.bat b/.github/scripts/windows/test_task.bat index 0bfdaf664125..199a23430f5c 100644 --- a/.github/scripts/windows/test_task.bat +++ b/.github/scripts/windows/test_task.bat @@ -116,8 +116,9 @@ set PHP_BUILD_DIR=%PHP_BUILD_OBJ_DIR%\Release if "%THREAD_SAFE%" equ "1" set PHP_BUILD_DIR=%PHP_BUILD_DIR%_TS rem prepare for mail -curl -sLo hMailServer.exe https://www.hmailserver.com/download_file/?downloadid=271 -hMailServer.exe /verysilent +curl -sLo hMailServer.zip https://downloads.php.net/~windows/php-sdk/deps/vs18/x64/hmailserver-5.7.0-vs18-x64.zip +unzip -q hMailServer.zip -d hMailServer +hMailServer\bin\hMailServer.exe /verysilent cd %APPVEYOR_BUILD_FOLDER% %PHP_BUILD_DIR%\php.exe -dextension_dir=%PHP_BUILD_DIR% -dextension=com_dotnet appveyor\setup_hmailserver.php diff --git a/ext/standard/tests/mail/bug80751.phpt b/ext/standard/tests/mail/bug80751.phpt index fd4fa744fe3c..97cb0575f82d 100644 --- a/ext/standard/tests/mail/bug80751.phpt +++ b/ext/standard/tests/mail/bug80751.phpt @@ -37,7 +37,7 @@ function find_and_delete_message($username, $subject) { if ($info->subject === $subject) { $header = imap_fetchheader($imap_stream, $i); echo "Return-Path header found: "; - var_dump(strpos($header, 'Return-Path: joe@example.com') !== false); + var_dump(strpos($header, 'Return-Path: ') !== false); echo "To header found: "; var_dump(strpos($header, "To: \"\" <{$users[1]}@$domain>") !== false); echo "From header found: "; From a0336012739b35630a32674a484a7023433bde27 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:58:56 +0200 Subject: [PATCH 2/4] session: fix corruption in mod_mm --- ext/session/mod_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index b997a2bdcff5..75ee713e9f09 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -351,7 +351,7 @@ PS_READ_FUNC(mm) && ps_mm_key_exists(data, key) == FAILURE) { /* key points to PS(id), but cannot change here. */ if (key) { - efree(PS(id)); + zend_string_release_ex(PS(id), false); PS(id) = NULL; } PS(id) = PS(mod)->s_create_sid((void **)&data); From 9366c61247f797e611a09f14478fc75a0b4edd33 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 4 Aug 2026 21:00:40 +0200 Subject: [PATCH 3/4] Fix GH-23043: broken session id code can cause zend_mm_heap corrupted The id must be reset to NULL before calling code that can invoke userland code, as the id remains visible after release due to a stale pointer. Closes GH-23046. --- NEWS | 5 +++ ext/session/session.c | 3 ++ .../tests/user_session_module/gh23043.phpt | 35 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 ext/session/tests/user_session_module/gh23043.phpt diff --git a/NEWS b/NEWS index 378643836c80..474db936ef15 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,11 @@ PHP NEWS . Fixed segfault in ReflectionMethod::createFromMethodName() on an uninstantiable subclass. (iliaal) +- Session: + . Fix corruption in mod_mm. (ndossche) + . Fixed bug GH-23043 (broken session id code can cause zend_mm_heap + corrupted). (ndossche) + - Sockets: . Fixed various memory related issues in ext/sockets. (David Carlier) diff --git a/ext/session/session.c b/ext/session/session.c index ba71d709a536..6380505ae951 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -443,6 +443,7 @@ static zend_result php_session_initialize(void) /* {{{ */ if (!PS(id) || !ZSTR_VAL(PS(id))[0]) { if (PS(id)) { zend_string_release_ex(PS(id), 0); + PS(id) = NULL; } PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { @@ -460,6 +461,7 @@ static zend_result php_session_initialize(void) /* {{{ */ ) { if (PS(id)) { zend_string_release_ex(PS(id), 0); + PS(id) = NULL; } PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { @@ -2440,6 +2442,7 @@ PHP_FUNCTION(session_regenerate_id) /* Try to generate non-existing ID */ while (limit-- && PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == SUCCESS) { zend_string_release_ex(PS(id), 0); + PS(id) = NULL; PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { PS(mod)->s_close(&PS(mod_data)); diff --git a/ext/session/tests/user_session_module/gh23043.phpt b/ext/session/tests/user_session_module/gh23043.phpt new file mode 100644 index 000000000000..e3528884a79a --- /dev/null +++ b/ext/session/tests/user_session_module/gh23043.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-23043 (broken session id code can cause zend_mm_heap corrupted) +--EXTENSIONS-- +session +--CREDITS-- +lmaltsis +--FILE-- + +--EXPECTF-- +string(0) "" + +Warning: SessionHandler::write(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed in %s on line %d + +Warning: session_write_close(): Failed to write session data using user defined save handler. (session.save_path: , handler: a::write) in %s on line %d +string(0) "" + +Warning: SessionHandler::write(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed in Unknown on line 0 + +Warning: session_write_close(): Failed to write session data using user defined save handler. (session.save_path: , handler: a::write) in Unknown on line 0 From 3f8efc2f054ea230d8948e74dcb9b13e41273e90 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 5 Aug 2026 09:16:12 -0400 Subject: [PATCH 4/4] Reject embedded NUL in SimpleXMLElement path/URL constructor When dataIsURL is true, __construct parsed the path as a plain string and passed it to xmlReadFile, so an embedded NUL truncated the path. simplexml_load_file already rejects NULs via the path parameter type. Match that check before xmlReadFile. Closes GH-23069 --- NEWS | 4 +++ ext/simplexml/simplexml.c | 5 ++++ .../tests/bug_sxe_ctor_nul_path.phpt | 26 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 ext/simplexml/tests/bug_sxe_ctor_nul_path.phpt diff --git a/NEWS b/NEWS index 474db936ef15..06f35fa08ee4 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,10 @@ PHP NEWS . Fixed bug GH-23043 (broken session id code can cause zend_mm_heap corrupted). (ndossche) +- SimpleXML: + . Fixed SimpleXMLElement::__construct() accepting embedded null bytes in + URL/path mode. (iliaal) + - Sockets: . Fixed various memory related issues in ext/sockets. (David Carlier) diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 8cf8e657e58f..4ae396b3fe1d 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2334,6 +2334,11 @@ PHP_METHOD(SimpleXMLElement, __construct) RETURN_THROWS(); } + if (is_url && CHECK_NULL_PATH(data, data_len)) { + zend_argument_value_error(1, "must not contain any null bytes"); + RETURN_THROWS(); + } + PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory); docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options); PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory); diff --git a/ext/simplexml/tests/bug_sxe_ctor_nul_path.phpt b/ext/simplexml/tests/bug_sxe_ctor_nul_path.phpt new file mode 100644 index 000000000000..aea5396eac30 --- /dev/null +++ b/ext/simplexml/tests/bug_sxe_ctor_nul_path.phpt @@ -0,0 +1,26 @@ +--TEST-- +SimpleXMLElement constructor rejects embedded NUL in URL/path mode +--EXTENSIONS-- +simplexml +--FILE-- +'); +$path = $tmp . "\0evil"; +try { + new SimpleXMLElement($path, 0, true); + echo "ctor: loaded\n"; +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} +try { + simplexml_load_file($path); + echo "load_file: loaded\n"; +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} +unlink($tmp); +?> +--EXPECT-- +ValueError: SimpleXMLElement::__construct(): Argument #1 ($data) must not contain any null bytes +ValueError: simplexml_load_file(): Argument #1 ($filename) must not contain any null bytes