[GIT-PULLS] [php-src] PR #23014: Fix use-after-free of an array callable freed during validation
[email protected] (iliaal) Tue, 4 Aug 2026 01:19:35 +0000
| Newsgroups | php.git-pulls |
|---|---|
| Message-ID | <[email protected]> |
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.