diff --git a/Zend/tests/gh10571_1.phpt b/Zend/tests/gh10571_1.phpt new file mode 100644 index 0000000000000..9442da8dd5289 --- /dev/null +++ b/Zend/tests/gh10571_1.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-10571: Assertion `zval_get_type(&(*(zptr))) == 6 && "Concat should return string"' failed - OP +--FILE-- +prop .= new B(); +var_dump($a); +?> +--EXPECT-- +string(0) "" diff --git a/Zend/tests/gh10571_2.phpt b/Zend/tests/gh10571_2.phpt new file mode 100644 index 0000000000000..a2e9ed9067a31 --- /dev/null +++ b/Zend/tests/gh10571_2.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-10571: Assertion `zval_get_type(&(*(zptr))) == 6 && "Concat should return string"' failed - DIM OP +--FILE-- +prop[0] .= new B(); +var_dump($a); +?> +--EXPECT-- +string(0) "" diff --git a/Zend/tests/gh10571_3.phpt b/Zend/tests/gh10571_3.phpt new file mode 100644 index 0000000000000..da84b82767f6e --- /dev/null +++ b/Zend/tests/gh10571_3.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-10571: Assertion `zval_get_type(&(*(zptr))) == 6 && "Concat should return string"' failed - DIM OP resize +--FILE-- +prop[] = $i; + } + return "x"; + } +} + +$a = new A(); +$a->prop[0] .= new B(); +var_dump(count($a->prop)); +var_dump($a->prop[0]); +?> +--EXPECT-- +int(1001) +string(1) "a" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 77c1487b65c62..bb7c1a4c85b61 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1059,6 +1059,10 @@ ZEND_VM_C_LABEL(assign_op_object): zval *orig_zptr = zptr; zend_reference *ref; + if (OP1_TYPE == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -1085,6 +1089,10 @@ ZEND_VM_C_LABEL(assign_op_object): if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (OP1_TYPE == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -1183,6 +1191,8 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array): value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + GC_ADDREF(ht); + do { if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -1198,6 +1208,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array): if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b32ef2a6cc132..5100d95cfb505 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -23545,6 +23545,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_H zval *orig_zptr = zptr; zend_reference *ref; + if (IS_VAR == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -23571,6 +23575,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_H if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_VAR == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -23623,6 +23631,8 @@ 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); + GC_ADDREF(ht); + do { if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -23638,6 +23648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -26506,6 +26517,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_ zval *orig_zptr = zptr; zend_reference *ref; + if (IS_VAR == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -26532,6 +26547,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_VAR == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -26584,6 +26603,8 @@ 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); + GC_ADDREF(ht); + do { if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -26599,6 +26620,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -29025,6 +29047,8 @@ 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); + GC_ADDREF(ht); + do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -29040,6 +29064,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_ if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -30843,6 +30868,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HAND zval *orig_zptr = zptr; zend_reference *ref; + if (IS_VAR == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -30869,6 +30898,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HAND if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_VAR == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -30921,6 +30954,8 @@ 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); + GC_ADDREF(ht); + do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -30936,6 +30971,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -33487,6 +33523,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONS zval *orig_zptr = zptr; zend_reference *ref; + if (IS_UNUSED == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -33513,6 +33553,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONS if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_UNUSED == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -35633,6 +35677,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPV zval *orig_zptr = zptr; zend_reference *ref; + if (IS_UNUSED == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -35659,6 +35707,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPV if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_UNUSED == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -38260,6 +38312,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_H zval *orig_zptr = zptr; zend_reference *ref; + if (IS_UNUSED == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -38286,6 +38342,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_H if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_UNUSED == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -42377,6 +42437,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HA zval *orig_zptr = zptr; zend_reference *ref; + if (IS_CV == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -42403,6 +42467,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HA if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_CV == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -42455,6 +42523,8 @@ 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); + GC_ADDREF(ht); + do { if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -42470,6 +42540,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -46306,6 +46377,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_H zval *orig_zptr = zptr; zend_reference *ref; + if (IS_CV == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -46332,6 +46407,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_H if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_CV == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -46384,6 +46463,8 @@ 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); + GC_ADDREF(ht); + do { if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -46399,6 +46480,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -49463,6 +49545,8 @@ 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); + GC_ADDREF(ht); + do { if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -49478,6 +49562,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) { @@ -51789,6 +51874,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDL zval *orig_zptr = zptr; zend_reference *ref; + if (IS_CV == IS_CV) { + GC_ADDREF(zobj); + } + do { if (UNEXPECTED(Z_ISREF_P(zptr))) { ref = Z_REF_P(zptr); @@ -51815,6 +51904,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDL if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), zptr); } + + if (IS_CV == IS_CV) { + GC_DTOR(zobj); + } } } else { zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); @@ -51867,6 +51960,8 @@ 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); + GC_ADDREF(ht); + do { if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { zend_reference *ref = Z_REF_P(var_ptr); @@ -51882,6 +51977,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + GC_DTOR_NO_REF(ht); FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); } else { if (EXPECTED(Z_ISREF_P(container))) {