diff options
-rw-r--r-- | Zend/tests/generators/yield_from_already_running.phpt | 14 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 11 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 44 |
3 files changed, 59 insertions, 10 deletions
diff --git a/Zend/tests/generators/yield_from_already_running.phpt b/Zend/tests/generators/yield_from_already_running.phpt new file mode 100644 index 0000000000..789490ccd3 --- /dev/null +++ b/Zend/tests/generators/yield_from_already_running.phpt @@ -0,0 +1,14 @@ +--TEST-- +Yielding from the already running Generator should fail (bug #69458) +--FILE-- +<?php + +function gen() { + yield from yield; +} + +($gen = gen())->send($gen); + +?> +--EXPECTF-- +Fatal error: Impossible to yield from the Generator being currently run in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a2f7ace870..f4bd498832 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7389,8 +7389,15 @@ ZEND_VM_HANDLER(142, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY) FREE_OP1_IF_VAR(); if (Z_ISUNDEF(new_gen->retval)) { - zend_generator_yield_from(generator, new_gen); - } else if (new_gen->execute_data == NULL) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run"); + + HANDLE_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue"); HANDLE_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 457de3dd9f..94ed61d7c7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4045,8 +4045,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( } if (Z_ISUNDEF(new_gen->retval)) { - zend_generator_yield_from(generator, new_gen); - } else if (new_gen->execute_data == NULL) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run"); + + HANDLE_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue"); HANDLE_EXCEPTION(); @@ -11678,8 +11685,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZE } if (Z_ISUNDEF(new_gen->retval)) { - zend_generator_yield_from(generator, new_gen); - } else if (new_gen->execute_data == NULL) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run"); + + HANDLE_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue"); HANDLE_EXCEPTION(); @@ -15377,8 +15391,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZE zval_ptr_dtor_nogc(free_op1); if (Z_ISUNDEF(new_gen->retval)) { - zend_generator_yield_from(generator, new_gen); - } else if (new_gen->execute_data == NULL) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run"); + + HANDLE_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue"); HANDLE_EXCEPTION(); @@ -28967,8 +28988,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN } if (Z_ISUNDEF(new_gen->retval)) { - zend_generator_yield_from(generator, new_gen); - } else if (new_gen->execute_data == NULL) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run"); + + HANDLE_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue"); HANDLE_EXCEPTION(); |