[php-src] PR #24548: Fix GH-24492 (partial): route caller-sized string builders through the fallible allocator

From: Date: Thu, 22 Oct 2026 15:26:22 +0000
Subject: [php-src] PR #24548: Fix GH-24492 (partial): route caller-sized string builders through the fallible allocator
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-39711@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/24548 Author: VijhnAustin Fixes part of #24492. ## Problem Several ext/standard functions grow their output buffer with the non-fallible string allocators. When the requested size crosses the soft memory_limit, the allocation is not reported back to the caller; it escalates to the hard limit (memory_hard_limit_percent) and the process is terminated via _exit(137), so registered shutdown functions never run and the catchable "Allowed memory size … exhausted" fatal that 8.5.11 produced for the same input is lost. A single userland call with an attacker-influenced size is enough. ## Fix Route these sites through the fallible allocation API already in the tree (zend_string_fextend / zend_string_falloc / zend_string_safe_falloc with fallible = true), propagate the NULL, and surface the standard engine OOM via RETURN_OOM() at the userland boundary: - sprintf/printf/vprintf/vsprintf/fprintf/vfprintf (formatted_print.c; the php_sprintf_append* helpers now return bool) - pack (pack.c) - bin2hex and utf8_encode (string.c) - number_format (math.c; tmpbuf released on the failure path) - convert_uuencode (uuencode.c) - quoted_printable_encode (quot_print.c) ## Scope This is a **partial** fix. Other sites named in the issue — base64_encode, urlencode/rawurlencode, var_export, the bcmath family, and the main/spprintf.c PAD_CHAR path — route their result through PHPAPI helpers whose internal callers currently dereference the result without a NULL check (they never see a failed huge allocation today because the process is killed first). Converting those safely needs a caller audit, so they are intentionally left for follow-up. The ext/xml/Expat variant is already handled in #24516. ## Reproduction With memory_limit=16M and memory_hard_limit_percent=200: ```php register_shutdown_function(static fn() => print("shutdown\n")); sprintf("%40000000s", ""); // or pack("x40000000"); number_format(1.0, 100000000); etc. ``` Before (stock): Hard memory limit of 33554432 bytes exhausted …, exit 137, no shutdown. After (patched): catchable Allowed memory size of 16777216 bytes exhausted …, shutdown runs, exit 255. ## Tests Adds 17 .phpt under ext/standard/tests/{strings,math}/gh24492_*, each pinning memory_hard_limit_percent=200 and asserting both the catchable fatal and that a shutdown function still runs (so a failure while preparing the input cannot masquerade as a reproduced bug). Verified on a Windows x64 build (17/17 passing); the patch applies cleanly to current PHP-8.5. Also reproduces on 8.4.27 per the issue — happy to retarget to PHP-8.4 if that is preferred. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

« previous php.git-pulls (#39711) next »