[php-src] PR #23014: Fix use-after-free of an array callable freed during validation
| From: | iliaal | Date: | Tue, 04 Aug 2026 01:19:35 +0000 |
| Subject: | [php-src] PR #23014: Fix use-after-free of an array callable freed during validation | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-37487@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/23014
Author: iliaal
INIT_USER_CALL reads the callable array from op2 without holding a reference, so an
error handler reached by the compound-callable deprecation can free the receiver before the call
frame is built.
```php
class Victim { public $tag = "alive"; public function target() { echo $this->tag; } }
class Holder extends Victim {}
set_error_handler(function ($n, $s) { if (str_contains($s, 'Callables of the form')) {
$GLOBALS['cb'] = null; gc_collect_cycles(); } return true; });
$cb = [new Holder(), 'Victim::target'];
call_user_func($cb); // SIGSEGV
```
array_map() and friends are unaffected: the callable arrives as an argument, so the
frame holds a reference for the call.
Unlike #22881 the hold belongs in the VM here. The reference has to outlive
zend_is_callable_at_frame(), since releasing it there drops the receiver before the
GC_ADDREF a few lines below.