Commit 6144bac2dc7 for php
commit 6144bac2dc71759be505641446b021579be7d052
Author: Shivam Mathur <shivam_jpr@hotmail.com>
Date: Thu Nov 12 06:46:20 2026 +0530
Align the Windows OPcache JIT buffer (#25262)
* Align the Windows OPcache JIT buffer
* Assert that the OPcache JIT buffer is page-aligned
diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c
index dbc7a37ca07..980bf2d3eab 100644
--- a/ext/opcache/jit/zend_jit.c
+++ b/ext/opcache/jit/zend_jit.c
@@ -3659,6 +3659,7 @@ int zend_jit_check_support(void)
void zend_jit_startup(void *buf, size_t size, bool reattached)
{
+ ZEND_ASSERT(((uintptr_t)buf & (zend_get_page_size() - 1)) == 0);
zend_jit_halt_op = zend_get_halt_op();
zend_jit_profile_counter_rid = zend_get_op_array_extension_handle(ACCELERATOR_PRODUCT_NAME);
diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c
index 5e37cedcb4d..da6ef8c3db2 100644
--- a/ext/opcache/shared_alloc_win32.c
+++ b/ext/opcache/shared_alloc_win32.c
@@ -327,7 +327,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_
}
shared_segment->pos = ACCEL_BASE_POINTER_SIZE;
- shared_segment->size = requested_size - ACCEL_BASE_POINTER_SIZE;
+ shared_segment->size = requested_size;
zend_shared_alloc_unlock_win32();
diff --git a/ext/opcache/tests/jit/gh25213.phpt b/ext/opcache/tests/jit/gh25213.phpt
new file mode 100644
index 00000000000..1ab64b8e08f
--- /dev/null
+++ b/ext/opcache/tests/jit/gh25213.phpt
@@ -0,0 +1,53 @@
+--TEST--
+GH-25213 (JIT buffer misalignment crashes OPcache when shared memory fills up on Windows)
+--EXTENSIONS--
+opcache
+--SKIPIF--
+<?php
+if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only');
+if (ini_get('opcache.jit') === false) die('skip PHP is compiled without JIT');
+?>
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.memory_consumption=16
+opcache.interned_strings_buffer=1
+opcache.max_accelerated_files=20000
+opcache.jit=tracing
+opcache.jit_buffer_size=64M
+--FILE--
+<?php
+if (!(opcache_get_status(false)['jit']['enabled'] ?? false)) {
+ throw new RuntimeException('JIT is not enabled');
+}
+$dir = __DIR__ . '/gh25213_tmp';
+mkdir($dir);
+for ($i = 0; $i < 20000; $i++) {
+ $file = "$dir/c$i.php";
+ file_put_contents($file, "<?php class C$i extends ArrayObject { public function m(int \$a): int { return \$a + $i; } }\n");
+ require $file;
+ unlink($file);
+ $status = opcache_get_status(false);
+ if ($status['cache_full']) {
+ break;
+ }
+}
+var_dump($status['cache_full']);
+var_dump($status['memory_usage']['free_memory'] < 65536);
+var_dump($status['opcache_statistics']['num_cached_keys'] < $status['opcache_statistics']['max_cached_keys']);
+rmdir($dir);
+?>
+--CLEAN--
+<?php
+$dir = __DIR__ . '/gh25213_tmp';
+if (is_dir($dir)) {
+ foreach (glob("$dir/*") as $file) {
+ unlink($file);
+ }
+ rmdir($dir);
+}
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)