diff options
-rw-r--r-- | Zend/tests/generators/yield_from_force_closed.phpt | 37 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 6 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 24 |
3 files changed, 67 insertions, 0 deletions
diff --git a/Zend/tests/generators/yield_from_force_closed.phpt b/Zend/tests/generators/yield_from_force_closed.phpt new file mode 100644 index 0000000000..87fcd2e8ed --- /dev/null +++ b/Zend/tests/generators/yield_from_force_closed.phpt @@ -0,0 +1,37 @@ +--TEST-- +Cannot "yield from" from force closed generator +--FILE-- +<?php + +function gen1() { + echo "gen1\n"; + yield 1; +} + +function gen2() { + try { + echo "try\n"; + yield from gen1(); + } finally { + echo "finally\n"; + yield from gen1(); + } +} + +try { + $gen = gen2(); + $gen->rewind(); + unset($gen); +} catch (Error $e) { + echo $e, "\n"; +} + +?> +--EXPECTF-- +try +gen1 +finally +Error: Cannot use "yield from" in a force-closed generator in %s:%d +Stack trace: +#0 %s(%d): gen2() +#1 {main} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index cbb986b028..ce7c6faea2 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7442,6 +7442,12 @@ ZEND_VM_HANDLER(142, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY) SAVE_OPLINE(); val = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + FREE_OP1(); + HANDLE_EXCEPTION(); + } + if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); if (OP1_TYPE != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d9d58e02ab..aba8081585 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4106,6 +4106,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( SAVE_OPLINE(); val = EX_CONSTANT(opline->op1); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + + HANDLE_EXCEPTION(); + } + if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { @@ -12502,6 +12508,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZE SAVE_OPLINE(); val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { @@ -16320,6 +16332,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZE SAVE_OPLINE(); val = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } + if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { @@ -29759,6 +29777,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN SAVE_OPLINE(); val = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + + HANDLE_EXCEPTION(); + } + if (Z_TYPE_P(val) == IS_ARRAY) { ZVAL_COPY_VALUE(&generator->values, val); if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(val)) { |