Skip to content

Commit 6d538e8

Browse files
committed
Fix OSS Fuzz issue: yielding from an aborted generator
1 parent 7a95e94 commit 6d538e8

File tree

3 files changed

+55
-24
lines changed

3 files changed

+55
-24
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Impossible to yield from a generator which already failed, nested version
3+
--FILE--
4+
<?php
5+
6+
function from() {
7+
yield 0;
8+
throw new Exception();
9+
}
10+
function gen($gen) {
11+
yield from $gen;
12+
}
13+
14+
$gen1 = from();
15+
$gen2 = gen($gen1);
16+
$gen3 = gen($gen1);
17+
try {
18+
$gen2->next();
19+
} catch (Exception $e) {
20+
unset($gen2);
21+
}
22+
$gen3->next();
23+
24+
?>
25+
--EXPECTF--
26+
Fatal error: Uncaught Error: Generator passed to yield from was aborted without proper return and is unable to continue in %s:%d
27+
Stack trace:
28+
#0 [internal function]: gen(Object(Generator))
29+
#1 %s(%d): Generator->next()
30+
#2 {main}
31+
thrown in %s on line %d

Zend/zend_vm_def.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8033,7 +8033,12 @@ ZEND_VM_C_LABEL(yield_from_try_again):
80338033
Z_ADDREF_P(val);
80348034
FREE_OP1();
80358035

8036-
if (Z_ISUNDEF(new_gen->retval)) {
8036+
if (UNEXPECTED(new_gen->execute_data == NULL)) {
8037+
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
8038+
zval_ptr_dtor(val);
8039+
UNDEF_RESULT();
8040+
HANDLE_EXCEPTION();
8041+
} else if (Z_ISUNDEF(new_gen->retval)) {
80378042
if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
80388043
zend_throw_error(NULL, "Impossible to yield from the Generator being currently run");
80398044
zval_ptr_dtor(val);
@@ -8042,11 +8047,6 @@ ZEND_VM_C_LABEL(yield_from_try_again):
80428047
} else {
80438048
zend_generator_yield_from(generator, new_gen);
80448049
}
8045-
} else if (UNEXPECTED(new_gen->execute_data == NULL)) {
8046-
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
8047-
zval_ptr_dtor(val);
8048-
UNDEF_RESULT();
8049-
HANDLE_EXCEPTION();
80508050
} else {
80518051
if (RETURN_VALUE_USED(opline)) {
80528052
ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval);

Zend/zend_vm_execute.h

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5376,7 +5376,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(
53765376

53775377
Z_ADDREF_P(val);
53785378

5379-
if (Z_ISUNDEF(new_gen->retval)) {
5379+
if (UNEXPECTED(new_gen->execute_data == NULL)) {
5380+
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
5381+
zval_ptr_dtor(val);
5382+
UNDEF_RESULT();
5383+
HANDLE_EXCEPTION();
5384+
} else if (Z_ISUNDEF(new_gen->retval)) {
53805385
if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
53815386
zend_throw_error(NULL, "Impossible to yield from the Generator being currently run");
53825387
zval_ptr_dtor(val);
@@ -5385,11 +5390,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(
53855390
} else {
53865391
zend_generator_yield_from(generator, new_gen);
53875392
}
5388-
} else if (UNEXPECTED(new_gen->execute_data == NULL)) {
5389-
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
5390-
zval_ptr_dtor(val);
5391-
UNDEF_RESULT();
5392-
HANDLE_EXCEPTION();
53935393
} else {
53945394
if (RETURN_VALUE_USED(opline)) {
53955395
ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval);
@@ -14615,7 +14615,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER
1461514615
Z_ADDREF_P(val);
1461614616
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
1461714617

14618-
if (Z_ISUNDEF(new_gen->retval)) {
14618+
if (UNEXPECTED(new_gen->execute_data == NULL)) {
14619+
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
14620+
zval_ptr_dtor(val);
14621+
UNDEF_RESULT();
14622+
HANDLE_EXCEPTION();
14623+
} else if (Z_ISUNDEF(new_gen->retval)) {
1461914624
if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
1462014625
zend_throw_error(NULL, "Impossible to yield from the Generator being currently run");
1462114626
zval_ptr_dtor(val);
@@ -14624,11 +14629,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER
1462414629
} else {
1462514630
zend_generator_yield_from(generator, new_gen);
1462614631
}
14627-
} else if (UNEXPECTED(new_gen->execute_data == NULL)) {
14628-
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
14629-
zval_ptr_dtor(val);
14630-
UNDEF_RESULT();
14631-
HANDLE_EXCEPTION();
1463214632
} else {
1463314633
if (RETURN_VALUE_USED(opline)) {
1463414634
ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval);
@@ -39261,7 +39261,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN
3926139261

3926239262
Z_ADDREF_P(val);
3926339263

39264-
if (Z_ISUNDEF(new_gen->retval)) {
39264+
if (UNEXPECTED(new_gen->execute_data == NULL)) {
39265+
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
39266+
zval_ptr_dtor(val);
39267+
UNDEF_RESULT();
39268+
HANDLE_EXCEPTION();
39269+
} else if (Z_ISUNDEF(new_gen->retval)) {
3926539270
if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
3926639271
zend_throw_error(NULL, "Impossible to yield from the Generator being currently run");
3926739272
zval_ptr_dtor(val);
@@ -39270,11 +39275,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN
3927039275
} else {
3927139276
zend_generator_yield_from(generator, new_gen);
3927239277
}
39273-
} else if (UNEXPECTED(new_gen->execute_data == NULL)) {
39274-
zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
39275-
zval_ptr_dtor(val);
39276-
UNDEF_RESULT();
39277-
HANDLE_EXCEPTION();
3927839278
} else {
3927939279
if (RETURN_VALUE_USED(opline)) {
3928039280
ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval);

0 commit comments

Comments
 (0)