diff options
author | Bob Weinand <bobwei9@hotmail.com> | 2020-09-15 20:07:25 +0200 |
---|---|---|
committer | Bob Weinand <bobwei9@hotmail.com> | 2020-09-15 20:07:33 +0200 |
commit | 6d538e83aa1e98694402eea5433e38d387f8729a (patch) | |
tree | d4d89d3cd6aa0fc412d389ef1d036eaf30167dff | |
parent | 7a95e943d642e05532979a06221c476183eac7e4 (diff) | |
download | php-git-6d538e83aa1e98694402eea5433e38d387f8729a.tar.gz |
Fix OSS Fuzz issue: yielding from an aborted generator
-rw-r--r-- | Zend/tests/generators/yield_from_aborted_generator_with_children.phpt | 31 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 12 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 36 |
3 files changed, 55 insertions, 24 deletions
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-- +<?php + +function from() { + yield 0; + throw new Exception(); +} +function gen($gen) { + yield from $gen; +} + +$gen1 = from(); +$gen2 = gen($gen1); +$gen3 = gen($gen1); +try { + $gen2->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); |