summaryrefslogtreecommitdiff
path: root/Zend/zend_vm_execute.h
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r--Zend/zend_vm_execute.h1935
1 files changed, 1520 insertions, 415 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 29b6d7c500..b1bcd74d23 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4118,6 +4118,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -4133,29 +4134,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
/* Set the new yielded value */
if (IS_CONST != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = opline->op1.zv;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = opline->op1.zv;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
- generator->value = copy;
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -4759,6 +4803,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -4774,29 +4819,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
/* Set the new yielded value */
if (IS_CONST != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = opline->op1.zv;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = opline->op1.zv;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
- generator->value = copy;
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -5725,6 +5813,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -5740,29 +5829,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
/* Set the new yielded value */
if (IS_CONST != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = opline->op1.zv;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = opline->op1.zv;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = opline->op1.zv;
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -6386,6 +6518,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -6401,29 +6534,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
/* Set the new yielded value */
if (IS_CONST != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = opline->op1.zv;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = opline->op1.zv;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- generator->value = copy;
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = opline->op1.zv;
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -7086,6 +7262,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -7101,29 +7278,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
/* Set the new yielded value */
if (IS_CONST != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = opline->op1.zv;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = opline->op1.zv;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- generator->value = copy;
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = opline->op1.zv;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -9093,6 +9313,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -9109,29 +9330,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_
/* Set the new yielded value */
if (IS_TMP_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!1) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -9734,6 +9998,7 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -9750,29 +10015,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
/* Set the new yielded value */
if (IS_TMP_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!1) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
- generator->value = copy;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -10700,6 +11008,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -10716,29 +11025,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
/* Set the new yielded value */
if (IS_TMP_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!1) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
- generator->value = copy;
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -11227,6 +11579,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -11243,29 +11596,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
/* Set the new yielded value */
if (IS_TMP_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!1) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
- generator->value = copy;
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -11865,6 +12261,7 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -11881,29 +12278,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* Set the new yielded value */
if (IS_TMP_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!1) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!1) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -15729,6 +16169,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -15745,30 +16186,74 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_
/* Set the new yielded value */
if (IS_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -17757,6 +18242,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -17773,30 +18259,74 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
/* Set the new yielded value */
if (IS_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- generator->value = copy;
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -20165,6 +20695,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -20181,30 +20712,74 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
/* Set the new yielded value */
if (IS_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- generator->value = copy;
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -21252,6 +21827,7 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -21268,30 +21844,74 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
/* Set the new yielded value */
if (IS_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- generator->value = copy;
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -23329,6 +23949,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zend_free_op free_op1;
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -23345,30 +23966,74 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* Set the new yielded value */
if (IS_VAR != IS_UNUSED) {
- zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
+ zval *value, *copy;
- /* Consts, temporary variables and references need copying */
- if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- generator->value = copy;
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ /* Consts, temporary variables and references need copying */
+ if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -24766,6 +25431,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -24781,29 +25447,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
/* Set the new yielded value */
if (IS_UNUSED != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = NULL;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = NULL;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
- generator->value = copy;
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -26025,6 +26734,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -26040,29 +26750,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
/* Set the new yielded value */
if (IS_UNUSED != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = NULL;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = NULL;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -27284,6 +28037,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -27299,29 +28053,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
/* Set the new yielded value */
if (IS_UNUSED != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = NULL;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = NULL;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -27655,6 +28452,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -27670,29 +28468,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
/* Set the new yielded value */
if (IS_UNUSED != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = NULL;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = NULL;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -28911,6 +29752,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -28926,29 +29768,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
/* Set the new yielded value */
if (IS_UNUSED != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = NULL;
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = NULL;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = NULL;
- generator->value = copy;
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = NULL;
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -32376,6 +33261,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -32391,29 +33277,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
/* Set the new yielded value */
if (IS_CV != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- generator->value = copy;
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -34274,6 +35203,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -34289,29 +35219,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* Set the new yielded value */
if (IS_CV != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
- generator->value = copy;
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -36551,6 +37524,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -36566,29 +37540,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* Set the new yielded value */
if (IS_CV != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
- generator->value = copy;
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
+
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -37498,6 +38515,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -37513,29 +38531,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
/* Set the new yielded value */
if (IS_CV != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
- generator->value = copy;
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));
@@ -39444,6 +40505,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
{
USE_OPLINE
+
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
@@ -39459,29 +40521,72 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* Set the new yielded value */
if (IS_CV != IS_UNUSED) {
+ if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ /* Constants and temporary variables aren't yieldable by reference,
+ * but we still allow them with a notice. */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ zval *value, *copy;
- zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- /* Consts, temporary variables and references need copying */
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
- ) {
- zval *copy;
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
- ALLOC_ZVAL(copy);
- INIT_PZVAL_COPY(copy, value);
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
- /* Temporary variables don't need ctor copying */
- if (!0) {
- zval_copy_ctor(copy);
- }
+ generator->value = copy;
+ } else {
+ zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
+ }
+
+ /* If a function call result is yielded and the function did
+ * not return by reference we throw a notice. */
+ if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr)
+ && !(opline->extended_value == ZEND_RETURNS_FUNCTION
+ && EX_T(opline->op1.var).var.fcall_returned_reference)
+ && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ } else {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ Z_ADDREF_PP(value_ptr);
+ generator->value = *value_ptr;
+ }
- generator->value = copy;
+ }
} else {
- Z_ADDREF_P(value);
- generator->value = value;
- }
+ zval *value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ /* Consts, temporary variables and references need copying */
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR
+ || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ ) {
+ zval *copy;
+
+ ALLOC_ZVAL(copy);
+ INIT_PZVAL_COPY(copy, value);
+
+ /* Temporary variables don't need ctor copying */
+ if (!0) {
+ zval_copy_ctor(copy);
+ }
+
+ generator->value = copy;
+ } else {
+ Z_ADDREF_P(value);
+ generator->value = value;
+ }
+ }
} else {
/* If no value was specified yield null */
Z_ADDREF(EG(uninitialized_zval));