From b20843e56348668a139561830ce0ea49010bfed0 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Sun, 8 Nov 2026 15:35:23 +0000 Subject: [PATCH 1/2] Fixed heap corruption on shutdown of a Windows process that fell back the file cache --- NEWS | 2 + ext/opcache/ZendAccelerator.c | 8 ++- .../tests/file_cache_fallback_win32.phpt | 70 +++++++++++++++++++ ext/opcache/tests/gh18417.phpt | 11 +-- 4 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 ext/opcache/tests/file_cache_fallback_win32.phpt diff --git a/NEWS b/NEWS index 3cd0dcfc86d6..8e197ef0ac68 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ PHP NEWS (Ilia Alshanetsky) . Fixed bug GH-25195 (smm_shared_globals left dangling without an SHM backend). (Lazizbek Ergashev) + . Fixed heap corruption on shutdown of a Windows process that fell back to + the file cache. (Kamil Tekiela) - SOAP: . Fixed bug GH-25267 (NULL dereference in to_xml_any() with integer key). diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index c1248404270d..f606d1c23ccb 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3549,7 +3549,13 @@ void accel_shutdown(void) orig_post_shutdown_cb = zend_post_shutdown_cb; zend_post_shutdown_cb = accel_post_shutdown; } else { - free(accel_shared_globals); +#if ENABLE_FILE_CACHE_FALLBACK + /* A fallback process maps accel_shared_globals from SHM; it did not allocate it. */ + if (!fallback_process) +#endif + { + free(accel_shared_globals); + } } zend_compile_file = accelerator_orig_compile_file; diff --git a/ext/opcache/tests/file_cache_fallback_win32.phpt b/ext/opcache/tests/file_cache_fallback_win32.phpt new file mode 100644 index 000000000000..a88083c41281 --- /dev/null +++ b/ext/opcache/tests/file_cache_fallback_win32.phpt @@ -0,0 +1,70 @@ +--TEST-- +Shutdown of a process that fell back to the file cache must not free the SHM globals +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_cache_only=0 +--SKIPIF-- + +--FILE-- + ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes, null, $env); +echo stream_get_contents($pipes[1]); +echo stream_get_contents($pipes[2]); +printf("exit code: 0x%08X\n", proc_close($proc) & 0xFFFFFFFF); +?> +--CLEAN-- +isDir() ? @rmdir($f->getPathname()) : @unlink($f->getPathname()); +} +@rmdir($base); +?> +--EXPECT-- +bool(true) +exit code: 0x00000000 diff --git a/ext/opcache/tests/gh18417.phpt b/ext/opcache/tests/gh18417.phpt index f4f430827b3a..65a5eaf23268 100644 --- a/ext/opcache/tests/gh18417.phpt +++ b/ext/opcache/tests/gh18417.phpt @@ -1,11 +1,14 @@ --TEST-- GH-18417 (Windows SHM reattachment fails when increasing memory_consumption or jit_buffer_size) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_cache_only=0 --SKIPIF-- --FILE-- Date: Sun, 8 Nov 2026 16:28:24 +0000 Subject: [PATCH 2/2] Update file_cache_fallback_win32.phpt --- ext/opcache/tests/file_cache_fallback_win32.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/tests/file_cache_fallback_win32.phpt b/ext/opcache/tests/file_cache_fallback_win32.phpt index a88083c41281..07b5d01a6cd8 100644 --- a/ext/opcache/tests/file_cache_fallback_win32.phpt +++ b/ext/opcache/tests/file_cache_fallback_win32.phpt @@ -30,7 +30,7 @@ copy($srcDir . DIRECTORY_SEPARATOR . $dll, $binDir . DIRECTORY_SEPARATOR . $dll) $args = [ $binDir . DIRECTORY_SEPARATOR . basename(PHP_BINARY), '-n', - '-d', 'extension_dir=' . ini_get('extension_dir'), + '-d', 'extension_dir="' . ini_get('extension_dir') . '"', ]; if (file_exists(ini_get('extension_dir') . DIRECTORY_SEPARATOR . 'php_opcache.dll')) { $args[] = '-d'; @@ -43,7 +43,7 @@ foreach (['opcache.memory_consumption', 'opcache.jit', 'opcache.jit_buffer_size' array_push($args, '-d', 'opcache.enable=1', '-d', 'opcache.enable_cli=1', - '-d', 'opcache.file_cache=' . $cacheDir, + '-d', 'opcache.file_cache="' . $cacheDir . '"', '-d', 'opcache.file_cache_fallback=1', '-r', 'var_dump(opcache_get_status(false)["file_cache_only"]);' );