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_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..c544fbaa4a488 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1154,12 +1154,23 @@ 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;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 ZEND_VM_C_LABEL(assign_dim_op_new_array):
@@ -1181,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);
@@ -1193,6 +1202,9 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 				}
 			}
 			zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
+			if (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -1232,6 +1244,8 @@ 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);
+			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 21b927c02b895..473749f31aa98 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22872,12 +22872,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -22899,8 +22910,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);
@@ -22911,6 +22920,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -22950,6 +22962,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -25771,12 +25785,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -25798,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);
@@ -25810,6 +25833,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -25849,6 +25875,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -28172,12 +28200,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -28199,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);
@@ -28211,6 +28248,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -28250,6 +28290,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -30068,12 +30110,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -30095,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);
@@ -30107,6 +30158,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -30146,6 +30200,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);
@@ -41145,12 +41201,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -41172,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);
@@ -41184,6 +41249,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -41223,6 +41291,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = RT_CONSTANT(opline, opline->op2);
@@ -44985,12 +45055,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -45012,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);
@@ -45024,6 +45103,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -45063,6 +45145,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC);
@@ -47975,12 +48059,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -48002,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);
@@ -48014,6 +48107,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -48053,6 +48149,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = NULL;
@@ -50402,12 +50500,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL
 	zval *var_ptr;
 	zval *value, *container, *dim;
 	HashTable *ht;
+	zend_array *value_array;
 
 	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) && 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.
+			 * 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 {
+			value_array = NULL;
+		}
 		SEPARATE_ARRAY(container);
 		ht = Z_ARRVAL_P(container);
 assign_dim_op_new_array:
@@ -50429,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);
@@ -50441,6 +50548,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 (UNEXPECTED(value_array)) {
+				GC_DTOR_NO_REF(value_array);
+			}
 		} while (0);
 
 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -50480,6 +50590,8 @@ 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);
+			value_array = NULL;
 			goto assign_dim_op_new_array;
 		} else {
 			dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC);