From 67d523dd64d8cf401bb889384a5ce96094b9a005 Mon Sep 17 00:00:00 2001
From: nielsdos <7771979+nielsdos@users.noreply.github.com>
Date: Wed, 3 May 2023 23:45:52 +0200
Subject: [PATCH 1/5] WIP

---
 Zend/zend_operators.c  |   8 ++-
 Zend/zend_vm_def.h     |  14 +++++-
 Zend/zend_vm_execute.h | 112 ++++++++++++++++++++++++++++++++++++++---
 3 files changed, 123 insertions(+), 11 deletions(-)

diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index d16699d698fea..dcb70a2d448b0 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1045,10 +1045,14 @@ static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zva
 	}
 	if (result != op1) {
 		ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1)));
+		zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
 	} else {
-		SEPARATE_ARRAY(result);
+		zval tmp;
+		ZVAL_COPY_VALUE(&tmp, result);
+		SEPARATE_ARRAY(&tmp);
+		zend_hash_merge(Z_ARRVAL_P(&tmp), Z_ARRVAL_P(op2), zval_add_ref, 0);
+		ZVAL_COPY_VALUE(result, &tmp);
 	}
-	zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
 }
 /* }}} */
 
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 0b6604217fa35..24640fabd31e0 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1154,12 +1154,20 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 ZEND_VM_C_LABEL(assign_dim_op_array):
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 ZEND_VM_C_LABEL(assign_dim_op_new_array):
@@ -1181,7 +1189,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -1193,6 +1201,9 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -1232,6 +1243,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 					ZEND_VM_C_GOTO(assign_dim_op_ret_null);
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			ZEND_VM_C_GOTO(assign_dim_op_new_array);
 		} else {
 			dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 21b927c02b895..a09f46dc33a30 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22872,12 +22872,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -22899,7 +22907,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -22911,6 +22919,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -22950,6 +22961,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -25771,12 +25783,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -25798,7 +25818,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -25810,6 +25830,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -25849,6 +25872,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -28172,12 +28196,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -28199,7 +28231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -28211,6 +28243,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -28250,6 +28285,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -30068,12 +30104,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -30095,7 +30139,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -30107,6 +30151,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -30146,6 +30193,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
@@ -41145,12 +41193,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -41172,7 +41228,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -41184,6 +41240,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -41223,6 +41282,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -44985,12 +45045,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -45012,7 +45080,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -45024,6 +45092,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -45063,6 +45134,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -47975,12 +48047,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -48002,7 +48082,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -48014,6 +48094,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -48053,6 +48136,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -50402,12 +50486,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	bool flag = false;
+	zval value_copy;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
 
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
+		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
+			Z_ADDREF_P(&value_copy);
+			flag = true;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -50429,7 +50521,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 			}
 		}
 
-		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 
 		do {
 			if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
@@ -50441,6 +50533,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (flag) {
+				i_zval_ptr_dtor(&value_copy);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -50480,6 +50575,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 					goto assign_dim_op_ret_null;
 				}
 			}
+			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);

From 1924509b58ae1124706bb03d5d0fe3757a80af5e Mon Sep 17 00:00:00 2001
From: nielsdos <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 4 May 2023 19:56:54 +0200
Subject: [PATCH 2/5] Maybe fix angry compiler

---
 Zend/zend_vm_def.h     | 10 +++---
 Zend/zend_vm_execute.h | 82 +++++++++++++++++++++---------------------
 2 files changed, 45 insertions(+), 47 deletions(-)

diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 24640fabd31e0..b8f2bbc1d7778 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1154,7 +1154,6 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -1164,9 +1163,9 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 ZEND_VM_C_LABEL(assign_dim_op_array):
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -1201,7 +1200,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -1244,6 +1243,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			ZEND_VM_C_GOTO(assign_dim_op_new_array);
 		} else {
 			dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index a09f46dc33a30..f1cea2194f4a8 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22872,7 +22872,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -22882,9 +22881,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -22907,8 +22906,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -22919,7 +22916,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -22962,6 +22959,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -25783,7 +25781,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -25793,9 +25790,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -25830,7 +25827,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -25873,6 +25870,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -28196,7 +28194,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -28206,9 +28203,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -28243,7 +28240,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -28286,6 +28283,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -30104,7 +30102,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -30114,9 +30111,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -30151,7 +30148,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -30194,6 +30191,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
@@ -41193,7 +41191,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -41203,9 +41200,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -41240,7 +41237,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -41283,6 +41280,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -45045,7 +45043,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -45055,9 +45052,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -45092,7 +45089,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -45135,6 +45132,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -48047,7 +48045,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -48057,9 +48054,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -48094,7 +48091,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -48137,6 +48134,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -50486,7 +50484,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	bool flag = false;
 	zval value_copy;
 
 	SAVE_OPLINE();
@@ -50496,9 +50493,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
 		if (UNEXPECTED(Z_ISREF_P(value))) {
-			ZVAL_COPY_VALUE(&value_copy, Z_REFVAL_P(value));
-			Z_ADDREF_P(&value_copy);
-			flag = true;
+			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+		} else {
+			ZVAL_UNDEF(&value_copy);
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -50533,7 +50530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (flag) {
+			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -50576,6 +50573,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
+			ZVAL_UNDEF(&value_copy);
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);

From 64de68483b490344bcef55ec6c20c48c7cc602d1 Mon Sep 17 00:00:00 2001
From: nielsdos <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 4 May 2023 20:36:04 +0200
Subject: [PATCH 3/5] Now fixed the compiler warning for real

---
 Zend/zend_vm_def.h     |  14 +++---
 Zend/zend_vm_execute.h | 110 ++++++++++++++++++++++++-----------------
 2 files changed, 72 insertions(+), 52 deletions(-)

diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b8f2bbc1d7778..8a5598c02be57 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1162,10 +1162,14 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 ZEND_VM_C_LABEL(assign_dim_op_array):
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -1188,8 +1192,6 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -1200,7 +1202,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -1243,7 +1245,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			ZEND_VM_C_GOTO(assign_dim_op_new_array);
 		} else {
 			dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index f1cea2194f4a8..aa027353e35ee 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22880,10 +22880,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -22916,7 +22920,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -22959,7 +22963,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -25789,10 +25793,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -25815,8 +25823,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -25827,7 +25833,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -25870,7 +25876,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -28202,10 +28208,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -28228,8 +28238,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -28240,7 +28248,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -28283,7 +28291,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -30110,10 +30118,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -30136,8 +30148,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -30148,7 +30158,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -30191,7 +30201,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
@@ -41199,10 +41209,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -41225,8 +41239,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -41237,7 +41249,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -41280,7 +41292,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -45051,10 +45063,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -45077,8 +45093,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -45089,7 +45103,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -45132,7 +45146,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -48053,10 +48067,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -48079,8 +48097,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -48091,7 +48107,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -48134,7 +48150,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -50492,10 +50508,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
+			 * We need to do this here already to do a correct array separation in case the value is related to
+			 * the array. */
 			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
 		} else {
-			ZVAL_UNDEF(&value_copy);
+			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
+			Z_COUNTED(value_copy) = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -50518,8 +50538,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 			}
 		}
 
-		// value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-
 		do {
 			if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
 				zend_reference *ref = Z_REF_P(var_ptr);
@@ -50530,7 +50548,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_TYPE(value_copy) != IS_UNDEF)) {
+			if (UNEXPECTED(Z_COUNTED(value_copy))) {
 				i_zval_ptr_dtor(&value_copy);
 			}
 		} while (0);
@@ -50573,7 +50591,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			ZVAL_UNDEF(&value_copy);
+			Z_COUNTED(value_copy) = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);

From c6a47280c828653fd93044da861d44370b8993ce Mon Sep 17 00:00:00 2001
From: nielsdos <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 4 May 2023 21:15:03 +0200
Subject: [PATCH 4/5] Improvements and tests

---
 Zend/tests/gh10085_1.phpt |  22 ++++++
 Zend/tests/gh10085_2.phpt |  25 +++++++
 Zend/zend_vm_def.h        |  19 +++--
 Zend/zend_vm_execute.h    | 152 ++++++++++++++++++--------------------
 4 files changed, 128 insertions(+), 90 deletions(-)
 create mode 100644 Zend/tests/gh10085_1.phpt
 create mode 100644 Zend/tests/gh10085_2.phpt

