[php-src] Issue #24492: sprintf()/pack()/bin2hex() _exit(137) at hard memory limit where 8.5.11 raised a catchable OOM (incomplete fallible-alloc
conversion, 8.5.12/8.4.27)

From: Date: Wed, 21 Oct 2026 18:08:52 +0000
Subject: [php-src] Issue #24492: sprintf()/pack()/bin2hex() _exit(137) at hard memory limit where 8.5.11 raised a catchable OOM (incomplete fallible-alloc
conversion, 8.5.12/8.4.27)
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-253059@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24492 Author: VijhnAustin ### Description Since commit 31c0ea7d ("Avoid state corruption via bailout", CVE-2026-109618/109619), a **non-fallible** allocation that would cross the new hard memory limit (default 200% of memory_limit) terminates the process via _exit(137) in zend_mm_hard_limit_error() (Zend/zend_alloc.c). Most allocation sites were moved to the new fallible API, but several core functions still allocate non-fallibly from a small, caller-supplied size, so they kill the whole process instead of raising the catchable "Allowed memory size exhausted" fatal that 8.5.11 produced for the same input. The following code: ```php <?php sprintf("%400000000s", ""); ``` Run with: php -n -d memory_limit=128M repro.php Resulted in this output (8.5.12): ``` Hard memory limit of 268435456 bytes exhausted (tried to allocate 505413632 bytes) in Command line code on line 1 ``` Exit code **137** — process terminated; the allocation is never actually performed (the hard-limit check rejects first). But I expected this output instead (the 8.5.11 behavior): ``` Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 503316512 bytes) in Command line code on line 1 ``` Exit code **255** — catchable fatal, the process/worker survives. The same process kill occurs from other small integer parameters — pack("x300000000"), number_format(1.0, 100000000), bcadd("1","1",100000000) — and from large in-heap inputs to bin2hex / base64_encode / urlencode / var_export / convert_uuencode / utf8_encode / quoted_printable_encode. A crafted phar:// manifest length triggers it from a ~100-byte file. Sites still using the non-fallible allocator in 8.5.12: - smart_string_alloc() in PAD_CHAR — main/spprintf.c - zend_string_alloc(outputsize, 0) — ext/standard/pack.c:431 - zend_string_safe_alloc(..., 0) in php_bin2hex() / php_utf8_encode() — ext/standard/string.c Mechanism: zend_mm_check_limit() calls zend_mm_hard_limit_error() → _exit(137) when !heap->fallible and the allocation would cross hard_limit. Routing these sites through the fallible API (femalloc / zend_string_finit / smart_str_ferealloc) would keep the OOM catchable, consistent with the rest of the patch. Reproduces identically on 8.4.27 (8.4.26 behaves like 8.5.11). The path is in Zend/zend_alloc.c, so it is platform-independent; tested here on official Windows x64 NTS builds. ### PHP Version ```plain PHP 8.5.12 (cli) (built: Oct 20 2026 04:19:56) (NTS Visual C++ 2022 x64) Copyright (c) The PHP Group Built by The PHP Group Zend Engine v4.5.12, Copyright (c) Zend Technologies ``` ### Operating System Windows 11 (code path is OS-independent — Zend/zend_alloc.c)

« previous php.bugs (#253059) next »