Skip to content

Fix GH-22516: widen zend_mm srun free counter to cover bin 0#22530

Open
iliaal wants to merge 1 commit into
php:masterfrom
iliaal:fix/gh-22516-zend-mm-bin0-counter
Open

Fix GH-22516: widen zend_mm srun free counter to cover bin 0#22530
iliaal wants to merge 1 commit into
php:masterfrom
iliaal:fix/gh-22516-zend-mm-bin0-counter

Conversation

@iliaal

@iliaal iliaal commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Fix is trivial, but given it is only 32bit... not 100% sure if needed

zend_mm_gc()'s per-page free-slot counter is stored in a 9-bit field (ZEND_MM_SRUN_FREE_COUNTER_MASK, max 511), but bin 0 has 512 slots, so a fully-free bin-0 page drives the counter to 512, overflows the field, and reads back as 0. The fully-free-page checks (counter == bin_elements) then never fire and the page is never reclaimed. Widening the field to 10 bits (0x03ff0000) fixes it: bit 25 was unused, and the change is a no-op for every other bin since they all hold at most 256 slots.

Reachable only where ZEND_MM_MIN_USEABLE_BIN_SIZE == 8, i.e. 32-bit or heap-protection-disabled builds. On 64-bit with heap protection, zend_mm_alloc_heap() rounds every sub-16-byte request up to bin 1, so bin 0 is never used and the change is inert there.

Fixes #22516

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 phpGH-22516
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zend_alloc bin 0 may leak

1 participant