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-- + +--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-- + +--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 {