mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Fix bug #71604
Alternatively could throw some kind of uncatchable dummy exception into the generator. Right now just checking for NULL in two places seems simpler.
This commit is contained in:
parent
79de9fa4aa
commit
921b3251b3
2
NEWS
2
NEWS
@ -14,6 +14,8 @@ PHP NEWS
|
||||
. Fixed bug #62814 (It is possible to stiffen child class members visibility).
|
||||
(Nikita)
|
||||
. Fixed bug #69989 (Generators don't participate in cycle GC). (Nikita)
|
||||
. Fixed bug #71604 (Aborted Generators continue after nested finally).
|
||||
(Nikita)
|
||||
. Fixed bug #71572 (String offset assignment from an empty string inserts
|
||||
null byte). (Francois)
|
||||
. Fixed bug #71897 (ASCII 0x7F Delete control character permitted in
|
||||
|
25
Zend/tests/try/bug71604.phpt
Normal file
25
Zend/tests/try/bug71604.phpt
Normal file
@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
Bug #71604: Aborted Generators continue after nested finally
|
||||
--FILE--
|
||||
<?php
|
||||
function gen() {
|
||||
try {
|
||||
try {
|
||||
yield;
|
||||
} finally {
|
||||
print "INNER\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
print "EX\n";
|
||||
} finally {
|
||||
print "OUTER\n";
|
||||
}
|
||||
print "NOTREACHED\n";
|
||||
}
|
||||
|
||||
gen()->current();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
INNER
|
||||
OUTER
|
39
Zend/tests/try/bug71604_2.phpt
Normal file
39
Zend/tests/try/bug71604_2.phpt
Normal file
@ -0,0 +1,39 @@
|
||||
--TEST--
|
||||
Bug #71604: Aborted Generators continue after nested finally (2)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function gen() {
|
||||
try {
|
||||
throw new Exception(1);
|
||||
} finally {
|
||||
try {
|
||||
throw new Exception(2);
|
||||
} finally {
|
||||
try {
|
||||
yield;
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
gen()->rewind();
|
||||
} catch (Exception $e) {
|
||||
echo $e, "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Exception: 1 in %s:%d
|
||||
Stack trace:
|
||||
#0 [internal function]: gen()
|
||||
#1 %s(%d): Generator->rewind()
|
||||
#2 {main}
|
||||
|
||||
Next Exception: 2 in %s:%d
|
||||
Stack trace:
|
||||
#0 [internal function]: gen()
|
||||
#1 %s(%d): Generator->rewind()
|
||||
#2 {main}
|
38
Zend/tests/try/bug71604_3.phpt
Normal file
38
Zend/tests/try/bug71604_3.phpt
Normal file
@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
Bug #71604: Aborted Generators continue after nested finally (3)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function gen() {
|
||||
try {
|
||||
throw new Exception(1);
|
||||
} finally {
|
||||
try {
|
||||
yield;
|
||||
} finally {
|
||||
try {
|
||||
throw new Exception(2);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
gen()->rewind();
|
||||
} catch (Exception $e) {
|
||||
echo $e, "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Exception: 1 in %s:%d
|
||||
Stack trace:
|
||||
#0 [internal function]: gen()
|
||||
#1 %s(%d): Generator->rewind()
|
||||
#2 {main}
|
||||
|
||||
Next Exception: 2 in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): gen()
|
||||
#1 {main}
|
@ -7107,6 +7107,7 @@ ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
|
||||
|
||||
ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_catch_offset, uint32_t op_num)
|
||||
{
|
||||
/* May be NULL during generator closing (only finally blocks are executed) */
|
||||
zend_object *ex = EG(exception);
|
||||
|
||||
/* Walk try/catch/finally structures upwards, performing the necessary actions */
|
||||
@ -7114,7 +7115,7 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca
|
||||
zend_try_catch_element *try_catch =
|
||||
&EX(func)->op_array.try_catch_array[try_catch_offset];
|
||||
|
||||
if (op_num < try_catch->catch_op) {
|
||||
if (op_num < try_catch->catch_op && ex) {
|
||||
/* Go to catch block */
|
||||
cleanup_live_vars(execute_data, op_num, try_catch->catch_op);
|
||||
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[try_catch->catch_op]);
|
||||
@ -7134,7 +7135,11 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca
|
||||
/* Chain potential exception from wrapping finally block */
|
||||
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
|
||||
if (Z_OBJ_P(fast_call)) {
|
||||
zend_exception_set_previous(ex, Z_OBJ_P(fast_call));
|
||||
if (ex) {
|
||||
zend_exception_set_previous(ex, Z_OBJ_P(fast_call));
|
||||
} else {
|
||||
EG(exception) = Z_OBJ_P(fast_call);
|
||||
}
|
||||
ex = Z_OBJ_P(fast_call);
|
||||
}
|
||||
}
|
||||
|
@ -1692,6 +1692,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try_catch_finally_helper_SPEC(uint32_t try_catch_offset, uint32_t op_num ZEND_OPCODE_HANDLER_ARGS_DC)
|
||||
{
|
||||
/* May be NULL during generator closing (only finally blocks are executed) */
|
||||
zend_object *ex = EG(exception);
|
||||
|
||||
/* Walk try/catch/finally structures upwards, performing the necessary actions */
|
||||
@ -1699,7 +1700,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try_catch_finally_hel
|
||||
zend_try_catch_element *try_catch =
|
||||
&EX(func)->op_array.try_catch_array[try_catch_offset];
|
||||
|
||||
if (op_num < try_catch->catch_op) {
|
||||
if (op_num < try_catch->catch_op && ex) {
|
||||
/* Go to catch block */
|
||||
cleanup_live_vars(execute_data, op_num, try_catch->catch_op);
|
||||
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[try_catch->catch_op]);
|
||||
@ -1719,7 +1720,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try_catch_finally_hel
|
||||
/* Chain potential exception from wrapping finally block */
|
||||
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
|
||||
if (Z_OBJ_P(fast_call)) {
|
||||
zend_exception_set_previous(ex, Z_OBJ_P(fast_call));
|
||||
if (ex) {
|
||||
zend_exception_set_previous(ex, Z_OBJ_P(fast_call));
|
||||
} else {
|
||||
EG(exception) = Z_OBJ_P(fast_call);
|
||||
}
|
||||
ex = Z_OBJ_P(fast_call);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user