From ea5c66ec9310430111b48d4589e56cea5c0b5ab0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 23 Jun 2015 20:13:25 +0200 Subject: [PATCH] Avoid op_num = -1 in unfinished generator cleanup Also add two tests showing that the -1 substraction in the computation of op_num is really necessary. --- .../aborted_yield_during_nested_fcalls.phpt | 18 ++++++++++++++++++ .../aborted_yield_during_switch.phpt | 19 +++++++++++++++++++ Zend/zend_generators.c | 9 +++++---- 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/generators/aborted_yield_during_nested_fcalls.phpt create mode 100644 Zend/tests/generators/aborted_yield_during_switch.phpt diff --git a/Zend/tests/generators/aborted_yield_during_nested_fcalls.phpt b/Zend/tests/generators/aborted_yield_during_nested_fcalls.phpt new file mode 100644 index 0000000000..9d3bea3ea2 --- /dev/null +++ b/Zend/tests/generators/aborted_yield_during_nested_fcalls.phpt @@ -0,0 +1,18 @@ +--TEST-- +Aborted yield during nested calls +--FILE-- +rewind(); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/generators/aborted_yield_during_switch.phpt b/Zend/tests/generators/aborted_yield_during_switch.phpt new file mode 100644 index 0000000000..1b1d6a15e6 --- /dev/null +++ b/Zend/tests/generators/aborted_yield_during_switch.phpt @@ -0,0 +1,19 @@ +--TEST-- +Aborted yield during switch +--FILE-- +rewind(); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 6a04ebd123..96592fa95d 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -34,15 +34,16 @@ static zend_object *zend_generator_create(zend_class_entry *class_type); static void zend_generator_cleanup_unfinished_execution(zend_generator *generator) /* {{{ */ { zend_execute_data *execute_data = generator->execute_data; - /* -1 required because we want the last run opcode, not the next to-be-run one. */ - uint32_t op_num = execute_data->opline - execute_data->func->op_array.opcodes - 1; if (generator->send_target) { - if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target); + Z_TRY_DELREF_P(generator->send_target); generator->send_target = NULL; } - { + if (execute_data->opline != execute_data->func->op_array.opcodes) { + /* -1 required because we want the last run opcode, not the next to-be-run one. */ + uint32_t op_num = execute_data->opline - execute_data->func->op_array.opcodes - 1; + /* There may be calls to zend_vm_stack_free_call_frame(), which modifies the VM stack * globals, so need to load/restore those. */ zend_vm_stack original_stack = EG(vm_stack); -- 2.40.0