[php-src] Issue #24605: var_export(), print_r() and unserialize() segfault on deep nesting — the stack-limit guard from #22871 is incomplete

From: Date: Fri, 23 Oct 2026 15:10:15 +0000
Subject: [php-src] Issue #24605: var_export(), print_r() and unserialize() segfault on deep nesting — the stack-limit guard from #22871 is incomplete
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-253131@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24605 Author: Volkopat ### Description #22871 added ZEND_CHECK_STACK_LIMIT to var_dump()/debug_zval_dump() so deep nesting throws a catchable Error instead of segfaulting, and its description notes var_export() "overflows the same way but needs a throw-based guard, left for a separate change." That guard was never added. print_r()'s array path and unserialize() have the same unguarded C recursion. serialize() (GH-15169) and DOMNode::normalize() (#23127) are already guarded. ### Reproduce (needs a real stack limit; a container makes it one line) docker run --rm --ulimit stack=524288:524288 -v "$PWD:/w" php:8.5.12-cli php /w/repro.php # or locally: bash -c 'ulimit -s 512; php repro.php' ```php <?php $depth = 3000; $a = 0; for ($i = 0; $i < $depth; $i++) { $a = [$a]; } try { serialize($a); } catch (\Error $e) { echo "serialize threw: {$e->getMessage()}\n"; } // guarded var_export($a); // SIGSEGV (exit 139) // print_r($a); // same // unserialize(str_repeat('a:1:{i:0;', $depth) . 'i:0;' . str_repeat('}', $depth)); // same ``` **Expected:** a catchable Error ("Maximum call stack size reached"), as serialize() produces on the identical structure in the same process. **Actual:** segmentation fault (exit 139). Stack cost is ~233 B/level, so crash depth tracks the stack (~35,000 at 8 MB, ~2,200 at 512 KB). var_export() and print_r() have no depth backstop, so they crash at ~35,000 on a stock 8 MB stack too; unserialize() throws at its default max_depth of 4096 first, so it only reaches the segfault when the stack is small enough that 4096 levels don't fit (threaded SAPIs, musl/Alpine, fibers, lowered ulimit). Fix: add ZEND_CHECK_STACK_LIMIT to the var_export, print_r and unserialize recursion, as the already-guarded paths do. ### PHP Version ```plain 8.5.12 ``` ### Operating System _No response_

« previous php.bugs (#253131) next »