Skip to content

Commit ea5c66e

Browse files
committed
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.
1 parent f4d08d8 commit ea5c66e

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Aborted yield during nested calls
3+
--FILE--
4+
<?php
5+
6+
function func() {}
7+
8+
function gen($x) {
9+
func(func($x, $x, func($x, yield)));
10+
}
11+
12+
$gen = gen("x");
13+
$gen->rewind();
14+
15+
?>
16+
===DONE===
17+
--EXPECT--
18+
===DONE===
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Aborted yield during switch
3+
--FILE--
4+
<?php
5+
6+
function gen($x) {
7+
switch ($x."y") {
8+
default:
9+
yield;
10+
}
11+
}
12+
13+
$gen = gen("x");
14+
$gen->rewind();
15+
16+
?>
17+
===DONE===
18+
--EXPECT--
19+
===DONE===

Zend/zend_generators.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,16 @@ static zend_object *zend_generator_create(zend_class_entry *class_type);
3434
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator) /* {{{ */
3535
{
3636
zend_execute_data *execute_data = generator->execute_data;
37-
/* -1 required because we want the last run opcode, not the next to-be-run one. */
38-
uint32_t op_num = execute_data->opline - execute_data->func->op_array.opcodes - 1;
3937

4038
if (generator->send_target) {
41-
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
39+
Z_TRY_DELREF_P(generator->send_target);
4240
generator->send_target = NULL;
4341
}
4442

45-
{
43+
if (execute_data->opline != execute_data->func->op_array.opcodes) {
44+
/* -1 required because we want the last run opcode, not the next to-be-run one. */
45+
uint32_t op_num = execute_data->opline - execute_data->func->op_array.opcodes - 1;
46+
4647
/* There may be calls to zend_vm_stack_free_call_frame(), which modifies the VM stack
4748
* globals, so need to load/restore those. */
4849
zend_vm_stack original_stack = EG(vm_stack);

0 commit comments

Comments
 (0)