diff options
author | Nikita Popov <nikic@php.net> | 2016-04-07 12:25:42 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2016-04-07 12:29:59 +0200 |
commit | aad4ecebf83568f41f5b27b274f988710ce53646 (patch) | |
tree | ffa9300a58f21f468728a0f9720db9038302b3b3 | |
parent | 079239a7cececfca9344b24f5bb1cca127d4bcc9 (diff) | |
download | php-git-aad4ecebf83568f41f5b27b274f988710ce53646.tar.gz |
Fixed bug #71980
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug71980.phpt | 43 | ||||
-rw-r--r-- | Zend/zend_generators.c | 12 |
3 files changed, 53 insertions, 4 deletions
@@ -24,6 +24,8 @@ PHP NEWS . Fixed bug #69537 (__debugInfo with empty string for key gives error). (krakjoe) . Fixed bug #62059 (ArrayObject and isset are not friends). (Nikita) + . Fixed bug #71980 (Decorated/Nested Generator is Uncloseable in Finally). + (Nikita) - Curl: . Fixed bug #71831 (CURLOPT_NOPROXY applied as long instead of string). diff --git a/Zend/tests/bug71980.phpt b/Zend/tests/bug71980.phpt new file mode 100644 index 0000000000..cd98f6567d --- /dev/null +++ b/Zend/tests/bug71980.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #71980: Decorated/Nested Generator is Uncloseable in Finally +--FILE-- +<?php + +class Dtor { + public function __destruct() { + echo "Dtor\n"; + } +} + +function gen1() { + try { + foreach ([42, new Dtor] as $value) { + yield $value; + } + } finally { + echo "Finally\n"; + } +} + +function gen2() { + try { + var_dump(new Dtor, yield); + } finally { + echo "Finally\n"; + } +} + +$gen = gen1(); +$gen->rewind(); +unset($gen); + +$gen = gen2(); +$gen->rewind(); +unset($gen); + +?> +--EXPECT-- +Dtor +Finally +Dtor +Finally diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 646e46b676..89b919a48c 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -31,7 +31,8 @@ static zend_object_handlers zend_generator_handlers; static zend_object *zend_generator_create(zend_class_entry *class_type); -static void zend_generator_cleanup_unfinished_execution(zend_generator *generator) /* {{{ */ +static void zend_generator_cleanup_unfinished_execution( + zend_generator *generator, uint32_t catch_op_num) /* {{{ */ { zend_execute_data *execute_data = generator->execute_data; @@ -47,7 +48,7 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato EG(vm_stack_end) = generator->stack->end; EG(vm_stack) = generator->stack; - zend_cleanup_unfinished_execution(execute_data, op_num, 0); + zend_cleanup_unfinished_execution(execute_data, op_num, catch_op_num); generator->stack = EG(vm_stack); generator->stack->top = EG(vm_stack_top); @@ -85,7 +86,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished /* Some cleanups are only necessary if the generator was closed * before it could finish execution (reach a return statement). */ if (UNEXPECTED(!finished_execution)) { - zend_generator_cleanup_unfinished_execution(generator); + zend_generator_cleanup_unfinished_execution(generator, 0); } /* Free closure object */ @@ -151,8 +152,11 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ /* If a finally block was found we jump directly to it and * resume the generator. */ if (finally_op_num) { - zval *fast_call = ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[finally_op_end].op1.var); + zval *fast_call; + zend_generator_cleanup_unfinished_execution(generator, finally_op_num); + + fast_call = ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[finally_op_end].op1.var); Z_OBJ_P(fast_call) = EG(exception); EG(exception) = NULL; fast_call->u2.lineno = (uint32_t)-1; |