-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Opcache CFG jmp optimization with try-finally breaks the exception table #18107
Comments
Note that there is a workaround by doing an extra throw in the finally statement, but that shouldn't be needed as far as I know. Generally this doesn't impact a lot, other than making unit tests where you expect a specific exception fiddly. |
The particular code you posted doesn't reproduce the issue for me, at least not on 8.3.16 nor 8.3-dev. |
I apologize, I thought I had it narrowed down and I think I had a different bug surfacing when I didn't include Here's a reproducing file:
and here's a bash log:
|
The static reference to an object doesn't matter, I'm gonna try to figure out the minimum script here, but you can do |
Ah, sorry for the rapid updates, here's the minimum script I think:
the
I guess is required to reproduce |
Thanks a lot! This reproduces on 8.3-dev for me, reduced a bit further: <?php
function readLinesFrom($filename)
{
$file = fopen($filename, 'r');
if ($file === false) {
throw new Exception;
}
try {
while (fgets($file)) {
yield 1;
}
} finally {
fclose($file);
}
}
iterator_to_array(readLinesFrom("/bad/file/path/1")); EDIT: the difference between the optimization before / after is a |
After the jump optimization is run, the php-src/Zend/Optimizer/zend_cfg.c Lines 141 to 154 in b450a9c
|
OOoooo you're right on the money, add an empty catch block and the issue goes away. |
Yeah, I think the assignment of |
Oh, so this isn't even yield or generator related, it's about the while loop.
seems to replicate as well |
Also works thinned all the way to:
From there, thinning further seems tricky. Mostly noting this to help in documentation of what exactly your WIP fix is fixing. |
It won't get simpler than that I think. That's a nice reproducer, thanks a lot for the effort; and for initially narrowing it down to the right optimization pass. I'll take that last reproducer as a test and I'm preparing a PR soon. |
… the exception table If there's a try-finally where the try_op starts on a basic block with a single JMP, and the JMP optimization causes that basic block to become unreachable, then we update try_op. In this case, there is no catch_op, so try_op is erroneously set to 0, we should instead set it to `b->start`.
… the exception table If there's a try-finally where the try_op starts on a basic block with a single JMP, and the JMP optimization causes that basic block to become unreachable, then we update try_op. In this case, there is no catch_op, so try_op is erroneously set to 0, we should instead set it to `b->start`.
* PHP-8.3: Fix GH-18107: Opcache CFG jmp optimization with try-finally breaks the exception table
* PHP-8.4: Fix GH-18107: Opcache CFG jmp optimization with try-finally breaks the exception table
Description
The following code:
when run multiple times with
php -dopcache.enable_cli=on -dopcache.optimization_level=0x0010 -derror_log=/proc/self/fd/2 myfile.php
Resulted in this output:
But when run with
php -dopcache.enable_cli=on -dopcache.optimization_level=0 -derror_log=/proc/self/fd/2 myfile.php
I get this instead:Slightly unsure if this is just another example of issue #8269 or not
PHP Version
PHP 8.3.16 and PHP 8.2.19
Operating System
Amazon Linux 2 and MacOS 15.2 (likely not relevant?)
The text was updated successfully, but these errors were encountered: