Reset CE cache slots on opcache reset

Permanent opcache interned strings could have ce_cache pointing to
non-permanent map_ptr slots. On reset, those would be left dangling.
Clear any non-permanent ce_cache slots when the interned string
state is reset.

This was fun to debug...
This commit is contained in:
Nikita Popov 2021-09-13 15:17:32 +02:00
parent b3646440b1
commit 86d470f3e0

View file

@ -411,6 +411,15 @@ static void accel_interned_strings_restore_state(void)
n = 0;
if (EXPECTED(s < top)) {
do {
if (ZSTR_HAS_CE_CACHE(s)) {
/* Discard non-global CE_CACHE slots on reset. */
uintptr_t idx = (GC_REFCOUNT(s) - 1) / sizeof(void *);
if (idx >= ZCSG(map_ptr_last)) {
GC_SET_REFCOUNT(s, 2);
GC_DEL_FLAGS(s, IS_STR_CLASS_NAME_MAP_PTR);
}
}
hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), ZSTR_H(s));
STRTAB_COLLISION(s) = *hash_slot;
*hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);