diff options
author | Dmitry Stogov <dmitry@php.net> | 2009-03-18 12:53:17 +0000 |
---|---|---|
committer | Dmitry Stogov <dmitry@php.net> | 2009-03-18 12:53:17 +0000 |
commit | ff5620524c943828426b8ba7eda337d1d9093ddd (patch) | |
tree | 1b0c64cab2a4800d7a011564bb4b95e7529c7a8b | |
parent | 15de25b22864d218b00021702bef8b5489936e04 (diff) | |
download | php-git-ff5620524c943828426b8ba7eda337d1d9093ddd.tar.gz |
Fixed bug #47704 (crashes on some "bad" operations with string offsets)
Removed unnecessary checks
-rw-r--r-- | Zend/tests/bug47704.phpt | 9 | ||||
-rw-r--r-- | Zend/zend_execute.c | 24 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 116 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 1412 |
4 files changed, 622 insertions, 939 deletions
diff --git a/Zend/tests/bug47704.phpt b/Zend/tests/bug47704.phpt new file mode 100644 index 0000000000..151754a4f9 --- /dev/null +++ b/Zend/tests/bug47704.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bug #47704 (crashes on some "bad" operations with string offsets) +--FILE-- +<?php +$s = "abd"; +$s[0]->a += 1; +?> +--EXPECTF-- +Fatal error: Cannot use string offset as an object in %sbug47704.php on line %d diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a752f331a2..f7feff43b0 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -861,17 +861,8 @@ num_index: default: zend_error(E_WARNING, "Illegal offset type"); - switch (type) { - case BP_VAR_R: - case BP_VAR_IS: - case BP_VAR_UNSET: - retval = &EG(uninitialized_zval_ptr); - break; - default: - retval = &EG(error_zval_ptr); - break; - } - break; + return (type == BP_VAR_W || type == BP_VAR_RW) ? + &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr); } return retval; } @@ -1048,12 +1039,7 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont break; case IS_NULL: - if (container == EG(error_zval_ptr)) { - if (result) { - AI_SET_PTR(result->var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - } else if (result) { + if (result) { AI_SET_PTR(result->var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -1119,8 +1105,8 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont zval_ptr_dtor(&overloaded_result); } } else if (result) { - AI_SET_PTR(result->var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); + AI_SET_PTR(result->var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (dim_is_tmp_var) { zval_ptr_dtor(&dim); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6c37ca5e19..9a970b8749 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -303,6 +303,10 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR znode *result = &opline->result; int have_get_ptr = 0; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -343,17 +347,14 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -369,13 +370,10 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -413,33 +411,29 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, binary_op); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W); - - if (object_ptr && OP1_TYPE != IS_CV && !OP1_FREE) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (OP1_TYPE == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (OP1_TYPE == IS_VAR && !OP1_FREE) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, binary_op); } else { zend_op *op_data = opline+1; zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -461,9 +455,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU } FREE_OP2(); FREE_OP1_VAR_PTR(); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -487,8 +478,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU } FREE_OP2(); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -561,6 +551,10 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -654,6 +648,10 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -745,7 +743,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) if (OP1_TYPE == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); @@ -786,7 +784,7 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) if (OP1_TYPE == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); @@ -827,7 +825,7 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) if (OP1_TYPE == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); } @@ -865,7 +863,7 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) if (OP1_TYPE == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); } @@ -1239,17 +1237,6 @@ ZEND_VM_HELPER_EX(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST| zend_free_op free_op2; zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - FREE_OP2(); - FREE_OP1(); - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -1510,16 +1497,12 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) zend_op *opline = EX(opline); zend_op *op_data = opline+1; zend_free_op free_op1; - zval **object_ptr; + zval **object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - } else { - object_ptr = NULL; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -1538,9 +1521,6 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); zval **variable_ptr_ptr; - if (OP1_TYPE == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC); FREE_OP2(); @@ -1581,7 +1561,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) zval *value = GET_OP2_ZVAL_PTR(BP_VAR_R); zval **variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (!variable_ptr_ptr) { + if (OP1_TYPE == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, OP2_TYPE TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -2915,10 +2895,6 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) if (!obj || Z_TYPE_P(obj) != IS_OBJECT) { zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); - FREE_OP1_IF_VAR(); - ZEND_VM_NEXT_OPCODE(); } ce = Z_OBJCE_P(obj); @@ -2930,8 +2906,6 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) } else { zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); } if (ce && clone) { @@ -3394,7 +3368,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV) zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); long index; - if (container) { + if (OP1_TYPE != IS_VAR || container) { if (OP1_TYPE == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -3487,7 +3461,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (container) { + if (OP1_TYPE != IS_VAR || container) { if (OP1_TYPE == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -3893,7 +3867,7 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST| int result = 0; long index; - if (container) { + if (OP1_TYPE != IS_VAR || container) { zend_free_op free_op2; zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2b4f9e7a7b..440a31ab59 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1712,10 +1712,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (!obj || Z_TYPE_P(obj) != IS_OBJECT) { zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); - - ZEND_VM_NEXT_OPCODE(); } ce = Z_OBJCE_P(obj); @@ -1727,8 +1723,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS } else { zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); } if (ce && clone) { @@ -4941,10 +4935,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (!obj || Z_TYPE_P(obj) != IS_OBJECT) { zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); - - ZEND_VM_NEXT_OPCODE(); } ce = Z_OBJCE_P(obj); @@ -4956,8 +4946,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); } if (ce && clone) { @@ -7597,7 +7585,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_VAR == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); @@ -7638,7 +7626,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_VAR == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); @@ -7679,7 +7667,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (IS_VAR == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); } @@ -7717,7 +7705,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if (IS_VAR == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); } @@ -8265,10 +8253,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (!obj || Z_TYPE_P(obj) != IS_OBJECT) { zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - ZEND_VM_NEXT_OPCODE(); } ce = Z_OBJCE_P(obj); @@ -8280,8 +8264,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); } if (ce && clone) { @@ -9279,6 +9261,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b znode *result = &opline->result; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -9319,17 +9305,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -9345,13 +9328,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -9389,33 +9369,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar zend_free_op free_op1, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (object_ptr && IS_VAR != IS_CV && !(free_op1.var != NULL)) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = &opline->op2.u.constant; - zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -9437,9 +9413,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -9462,8 +9435,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -9536,6 +9508,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -9629,6 +9605,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -9895,17 +9875,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST( zval *offset = &opline->op2.u.constant; - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -10144,16 +10113,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zend_op *opline = EX(opline); zend_op *op_data = opline+1; zend_free_op free_op1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zval *property_name = &opline->op2.u.constant; @@ -10172,9 +10137,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zval *dim = &opline->op2.u.constant; zval **variable_ptr_ptr; - if (IS_VAR == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); @@ -10214,7 +10176,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER zval *value = &opline->op2.u.constant; zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_VAR == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CONST TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -10588,7 +10550,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND zval *offset = &opline->op2.u.constant; long index; - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -10681,7 +10643,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); zval *offset = &opline->op2.u.constant; - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -10719,7 +10681,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST( int result = 0; long index; - if (container) { + if (IS_VAR != IS_VAR || container) { zval *offset = &opline->op2.u.constant; @@ -11112,6 +11074,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin znode *result = &opline->result; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -11152,17 +11118,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -11178,13 +11141,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -11222,33 +11182,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (object_ptr && IS_VAR != IS_CV && !(free_op1.var != NULL)) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -11270,9 +11226,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ } zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -11296,8 +11249,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ } zval_dtor(free_op2.var); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -11370,6 +11322,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -11463,6 +11419,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -11729,17 +11689,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(in zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - zval_dtor(free_op2.var); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -11978,16 +11927,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zend_op *opline = EX(opline); zend_op *op_data = opline+1; zend_free_op free_op1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -12006,9 +11951,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; - if (IS_VAR == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 1, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); @@ -12049,7 +11991,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zval *value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_VAR == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_TMP_VAR TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -12368,7 +12310,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); long index; - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -12461,7 +12403,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -12499,7 +12441,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(in int result = 0; long index; - if (container) { + if (IS_VAR != IS_VAR || container) { zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -12892,6 +12834,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin znode *result = &opline->result; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -12932,17 +12878,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -12958,13 +12901,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -13002,33 +12942,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ zend_free_op free_op1, free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (object_ptr && IS_VAR != IS_CV && !(free_op1.var != NULL)) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -13050,9 +12986,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -13076,8 +13009,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -13150,6 +13082,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -13243,6 +13179,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -13509,17 +13449,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(in zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -13758,16 +13687,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zend_op *opline = EX(opline); zend_op *op_data = opline+1; zend_free_op free_op1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -13786,9 +13711,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; - if (IS_VAR == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -13829,7 +13751,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A zval *value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_VAR == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_VAR TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -14199,7 +14121,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); long index; - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -14292,7 +14214,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -14330,7 +14252,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(in int result = 0; long index; - if (container) { + if (IS_VAR != IS_VAR || container) { zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -14479,6 +14401,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* znode *result = &opline->result; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -14519,17 +14445,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -14545,13 +14468,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -14589,33 +14509,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina zend_free_op free_op1, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (object_ptr && IS_VAR != IS_CV && !(free_op1.var != NULL)) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = NULL; - zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -14637,9 +14553,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -14662,8 +14575,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -14823,16 +14735,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zend_op *opline = EX(opline); zend_op *op_data = opline+1; zend_free_op free_op1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zval *property_name = NULL; @@ -14851,9 +14759,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zval *dim = NULL; zval **variable_ptr_ptr; - if (IS_VAR == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); @@ -15334,6 +15239,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina znode *result = &opline->result; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -15374,17 +15283,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -15400,13 +15306,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -15444,33 +15347,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o zend_free_op free_op1, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (object_ptr && IS_VAR != IS_CV && !(free_op1.var != NULL)) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -15492,9 +15391,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -15517,8 +15413,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -15591,6 +15486,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -15684,6 +15583,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -15950,17 +15853,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(int zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -16199,16 +16091,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zend_op *opline = EX(opline); zend_op *op_data = opline+1; zend_free_op free_op1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (IS_VAR == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -16227,9 +16115,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval **variable_ptr_ptr; - if (IS_VAR == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); @@ -16269,7 +16154,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_VAR == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CV TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -16635,7 +16520,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); long index; - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -16728,7 +16613,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (container) { + if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -16766,7 +16651,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int int result = 0; long index; - if (container) { + if (IS_VAR != IS_VAR || container) { zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -16914,10 +16799,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG if (!obj || Z_TYPE_P(obj) != IS_OBJECT) { zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); - - ZEND_VM_NEXT_OPCODE(); } ce = Z_OBJCE_P(obj); @@ -16929,8 +16810,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); } if (ce && clone) { @@ -16996,6 +16875,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int znode *result = &opline->result; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -17036,17 +16919,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -17062,13 +16942,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -17105,33 +16982,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi zend_free_op free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - - if (object_ptr && IS_UNUSED != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = &opline->op2.u.constant; - zval **container = NULL; - if (IS_UNUSED == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -17153,9 +17026,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -17178,8 +17048,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -17252,6 +17121,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -17345,6 +17218,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -17435,17 +17312,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CON zval *offset = &opline->op2.u.constant; - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -17853,7 +17719,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H zval *offset = &opline->op2.u.constant; long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -17945,7 +17811,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *offset = &opline->op2.u.constant; - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -17982,7 +17848,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CON int result = 0; long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { zval *offset = &opline->op2.u.constant; @@ -18129,6 +17995,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* znode *result = &opline->result; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -18169,17 +18039,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -18195,13 +18062,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -18238,33 +18102,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina zend_free_op free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - - if (object_ptr && IS_UNUSED != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zval **container = NULL; - if (IS_UNUSED == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -18286,9 +18146,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina } zval_dtor(free_op2.var); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -18312,8 +18169,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina } zval_dtor(free_op2.var); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -18386,6 +18242,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -18479,6 +18339,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -18569,17 +18433,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - zval_dtor(free_op2.var); - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -18932,7 +18785,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -19024,7 +18877,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -19061,7 +18914,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP int result = 0; long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -19208,6 +19061,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* znode *result = &opline->result; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -19248,17 +19105,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -19274,13 +19128,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -19317,33 +19168,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina zend_free_op free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - - if (object_ptr && IS_UNUSED != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zval **container = NULL; - if (IS_UNUSED == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -19365,9 +19212,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -19391,8 +19235,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -19465,6 +19308,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -19558,6 +19405,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -19648,17 +19499,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -20011,7 +19851,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -20103,7 +19943,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -20140,7 +19980,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR int result = 0; long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -20287,6 +20127,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int znode *result = &opline->result; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -20327,17 +20171,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -20353,13 +20194,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -20396,33 +20234,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b zend_free_op free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - - if (object_ptr && IS_UNUSED != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = NULL; - zval **container = NULL; - if (IS_UNUSED == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -20444,9 +20278,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -20469,8 +20300,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -20559,6 +20389,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b znode *result = &opline->result; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -20599,17 +20433,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -20625,13 +20456,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -20668,33 +20496,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar zend_free_op free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - - if (object_ptr && IS_UNUSED != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_UNUSED == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zval **container = NULL; - if (IS_UNUSED == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -20716,9 +20540,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -20741,8 +20562,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -20815,6 +20635,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -20908,6 +20732,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -20998,17 +20826,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV( zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -21359,7 +21176,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -21451,7 +21268,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (container) { + if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -21488,7 +21305,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV( int result = 0; long index; - if (container) { + if (IS_UNUSED != IS_VAR || container) { zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -21654,7 +21471,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (IS_CV == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); @@ -21694,7 +21511,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (IS_CV == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); PZVAL_LOCK(EG(uninitialized_zval_ptr)); @@ -21734,7 +21551,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_CV == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); } @@ -21771,7 +21588,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if (IS_CV == IS_VAR && !var_ptr) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - if (*var_ptr == EG(error_zval_ptr)) { + if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr); } @@ -22301,10 +22118,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (!obj || Z_TYPE_P(obj) != IS_OBJECT) { zend_error_noreturn(E_ERROR, "__clone method called on non-object"); - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); - - ZEND_VM_NEXT_OPCODE(); } ce = Z_OBJCE_P(obj); @@ -22316,8 +22129,6 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); } - EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); - Z_ADDREF_P(EX_T(opline->result.u.var).var.ptr); } if (ce && clone) { @@ -23168,6 +22979,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi znode *result = &opline->result; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -23208,17 +23023,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -23234,13 +23046,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -23277,33 +23086,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary zend_free_op free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (object_ptr && IS_CV != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_CV == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = &opline->op2.u.constant; - zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (IS_CV == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -23325,9 +23130,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -23350,8 +23152,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -23424,6 +23225,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -23517,6 +23322,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -23782,17 +23591,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(i zval *offset = &opline->op2.u.constant; - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -24028,16 +23826,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (IS_CV == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zval *property_name = &opline->op2.u.constant; @@ -24056,9 +23850,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zval *dim = &opline->op2.u.constant; zval **variable_ptr_ptr; - if (IS_CV == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); @@ -24098,7 +23889,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ zval *value = &opline->op2.u.constant; zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_CV == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CONST TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -24315,7 +24106,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL zval *offset = &opline->op2.u.constant; long index; - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -24407,7 +24198,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC); zval *offset = &opline->op2.u.constant; - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -24444,7 +24235,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(i int result = 0; long index; - if (container) { + if (IS_CV != IS_VAR || container) { zval *offset = &opline->op2.u.constant; @@ -24835,6 +24626,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina znode *result = &opline->result; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -24875,17 +24670,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -24901,13 +24693,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -24944,33 +24733,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o zend_free_op free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - - if (object_ptr && IS_CV != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_CV == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (IS_CV == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -24992,9 +24777,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o } zval_dtor(free_op2.var); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -25018,8 +24800,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o } zval_dtor(free_op2.var); - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -25092,6 +24873,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -25185,6 +24970,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -25450,17 +25239,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(int zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - zval_dtor(free_op2.var); - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -25696,16 +25474,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (IS_CV == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -25724,9 +25498,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; - if (IS_CV == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 1, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); @@ -25767,7 +25538,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_CV == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_TMP_VAR TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -25986,7 +25757,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); long index; - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -26078,7 +25849,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC); zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -26115,7 +25886,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int int result = 0; long index; - if (container) { + if (IS_CV != IS_VAR || container) { zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -26506,6 +26277,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina znode *result = &opline->result; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -26546,17 +26321,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -26572,13 +26344,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -26615,33 +26384,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o zend_free_op free_op2, free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (object_ptr && IS_CV != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_CV == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (IS_CV == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -26663,9 +26428,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -26689,8 +26451,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -26763,6 +26524,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -26856,6 +26621,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -27121,17 +26890,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(int zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -27367,16 +27125,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (IS_CV == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -27395,9 +27149,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; - if (IS_CV == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -27438,7 +27189,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_CV == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_VAR TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -27707,7 +27458,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); long index; - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -27799,7 +27550,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC); zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -27836,7 +27587,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int int result = 0; long index; - if (container) { + if (IS_CV != IS_VAR || container) { zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -27983,6 +27734,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b znode *result = &opline->result; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -28023,17 +27778,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -28049,13 +27801,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -28092,33 +27841,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar zend_free_op free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - - if (object_ptr && IS_CV != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_CV == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = NULL; - zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (IS_CV == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -28140,9 +27885,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -28165,8 +27907,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -28325,16 +28066,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (IS_CV == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zval *property_name = NULL; @@ -28353,9 +28090,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zval *dim = NULL; zval **variable_ptr_ptr; - if (IS_CV == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); @@ -28739,6 +28473,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar znode *result = &opline->result; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -28779,17 +28517,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar if (!have_get_ptr) { zval *z = NULL; - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - if (Z_OBJ_HT_P(object)->read_property) { - z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); - } - break; - case ZEND_ASSIGN_DIM: - if (Z_OBJ_HT_P(object)->read_dimension) { - z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); - } - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + if (Z_OBJ_HT_P(object)->read_property) { + z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC); + } + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + if (Z_OBJ_HT_P(object)->read_dimension) { + z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R TSRMLS_CC); + } } if (z) { if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) { @@ -28805,13 +28540,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar Z_ADDREF_P(z); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); - switch (opline->extended_value) { - case ZEND_ASSIGN_OBJ: - Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - break; - case ZEND_ASSIGN_DIM: - Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); - break; + if (opline->extended_value == ZEND_ASSIGN_OBJ) { + Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); + } else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ { + Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC); } if (!RETURN_VALUE_UNUSED(result)) { EX_T(result->u.var).var.ptr = z; @@ -28848,33 +28580,29 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op zend_free_op free_op_data2, free_op_data1; zval **var_ptr; zval *value; - zend_bool increment_opline = 0; switch (opline->extended_value) { case ZEND_ASSIGN_OBJ: return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - - if (object_ptr && IS_CV != IS_CV && !0) { - Z_ADDREF_PP(object_ptr); /* undo the effect of get_obj_zval_ptr_ptr() */ - } + zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (IS_CV == IS_VAR && !container) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } else if (Z_TYPE_PP(container) == IS_OBJECT) { + if (IS_CV == IS_VAR && !0) { + Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */ + } return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_op *op_data = opline+1; zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC); - if (IS_CV == IS_VAR && !container) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); - increment_opline = 1; + ZEND_VM_INC_OPCODE(); } } break; @@ -28896,9 +28624,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); - } ZEND_VM_NEXT_OPCODE(); } @@ -28921,8 +28646,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op PZVAL_LOCK(*var_ptr); } - if (increment_opline) { - ZEND_VM_INC_OPCODE(); + if (opline->extended_value == ZEND_ASSIGN_DIM) { FREE_OP(free_op_data1); FREE_OP_VAR_PTR(free_op_data2); } @@ -28995,6 +28719,10 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -29088,6 +28816,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -29353,17 +29085,6 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(int zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (container == EG(error_zval_ptr)) { - if (!RETURN_VALUE_UNUSED(&opline->result)) { - AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); - PZVAL_LOCK(EG(error_zval_ptr)); - } - - - ZEND_VM_NEXT_OPCODE(); - } - - if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) { if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -29599,16 +29320,12 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zval **object_ptr; + zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (IS_CV == IS_CV || EX_T(opline->op1.u.var).var.ptr_ptr) { - /* not an array offset */ - object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - object_ptr = NULL; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - - if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { + if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -29627,9 +29344,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval **variable_ptr_ptr; - if (IS_CV == IS_VAR && !object_ptr) { - zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); - } zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); @@ -29669,7 +29383,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); - if (!variable_ptr_ptr) { + if (IS_CV == IS_VAR && !variable_ptr_ptr) { if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CV TSRMLS_CC)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; @@ -29934,7 +29648,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); long index; - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -30026,7 +29740,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC); zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (container) { + if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -30063,7 +29777,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int int result = 0; long index; - if (container) { + if (IS_CV != IS_VAR || container) { zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); |