Closed Changochen closed 1 year ago
Actually this seems to be a whole category of "yield"-related issues with finally's. This also doesn't work:
<?php
function test() {
try {
yield null => 0;
} finally {
return [];
}
}
echo "hi\n";
var_dump([...test()]);
echo "hi2\n";
and if you replace null
with (new stdClass)
, or false
, or true
, ... for example, it also doesn't work.
EDIT: progress.... https://github.com/php/php-src/blob/7de83e273642f6bdc8e0dfd052d8ecefa7c7b9e5/Zend/zend_vm_def.h#L6236 commenting this line "fixes" both my test case and OP's for some reason :thinking: (but ofc introduces leakage etc etc)
I attempted a fix here: https://github.com/nielsdos/php-src/commit/665026320302712d531d1e889d1abfc1fa766084 This commit fixes both OP's issue and the issue I reported in my previous comment.
However, I found a variant of my previously reported issue which still crashes (may be different root cause?). It can be found here: https://github.com/nielsdos/php-src/commit/665026320302712d531d1e889d1abfc1fa766084#diff-e61ec0f8972fbb546701b53555d59a0bfe720abdf3040f6b87c23a8a7f94db40 I'm not sure what's going on in that case tbh
Maybe @bwoebi or @arnaud-lb can help, they've touched this code most recently :slightly_smiling_face:
This script seems to result in a memory corruption since at least 7.4 according to https://3v4l.org/8SDGE
The problem seems to be that we discard an exception that was thrown by an other frame, but the frame will still try to handle it. Since EG(exception) is NULL, it will not take the right code path, and continue to execute after having freed live variables.
Error("Keys must be of type int|string during array unpacking")
. EG(exception) is set, and EG(current_execute_data)->opline is set to EG(exception_op)@nielsdos your fix looks good. The case that still crashes is because EG(opline_before_exception) points to the generator op array, so in ZEND_HANDLE_EXCEPTION we call cleanup_unfinished_calls with an invalid op_num. We should probably save/restore EG(opline_before_exception) as well.
Thanks. That makes sense. I missed the opline_before_exception part so that's why I didn't understand what was going on with my extra testcase. I'll update the fix and PR it when I have time.
Description
The following code:
with
USE_TRACKED_ALLOC=1 USE_ZEND_ALLOC=0
Resulted in this output:PHP Version
PHP 8.3.0-dev
Operating System
No response