From 6d538e83aa1e98694402eea5433e38d387f8729a Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 15 Sep 2020 20:07:25 +0200 Subject: [PATCH] Fix OSS Fuzz issue: yielding from an aborted generator --- ..._from_aborted_generator_with_children.phpt | 31 ++++++++++++++++ Zend/zend_vm_def.h | 12 +++---- Zend/zend_vm_execute.h | 36 +++++++++---------- 3 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 Zend/tests/generators/yield_from_aborted_generator_with_children.phpt diff --git a/Zend/tests/generators/yield_from_aborted_generator_with_children.phpt b/Zend/tests/generators/yield_from_aborted_generator_with_children.phpt new file mode 100644 index 0000000000..7074e40ab6 --- /dev/null +++ b/Zend/tests/generators/yield_from_aborted_generator_with_children.phpt @@ -0,0 +1,31 @@ +--TEST-- +Impossible to yield from a generator which already failed, nested version +--FILE-- +next(); +} catch (Exception $e) { + unset($gen2); +} +$gen3->next(); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Generator passed to yield from was aborted without proper return and is unable to continue in %s:%d +Stack trace: +#0 [internal function]: gen(Object(Generator)) +#1 %s(%d): Generator->next() +#2 {main} + thrown in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 02a5e2c963..59a49cb413 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8033,7 +8033,12 @@ ZEND_VM_C_LABEL(yield_from_try_again): Z_ADDREF_P(val); FREE_OP1(); - if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); zval_ptr_dtor(val); @@ -8042,11 +8047,6 @@ ZEND_VM_C_LABEL(yield_from_try_again): } else { zend_generator_yield_from(generator, new_gen); } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); } else { if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e03712f868..0b1795f3ee 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5376,7 +5376,12 @@ yield_from_try_again: Z_ADDREF_P(val); - if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); zval_ptr_dtor(val); @@ -5385,11 +5390,6 @@ yield_from_try_again: } else { zend_generator_yield_from(generator, new_gen); } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); } else { if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); @@ -14615,7 +14615,12 @@ yield_from_try_again: Z_ADDREF_P(val); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); zval_ptr_dtor(val); @@ -14624,11 +14629,6 @@ yield_from_try_again: } else { zend_generator_yield_from(generator, new_gen); } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); } else { if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); @@ -39261,7 +39261,12 @@ yield_from_try_again: Z_ADDREF_P(val); - if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); zval_ptr_dtor(val); @@ -39270,11 +39275,6 @@ yield_from_try_again: } else { zend_generator_yield_from(generator, new_gen); } - } else if (UNEXPECTED(new_gen->execute_data == NULL)) { - zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); - zval_ptr_dtor(val); - UNDEF_RESULT(); - HANDLE_EXCEPTION(); } else { if (RETURN_VALUE_USED(opline)) { ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); -- 2.40.0