[php-src] PR #24585: Fix GH-24577: CE-cache flag on interned class name visible before map_ptr offset
| From: | prateekbhujel | Date: | Fri, 23 Oct 2026 03:12:16 +0000 |
| Subject: | [php-src] PR #24585: Fix GH-24577: CE-cache flag on interned class name visible before map_ptr offset | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39744@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24585
Author: prateekbhujel
Fixes GH-24577.
In Zend Engine and OPcache, class entry (CE) caching stores the
map_ptr offset in
type_name->gc.refcount and tags the string with
IS_STR_CLASS_NAME_MAP_PTR.
In multi-process environments like PHP-FPM, concurrent compilation on a cold cache could allow
worker processes to observe IS_STR_CLASS_NAME_MAP_PTR before the offset store was
committed or reordered, causing readers to pick up refcount 2 (the initial refcount for SHM interned
strings). Because (2 - 1) / sizeof(void*) == 0 < CG(map_ptr_last),
ZSTR_VALID_CE_CACHE accepted offset 2, leading to an unaligned read of bogus pointer
bytes at (map_ptr_base + 2) and SIGSEGV in object_init_ex.
This patch addresses both the validation invariant and memory ordering across the engine:
1. **Harden ZSTR_VALID_CE_CACHE()**: Strictly reject GC_REFCOUNT(s) <=
2 in Zend/zend_types.h, matching the guarantee in zend.c and
zend_persist.c that valid map_ptr offsets are always > 2.
2. **Correct store order in zend.c**: In zend_alloc_ce_cache(), set
GC_SET_REFCOUNT before setting IS_STR_CLASS_NAME_MAP_PTR.
3. **Acquire/Release memory fences**: Add acquire-release thread fences between publishing the
refcount and setting IS_STR_CLASS_NAME_MAP_PTR across Zend/zend.c,
ext/opcache/zend_persist.c, ext/opcache/ZendAccelerator.c, and the reader
in Zend/zend_execute_API.c.
4. **Regression test**: Add ext/opcache/tests/gh24577.phpt covering concurrent
compilation and instantiation under OPcache.