Commit d673a1f56dd for php.net
commit d673a1f56ddeb45faacfc27bcb5063942a26f60a
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Fri Jul 3 21:30:16 2026 -0400
Fix GH-22516: widen zend_mm srun free counter to cover bin 0 (#22530)
The per-page free-slot counter in zend_mm_gc() is stored in a 9-bit field
(ZEND_MM_SRUN_FREE_COUNTER_MASK, max 511). Bin 0 holds 512 slots, so a
fully-free bin-0 page drives the counter to 512, which overflows the field
and reads back as 0; the counter == bin_elements checks then never fire and
the page is never reclaimed. Widen the field to 10 bits (0x03ff0000); bit 25
was unused and the write side already stays below it for every other bin.
Bin 0 is only reachable where ZEND_MM_MIN_USEABLE_BIN_SIZE == 8 (32-bit, or
heap-protection-disabled builds).
Fixes GH-22516
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index d0f2b221b9a..0b040743abf 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -197,7 +197,7 @@ typedef zend_mm_bitset zend_mm_page_map[ZEND_MM_PAGE_MAP_LEN]; /* 64B */
#define ZEND_MM_SRUN_BIN_NUM_MASK 0x0000001f
#define ZEND_MM_SRUN_BIN_NUM_OFFSET 0
-#define ZEND_MM_SRUN_FREE_COUNTER_MASK 0x01ff0000
+#define ZEND_MM_SRUN_FREE_COUNTER_MASK 0x03ff0000
#define ZEND_MM_SRUN_FREE_COUNTER_OFFSET 16
#define ZEND_MM_NRUN_OFFSET_MASK 0x01ff0000