diff --git a/Zend/tests/gh10085_1.phpt b/Zend/tests/gh10085_1.phpt
new file mode 100644
index 0000000000000..cc11c96a09d32
--- /dev/null
+++ b/Zend/tests/gh10085_1.phpt
@@ -0,0 +1,22 @@
+--TEST--
+GH-10085: Assertion in add_function_array()
+--FILE--
+<?php
+$i = [[], 0];
+$ref = &$i;
+$i[0] += $ref;
+var_dump($i);
+?>
+--EXPECT--
+array(2) {
+  [0]=>
+  array(2) {
+    [0]=>
+    array(0) {
+    }
+    [1]=>
+    int(0)
+  }
+  [1]=>
+  int(0)
+}
diff --git a/Zend/tests/gh10085_2.phpt b/Zend/tests/gh10085_2.phpt
new file mode 100644
index 0000000000000..7895999f2cd05
--- /dev/null
+++ b/Zend/tests/gh10085_2.phpt
@@ -0,0 +1,25 @@
+--TEST--
+GH-10085: Assertion in add_function_array()
+--FILE--
+<?php
+$tmp = [0];
+unset($tmp[0]);
+$i = [$tmp, 0];
+unset($tmp);
+$ref = &$i;
+$i[0] += $ref;
+var_dump($i);
+?>
+--EXPECT--
+array(2) {
+  [0]=>
+  array(2) {
+    [0]=>
+    array(0) {
+    }
+    [1]=>
+    int(0)
+  }
+  [1]=>
+  int(0)
+}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 8a5598c02be57..a0cb6319c49d9 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1154,7 +1154,7 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
@@ -1162,14 +1162,13 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 ZEND_VM_C_LABEL(assign_dim_op_array):
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -1202,8 +1201,8 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -1245,7 +1244,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			ZEND_VM_C_GOTO(assign_dim_op_new_array);
 		} else {
 			dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index aa027353e35ee..fababf2cda456 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22872,7 +22872,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
@@ -22880,14 +22880,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -22920,8 +22919,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -22963,7 +22962,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -25785,7 +25784,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
@@ -25793,14 +25792,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -25833,8 +25831,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -25876,7 +25874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -28200,7 +28198,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
@@ -28208,14 +28206,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -28248,8 +28245,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -28291,7 +28288,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -30110,7 +30107,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC);
@@ -30118,14 +30115,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -30158,8 +30154,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -30201,7 +30197,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
@@ -41201,7 +41197,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
@@ -41209,14 +41205,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -41249,8 +41244,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -41292,7 +41287,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -45055,7 +45050,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
@@ -45063,14 +45058,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -45103,8 +45097,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -45146,7 +45140,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -48059,7 +48053,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
@@ -48067,14 +48061,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -48107,8 +48100,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -48150,7 +48143,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -50500,7 +50493,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
-	zval value_copy;
+	zend_array *value_array;
 
 	SAVE_OPLINE();
 	container = EX_VAR(opline->op1.var);
@@ -50508,14 +50501,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value)) && Z_OPT_REFCOUNTED_P(Z_REFVAL_P(value))) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to
-			 * the array. */
-			ZVAL_COPY(&value_copy, Z_REFVAL_P(value));
+			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			value_array = Z_ARR_P(Z_REFVAL_P(value));
+			GC_ADDREF(value_array);
 		} else {
-			/* Have to do it this way because for types the compiler gives a bogus uninitialized value warning. */
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
@@ -50548,8 +50540,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
-			if (UNEXPECTED(Z_COUNTED(value_copy))) {
-				i_zval_ptr_dtor(&value_copy);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
 			}
 		} while (0);
 
@@ -50591,7 +50583,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 				}
 			}
 			value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-			Z_COUNTED(value_copy) = NULL;
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);

From 87f41b4500e3a535ecafc04d0443d654454d45a4 Mon Sep 17 00:00:00 2001
From: nielsdos <7771979+nielsdos@users.noreply.github.com>
Date: Thu, 4 May 2023 22:08:40 +0200
Subject: [PATCH 5/5] Switch to a more performance-neutral approach

---
 Zend/zend_vm_def.h     |  5 +++--
 Zend/zend_vm_execute.h | 40 ++++++++++++++++++++++++----------------
 2 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index a0cb6319c49d9..c544fbaa4a488 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1162,9 +1162,10 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 ZEND_VM_C_LABEL(assign_dim_op_array):
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index fababf2cda456..473749f31aa98 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22880,9 +22880,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -25792,9 +25793,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -28206,9 +28208,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -30115,9 +30118,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -41205,9 +41209,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -45058,9 +45063,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -48061,9 +48067,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {
@@ -50501,9 +50508,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 assign_dim_op_array:
 		value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
-		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY)) {
+		if (UNEXPECTED(Z_ISREF_P(value) && Z_TYPE_P(Z_REFVAL_P(value)) == IS_ARRAY && Z_ARRVAL_P(Z_REFVAL_P(value)) == Z_ARRVAL_P(container) && !(GC_FLAGS(Z_ARRVAL_P(container)) & GC_IMMUTABLE))) {
 			/* The binary OP would normally deref the reference, so an increase in RC would only be done later.
-			 * We need to do this here already to do a correct array separation in case the value is related to the array. */
+			 * We need to do this here already to do a correct array separation in case the value is related to the array.
+			 * The only case where this would be problematic is when the container and value are the same array. */
 			value_array = Z_ARR_P(Z_REFVAL_P(value));
 			GC_ADDREF(value_array);
 		} else {