Skip to content

Fix GH-23626: OPcache: orphaned temporaries cause leaks and assertions - #24069

Open
khaledalam wants to merge 1 commit into
php:masterfrom
khaledalam:fix-gh-23626
Open

khaledalam wants to merge 1 commit into
php:masterfrom
khaledalam:fix-gh-23626

Conversation

@khaledalam

Copy link
Copy Markdown
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant