[php-src] PR #24069: Fix GH-23626: OPcache: orphaned temporaries cause leaks and assertions
| From: | khaledalam | Date: | Fri, 02 Oct 2026 06:47:31 +0000 |
| Subject: | [php-src] PR #24069: Fix GH-23626: OPcache: orphaned temporaries cause leaks and assertions | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39066@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24069
Author: khaledalam
When
match has arms but constant folding proves none of them can be taken, the block
pass treats MATCH_ERROR as a terminator and drops the following blocks as unreachable.
Temporaries created before the match and consumed only in those blocks lose their live
range, so:
- they are not freed when UnhandledMatchError unwinds (memory leak, wrong destructor
order), or
- if a non-consuming use like BIND_LEXICAL remains,
zend_calc_live_ranges() hits the keeps_op1_alive() assertion.
This was already handled for arm-less match by marking MATCH_ERROR as an
expression throw (ZEND_THROW_IS_EXPR), which stops the CFG from treating it as a block
terminator. This patch applies the marking unconditionally, as suggested by @ndossche in the issue.
### Before
```
$ php -d opcache.enable_cli=1 leak.php
caught
done
destruct a
destruct a-clone
=== Total 1 memory leaks detected ===
$ php -d opcache.enable_cli=1 assert.php
Assertion failed: (...), function keeps_op1_alive, file zend_opcode.c, line 912.
```
### After
```
$ php -d opcache.enable_cli=1 leak.php
destruct a-clone
caught
done
destruct a
$ php -d opcache.enable_cli=1 assert.php
ok
```
Output now matches running without opcache.