diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/generators/bug66041.phpt | 17 | ||||
-rw-r--r-- | Zend/zend_compile.c | 2 | ||||
-rw-r--r-- | Zend/zend_generators.c | 13 | ||||
-rw-r--r-- | Zend/zend_generators.h | 2 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 14 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 350 |
7 files changed, 266 insertions, 134 deletions
@@ -4,6 +4,8 @@ PHP NEWS - Core: . Added validation of class names in the autoload process. (Dmitry) + . Fixed buf #66041 (list() fails to unpack yielded ArrayAccess object). + (Nikita) - Date: . Fixed bug #66060 (Heap buffer over-read in DateInterval). (Remi) diff --git a/Zend/tests/generators/bug66041.phpt b/Zend/tests/generators/bug66041.phpt new file mode 100644 index 0000000000..d944224134 --- /dev/null +++ b/Zend/tests/generators/bug66041.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #66041: list() fails to unpack yielded ArrayAccess object +--FILE-- +<?php +function dumpElement() { + list($value) = yield; + var_dump($value); +}; + +$fixedArray = new SplFixedArray(1); +$fixedArray[0] = 'the element'; + +$generator = dumpElement(); +$generator->send($fixedArray); +?> +--EXPECT-- +string(11) "the element" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 60b9e3e653..c5f3769216 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2782,7 +2782,7 @@ void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_v SET_UNUSED(opline->op2); } - opline->result_type = IS_TMP_VAR; + opline->result_type = IS_VAR; opline->result.var = get_temporary_variable(CG(active_op_array)); GET_NODE(result, opline->result); } diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 0af20f4593..c0116332e7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -55,6 +55,11 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished zval_ptr_dtor(&execute_data->current_this); } + if (!finished_execution && generator->send_target) { + Z_DELREF_PP(generator->send_target); + generator->send_target = NULL; + } + /* A fatal error / die occurred during the generator execution. Trying to clean * up the stack may not be safe in this case. */ if (CG(unclean_shutdown)) { @@ -519,8 +524,12 @@ ZEND_METHOD(Generator, send) return; } - /* Put sent value into the TMP_VAR slot */ - MAKE_COPY_ZVAL(&value, &generator->send_target->tmp_var); + /* Put sent value in the target VAR slot, if it is used */ + if (generator->send_target) { + Z_DELREF_PP(generator->send_target); + Z_ADDREF_P(value); + *generator->send_target = value; + } zend_generator_resume(generator TSRMLS_CC); diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index bc125658ee..d5f6101315 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -49,7 +49,7 @@ typedef struct _zend_generator { /* Current key */ zval *key; /* Variable to put sent value into */ - temp_variable *send_target; + zval **send_target; /* Largest used integer key for auto-incrementing keys */ long largest_used_integer_key; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 05557e9833..9db6ea19f9 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5353,11 +5353,15 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ec29f9e7d8..3a0a70e946 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4198,11 +4198,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -4887,11 +4891,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -5904,11 +5912,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -6625,11 +6637,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -7373,11 +7389,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -9400,11 +9420,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -10091,11 +10115,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -11110,11 +11138,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -11690,11 +11722,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -12378,11 +12414,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -16265,11 +16305,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -18350,11 +18394,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -20818,11 +20866,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -21970,11 +22022,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -24104,11 +24160,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -25602,11 +25662,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -26916,11 +26980,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -28231,11 +28299,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -28653,11 +28725,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -29964,11 +30040,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -33449,11 +33529,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -35396,11 +35480,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -37725,11 +37813,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -38729,11 +38821,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ @@ -40724,11 +40820,15 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZVAL_LONG(generator->key, generator->largest_used_integer_key); } - /* If a value is sent it should go into the result var */ - generator->send_target = &EX_T(opline->result.var); - - /* Initialize the sent value to NULL */ - EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = &EX_T(opline->result.var).var.ptr; + Z_ADDREF(EG(uninitialized_zval)); + EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval); + } else { + generator->send_target = NULL; + } /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ |