mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix uncatchable exception thrown in generator
This procedure may be called during i_free_compiled_variables(), when EG(current_execute_data) is unfortunately already reset to the parent frame. EG(opline_before_exception) does not actually belong to this frame. Furthermore, setting opline to EG(exception_op) early will miss a later zend_rethrow_exception(), which will also miss installation of the correct EG(opline_before_exception). Fixes GH-20714 Closes GH-20716
This commit is contained in:
1
NEWS
1
NEWS
@@ -7,6 +7,7 @@ PHP NEWS
|
||||
with dynamic class const lookup default argument). (ilutov)
|
||||
. Fixed bug GH-20695 (Assertion failure in normalize_value() when parsing
|
||||
malformed INI input via parse_ini_string()). (ndossche)
|
||||
. Fixed bug GH-20714 (Uncatchable exception thrown in generator). (ilutov)
|
||||
|
||||
- Bz2:
|
||||
. Fixed bug GH-20620 (bzcompress overflow on large source size).
|
||||
|
||||
29
Zend/tests/gh20714.phpt
Normal file
29
Zend/tests/gh20714.phpt
Normal file
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
GH-20714: Uncatchable exception thrown in generator
|
||||
--CREDITS--
|
||||
Grégoire Paris (greg0ire)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function gen(): Generator {
|
||||
try {
|
||||
yield 1;
|
||||
} finally {}
|
||||
}
|
||||
|
||||
function process(): void {
|
||||
$g = gen();
|
||||
foreach ($g as $_) {
|
||||
throw new Exception('ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
process();
|
||||
} catch (Exception $e) {
|
||||
echo "Caught\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Caught
|
||||
@@ -321,7 +321,9 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
|
||||
zend_object *old_exception = NULL;
|
||||
const zend_op *old_opline_before_exception = NULL;
|
||||
if (EG(exception)) {
|
||||
if (EG(current_execute_data)) {
|
||||
if (EG(current_execute_data)
|
||||
&& EG(current_execute_data)->opline
|
||||
&& EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
EG(current_execute_data)->opline = EG(opline_before_exception);
|
||||
old_opline_before_exception = EG(opline_before_exception);
|
||||
}
|
||||
@@ -337,7 +339,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
|
||||
zend_generator_resume(generator);
|
||||
|
||||
if (old_exception) {
|
||||
if (EG(current_execute_data)) {
|
||||
if (old_opline_before_exception) {
|
||||
EG(current_execute_data)->opline = EG(exception_op);
|
||||
EG(opline_before_exception) = old_opline_before_exception;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user