From: Dmitry Stogov Date: Mon, 8 Sep 2014 11:46:45 +0000 (+0400) Subject: Removed IS_STR_OFFSET type and corresponding macros. Optimized string offset handling... X-Git-Tag: PRE_PHP7_REMOVALS~100 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e85545eca502b5eb74a88280e48e137a39839f61;p=php Removed IS_STR_OFFSET type and corresponding macros. Optimized string offset handling in ASSIGN_DIM opcode. --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 586eddec59..17f0eef456 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -755,42 +755,8 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p FREE_OP_IF_VAR(free_value); } -static zend_always_inline zend_long zend_fetch_dimension_str_offset(zval *dim, int type TSRMLS_DC) +static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC) { - zend_long offset; - - if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { - switch(Z_TYPE_P(dim)) { - case IS_STRING: - if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) { - break; - } - if (type != BP_VAR_UNSET) { - zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim)); - } - break; - case IS_DOUBLE: - case IS_NULL: - case IS_FALSE: - case IS_TRUE: - zend_error(E_NOTICE, "String offset cast occurred"); - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - break; - } - - offset = zval_get_long(dim); - } else { - offset = Z_LVAL_P(dim); - } - - return offset; -} - -static void zend_assign_to_string_offset(zval *str_offset, zend_long offset, zval *value, int value_type, zval *result TSRMLS_DC) -{ - zval *str = Z_STR_OFFSET_STR_P(str_offset); zend_string *old_str; if (offset < 0) { @@ -1135,7 +1101,7 @@ str_index: return retval; } -static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref TSRMLS_DC) +static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC) { zval *retval; zval *container = container_ptr; @@ -1175,17 +1141,40 @@ convert_to_array: zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); } - if (type != BP_VAR_UNSET) { - SEPARATE_STRING(container); - } - - /* This is a dummy, the offset is broken if we're here. - What matters is merely the IS_STR_OFFSET type set below.*/ - offset = zend_fetch_dimension_str_offset(dim, type TSRMLS_CC); + if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { + switch(Z_TYPE_P(dim)) { + case IS_STRING: + if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) { + break; + } + if (type != BP_VAR_UNSET) { + zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim)); + } + break; + case IS_DOUBLE: + case IS_NULL: + case IS_FALSE: + case IS_TRUE: + zend_error(E_NOTICE, "String offset cast occurred"); + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + break; + } - if (!IS_INTERNED(Z_STR_P(container))) zend_string_addref(Z_STR_P(container)); - ZVAL_STR_OFFSET(result, container, offset); + offset = zval_get_long(dim); + } else { + offset = Z_LVAL_P(dim); + } + if (allow_str_offset) { + SEPARATE_STRING(container); + if (!IS_INTERNED(Z_STR_P(container))) zend_string_addref(Z_STR_P(container)); + ZVAL_LONG(result, offset); + return container; /* assignment to string offset */ + } else { + ZVAL_INDIRECT(result, NULL); /* wrong string offset */ + } } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (!Z_OBJ_HT_P(container)->read_dimension) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); @@ -1250,26 +1239,32 @@ convert_to_array: ZVAL_INDIRECT(result, &EG(error_zval)); } } + return NULL; /* not an assignment to string offset */ } static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC); +} + +static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) +{ + return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC); } static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC) diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 389d3e5cd2..f8d80c95a4 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -239,7 +239,6 @@ struct _zend_ast_ref { /* internal types */ #define IS_INDIRECT 15 -#define IS_STR_OFFSET 16 #define IS_PTR 17 static inline zend_uchar zval_get_type(const zval* pz) { @@ -651,15 +650,6 @@ static inline zend_uchar zval_get_type(const zval* pz) { Z_TYPE_INFO_P(z) = IS_PTR; \ } while (0) - -#define Z_STR_OFFSET_STR(zval) Z_INDIRECT(zval) -#define Z_STR_OFFSET_STR_P(zval_p) Z_STR_OFFSET_STR(*(zval_p)) - -#define ZVAL_STR_OFFSET(z, s, i) do { \ - Z_STR_OFFSET_STR_P(z) = (s); \ - Z_TYPE_INFO_P(z) = IS_STR_OFFSET; \ - } while (0) - #endif /* ZEND_TYPES_H */ /* diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d37ab7cb7a..4bd80bd9d6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -335,7 +335,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval *value; int have_get_ptr = 0; - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -430,7 +430,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (OP1_TYPE == IS_VAR && !OP1_FREE) { @@ -445,7 +445,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -497,7 +497,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU value = GET_OP2_ZVAL_PTR(BP_VAR_R); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -692,7 +692,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| property = GET_OP2_ZVAL_PTR(BP_VAR_R); retval = EX_VAR(opline->result.var); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -784,7 +784,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR property = GET_OP2_ZVAL_PTR(BP_VAR_R); retval = EX_VAR(opline->result.var); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -867,6 +867,10 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) SAVE_OPLINE(); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); + if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_increment_function(var_ptr); if (RETURN_VALUE_USED(opline)) { @@ -875,9 +879,6 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -922,6 +923,10 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) SAVE_OPLINE(); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); + if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_decrement_function(var_ptr); if (RETURN_VALUE_USED(opline)) { @@ -930,9 +935,6 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -977,15 +979,16 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) SAVE_OPLINE(); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); + if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); fast_increment_function(var_ptr); ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); FREE_OP1_VAR_PTR(); @@ -1031,15 +1034,16 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) SAVE_OPLINE(); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); + if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); fast_decrement_function(var_ptr); ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); FREE_OP1_VAR_PTR(); @@ -1279,7 +1283,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV) SAVE_OPLINE(); container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -1305,7 +1309,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV) SAVE_OPLINE(); container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); @@ -1377,7 +1381,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) SAVE_OPLINE(); container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC); @@ -1439,7 +1443,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV) property = GET_OP2_ZVAL_PTR(BP_VAR_R); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -1464,7 +1468,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) property = GET_OP2_ZVAL_PTR(BP_VAR_R); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -1526,7 +1530,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP| if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -1552,7 +1556,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV) container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); property = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -1598,7 +1602,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W); property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -1619,7 +1623,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) SAVE_OPLINE(); object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -1635,57 +1639,38 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; + zval *variable_ptr; - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, OP2_TYPE TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, OP2_TYPE TSRMLS_CC); FREE_OP2(); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } FREE_OP1_VAR_PTR(); /* assign_dim has two opcodes! */ @@ -1768,8 +1753,8 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((OP2_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) || - (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) { + if ((OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) || + (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); } if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || @@ -2898,7 +2883,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } @@ -3134,7 +3119,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY) SAVE_OPLINE(); varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); } @@ -3933,7 +3918,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -4357,6 +4342,9 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV) SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (OP1_TYPE != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -4435,7 +4423,6 @@ ZEND_VM_C_LABEL(numeric_index_dim): FREE_OP2(); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -4456,7 +4443,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET); - if (OP1_TYPE == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -5667,7 +5654,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE } else { zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8076183ab0..0720356e94 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2653,7 +2653,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND retval_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } @@ -4042,7 +4042,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -4359,7 +4359,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -4838,7 +4838,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE } else { zval *value_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -5372,7 +5372,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -5572,7 +5572,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -5868,7 +5868,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ } else { zval *value_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -6555,7 +6555,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -6755,7 +6755,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -7203,7 +7203,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } else { zval *value_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -7622,7 +7622,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -7948,7 +7948,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL } else { zval *value_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -8465,7 +8465,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -8716,7 +8716,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -9010,7 +9010,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A } else { zval *value_ptr = NULL; - if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -9403,7 +9403,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE retval_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } @@ -10814,7 +10814,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -10985,7 +10985,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -11431,7 +11431,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ } else { zval *value_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -11965,7 +11965,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -12122,7 +12122,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -12418,7 +12418,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR } else { zval *value_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -13105,7 +13105,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -13262,7 +13262,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -13710,7 +13710,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR } else { zval *value_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -14013,7 +14013,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -14314,7 +14314,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER } else { zval *value_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -14831,7 +14831,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -14985,7 +14985,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -15279,7 +15279,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zval *value_ptr = NULL; - if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -15419,6 +15419,10 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_increment_function(var_ptr); if (RETURN_VALUE_USED(opline)) { @@ -15427,9 +15431,6 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -15474,6 +15475,10 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_decrement_function(var_ptr); if (RETURN_VALUE_USED(opline)) { @@ -15482,9 +15487,6 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -15529,15 +15531,16 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); fast_increment_function(var_ptr); ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; @@ -15583,15 +15586,16 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); fast_decrement_function(var_ptr); ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; @@ -15890,7 +15894,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } @@ -16020,7 +16024,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); } @@ -17314,7 +17318,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zval *value; int have_get_ptr = 0; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -17408,7 +17412,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { @@ -17423,7 +17427,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -17475,7 +17479,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar value = opline->op2.zv; var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -17670,7 +17674,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t property = opline->op2.zv; retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -17761,7 +17765,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ property = opline->op2.zv; retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -18013,7 +18017,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -18039,7 +18043,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); @@ -18111,7 +18115,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); @@ -18172,7 +18176,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA property = opline->op2.zv; container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -18197,7 +18201,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H property = opline->op2.zv; container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -18258,7 +18262,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -18284,7 +18288,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -18308,7 +18312,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property_name = opline->op2.zv; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -18329,7 +18333,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -18345,56 +18349,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = opline->op2.zv; - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } + zval *variable_ptr; - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -18750,7 +18736,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -18941,6 +18927,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -19019,7 +19008,6 @@ numeric_index_dim: break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -19040,7 +19028,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = opline->op2.zv; @@ -19324,7 +19312,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -19719,7 +19707,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin zval *value; int have_get_ptr = 0; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -19814,7 +19802,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { @@ -19829,7 +19817,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -19881,7 +19869,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -20076,7 +20064,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -20168,7 +20156,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -20268,7 +20256,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -20294,7 +20282,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); @@ -20366,7 +20354,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); @@ -20428,7 +20416,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -20453,7 +20441,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -20515,7 +20503,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -20541,7 +20529,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -20565,7 +20553,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -20586,7 +20574,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -20602,57 +20590,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); + zval *variable_ptr; - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); zval_dtor(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -20913,7 +20882,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -21032,6 +21001,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -21110,7 +21082,6 @@ numeric_index_dim: zval_dtor(free_op2.var); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -21131,7 +21102,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); @@ -21337,7 +21308,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -21732,7 +21703,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin zval *value; int have_get_ptr = 0; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -21827,7 +21798,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { @@ -21842,7 +21813,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -21894,7 +21865,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -22089,7 +22060,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -22181,7 +22152,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -22434,7 +22405,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -22460,7 +22431,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); @@ -22532,7 +22503,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); @@ -22594,7 +22565,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -22619,7 +22590,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -22681,7 +22652,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -22707,7 +22678,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -22731,7 +22702,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -22752,7 +22723,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -22768,57 +22739,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); + zval *variable_ptr; - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -22901,8 +22853,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) || - (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) { + if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) || + (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || @@ -23143,7 +23095,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -23334,6 +23286,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -23412,7 +23367,6 @@ numeric_index_dim: zval_ptr_dtor_nogc(free_op2.var); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -23433,7 +23387,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); @@ -23719,7 +23673,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -23839,7 +23793,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* zval *value; int have_get_ptr = 0; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -23933,7 +23887,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { @@ -23948,7 +23902,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (* var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -24000,7 +23954,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina value = NULL; var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -24343,7 +24297,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -24369,7 +24323,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); @@ -24426,7 +24380,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -24442,56 +24396,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = NULL; - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; + zval *variable_ptr; - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -24626,7 +24562,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -24945,7 +24881,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -25325,7 +25261,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zval *value; int have_get_ptr = 0; - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -25419,7 +25355,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) { @@ -25434,7 +25370,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -25486,7 +25422,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -25681,7 +25617,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -25772,7 +25708,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -25871,7 +25807,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -25897,7 +25833,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); @@ -25969,7 +25905,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); @@ -26030,7 +25966,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -26055,7 +25991,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -26116,7 +26052,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -26142,7 +26078,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -26166,7 +26102,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -26187,7 +26123,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -26203,56 +26139,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); + zval *variable_ptr; - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}; /* assign_dim has two opcodes! */ @@ -26334,8 +26252,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) || - (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) { + if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) || + (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); } if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || @@ -26573,7 +26491,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -26692,6 +26610,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_VAR != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -26770,7 +26691,6 @@ numeric_index_dim: break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -26791,7 +26711,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); @@ -26995,7 +26915,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -27195,7 +27115,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zval *value; int have_get_ptr = 0; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -27288,7 +27208,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { @@ -27303,7 +27223,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -27355,7 +27275,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi value = opline->op2.zv; var_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -27550,7 +27470,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde property = opline->op2.zv; retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -27641,7 +27561,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd property = opline->op2.zv; retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -27762,7 +27682,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE property = opline->op2.zv; container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -27787,7 +27707,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD property = opline->op2.zv; container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -27848,7 +27768,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -27874,7 +27794,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP container = _get_obj_zval_ptr_unused(TSRMLS_C); property = opline->op2.zv; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -27898,7 +27818,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ object = _get_obj_zval_ptr_unused(TSRMLS_C); property_name = opline->op2.zv; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -28156,6 +28076,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_UNUSED != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -28234,7 +28157,6 @@ numeric_index_dim: break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -28255,7 +28177,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = opline->op2.zv; @@ -28459,7 +28381,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL } else { zval *value_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -28563,7 +28485,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* zval *value; int have_get_ptr = 0; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -28657,7 +28579,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { @@ -28672,7 +28594,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (* var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -28724,7 +28646,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -28919,7 +28841,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -29011,7 +28933,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -29134,7 +29056,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -29159,7 +29081,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -29221,7 +29143,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -29247,7 +29169,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO container = _get_obj_zval_ptr_unused(TSRMLS_C); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -29271,7 +29193,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA object = _get_obj_zval_ptr_unused(TSRMLS_C); property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -29439,6 +29361,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_UNUSED != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -29517,7 +29442,6 @@ numeric_index_dim: zval_dtor(free_op2.var); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -29538,7 +29462,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); @@ -29744,7 +29668,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER } else { zval *value_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -29848,7 +29772,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* zval *value; int have_get_ptr = 0; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -29942,7 +29866,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { @@ -29957,7 +29881,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (* var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -30009,7 +29933,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -30204,7 +30128,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -30296,7 +30220,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -30419,7 +30343,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -30444,7 +30368,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -30506,7 +30430,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -30532,7 +30456,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO container = _get_obj_zval_ptr_unused(TSRMLS_C); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -30556,7 +30480,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA object = _get_obj_zval_ptr_unused(TSRMLS_C); property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -30724,6 +30648,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_UNUSED != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -30802,7 +30729,6 @@ numeric_index_dim: zval_ptr_dtor_nogc(free_op2.var); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -30823,7 +30749,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); @@ -31029,7 +30955,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER } else { zval *value_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -31133,7 +31059,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zval *value; int have_get_ptr = 0; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -31226,7 +31152,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { @@ -31241,7 +31167,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -31293,7 +31219,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b value = NULL; var_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -31545,7 +31471,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND } else { zval *value_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -31649,7 +31575,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b zval *value; int have_get_ptr = 0; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -31742,7 +31668,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_UNUSED == IS_VAR && !0) { @@ -31757,7 +31683,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -31809,7 +31735,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -32004,7 +31930,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -32095,7 +32021,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -32216,7 +32142,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -32241,7 +32167,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -32302,7 +32228,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -32328,7 +32254,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD container = _get_obj_zval_ptr_unused(TSRMLS_C); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -32352,7 +32278,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN object = _get_obj_zval_ptr_unused(TSRMLS_C); property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -32518,6 +32444,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_UNUSED != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -32596,7 +32525,6 @@ numeric_index_dim: break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -32617,7 +32545,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - if (IS_UNUSED == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); @@ -32821,7 +32749,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ } else { zval *value_ptr = NULL; - if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -32951,6 +32879,10 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_increment_function(var_ptr); if (RETURN_VALUE_USED(opline)) { @@ -32959,9 +32891,6 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -33005,6 +32934,10 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_decrement_function(var_ptr); if (RETURN_VALUE_USED(opline)) { @@ -33013,9 +32946,6 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { if (RETURN_VALUE_USED(opline)) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -33059,15 +32989,16 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); fast_increment_function(var_ptr); ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -33112,15 +33043,16 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); fast_decrement_function(var_ptr); ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { - zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -33403,7 +33335,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER retval_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); } @@ -33532,7 +33464,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(varptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); } @@ -34660,7 +34592,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zval *value; int have_get_ptr = 0; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -34753,7 +34685,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { @@ -34768,7 +34700,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -34820,7 +34752,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary value = opline->op2.zv; var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -35015,7 +34947,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t property = opline->op2.zv; retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -35106,7 +35038,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t property = opline->op2.zv; retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -35358,7 +35290,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -35384,7 +35316,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); @@ -35456,7 +35388,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); @@ -35517,7 +35449,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN property = opline->op2.zv; container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -35542,7 +35474,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA property = opline->op2.zv; container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -35603,7 +35535,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -35629,7 +35561,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -35653,7 +35585,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); property_name = opline->op2.zv; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -35674,7 +35606,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -35690,56 +35622,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = opline->op2.zv; - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } + zval *variable_ptr; - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -35881,7 +35795,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO if ((IS_CV == IS_VAR || IS_CV == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -36072,6 +35986,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_CV != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -36150,7 +36067,6 @@ numeric_index_dim: break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -36171,7 +36087,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = opline->op2.zv; @@ -36455,7 +36371,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -36879,7 +36795,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina zval *value; int have_get_ptr = 0; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -36973,7 +36889,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { @@ -36988,7 +36904,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -37040,7 +36956,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -37235,7 +37151,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -37327,7 +37243,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -37427,7 +37343,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -37453,7 +37369,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); @@ -37525,7 +37441,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); @@ -37587,7 +37503,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -37612,7 +37528,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -37674,7 +37590,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -37700,7 +37616,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -37724,7 +37640,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -37745,7 +37661,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -37761,57 +37677,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); + zval *variable_ptr; - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC); zval_dtor(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -37955,7 +37852,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE if ((IS_CV == IS_VAR || IS_CV == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -38074,6 +37971,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_CV != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -38152,7 +38052,6 @@ numeric_index_dim: zval_dtor(free_op2.var); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -38173,7 +38072,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); @@ -38379,7 +38278,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -38773,7 +38672,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina zval *value; int have_get_ptr = 0; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -38867,7 +38766,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { @@ -38882,7 +38781,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -38934,7 +38833,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -39129,7 +39028,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -39221,7 +39120,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -39474,7 +39373,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -39500,7 +39399,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); @@ -39572,7 +39471,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); @@ -39634,7 +39533,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -39659,7 +39558,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -39721,7 +39620,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -39747,7 +39646,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -39771,7 +39670,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -39792,7 +39691,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -39808,57 +39707,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); + zval *variable_ptr; - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC); zval_ptr_dtor_nogc(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -39941,8 +39821,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) || - (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) { + if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) || + (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || @@ -40065,7 +39945,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE if ((IS_CV == IS_VAR || IS_CV == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -40256,6 +40136,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_CV != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -40334,7 +40217,6 @@ numeric_index_dim: zval_ptr_dtor_nogc(free_op2.var); break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -40355,7 +40237,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); @@ -40641,7 +40523,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -40760,7 +40642,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b zval *value; int have_get_ptr = 0; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -40853,7 +40735,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { @@ -40868,7 +40750,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -40920,7 +40802,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar value = NULL; var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -41263,7 +41145,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -41289,7 +41171,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); @@ -41346,7 +41228,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -41362,56 +41244,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = NULL; - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; + zval *variable_ptr; - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); - - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -41430,7 +41294,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC if ((IS_CV == IS_VAR || IS_CV == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -41731,7 +41595,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); } @@ -42110,7 +41974,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zval *value; int have_get_ptr = 0; - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -42203,7 +42067,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (IS_CV == IS_VAR && !0) { @@ -42218,7 +42082,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } - if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -42270,7 +42134,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); } @@ -42465,7 +42329,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -42556,7 +42420,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = EX_VAR(opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } @@ -42655,7 +42519,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (EXPECTED(opline->extended_value == 0)) { @@ -42681,7 +42545,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); @@ -42753,7 +42617,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); @@ -42814,7 +42678,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -42839,7 +42703,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW, 0 TSRMLS_CC); @@ -42900,7 +42764,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); } - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W, 0 TSRMLS_CC); @@ -42926,7 +42790,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET, 0 TSRMLS_CC); @@ -42950,7 +42814,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER object = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC); @@ -42971,7 +42835,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); object_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) { @@ -42987,56 +42851,38 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); - zval *variable_ptr = EX_VAR((opline+1)->op2.var); - zend_long offset = 0; - - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) || (UNEXPECTED(Z_ISREF_P(object_ptr)) && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_STRING)) { - ZVAL_DEREF(object_ptr); - - if (UNEXPECTED(Z_STRLEN_P(object_ptr) == 0)) { - goto string_failed; - } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - SEPARATE_STRING(object_ptr); + zval *variable_ptr; - offset = zend_fetch_dimension_str_offset(dim, BP_VAR_W TSRMLS_CC); - - if (!IS_INTERNED(Z_STR_P(object_ptr))) zend_string_addref(Z_STR_P(object_ptr)); - ZVAL_STR_OFFSET(variable_ptr, object_ptr, offset); - } else { -string_failed: - zend_fetch_dimension_address_W(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); - } + variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); - if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_assign_to_string_offset(variable_ptr, offset, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); - } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - if (IS_TMP_FREE(free_op_data1)) { - zval_dtor(value); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } - FREE_OP_VAR_PTR(free_op_data2); + if (UNEXPECTED(variable_ptr != NULL)) { + zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else { - if ((opline+1)->op1_type == IS_TMP_VAR) { - value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); - } else if ((opline+1)->op1_type == IS_CONST) { - value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); + if (UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_TMP_FREE(free_op_data1)) { + zval_dtor(value); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_VAR_PTR(free_op_data2); } else { - value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); - } - if (RETURN_VALUE_USED(opline)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if ((opline+1)->op1_type == IS_TMP_VAR) { + value = zend_assign_tmp_to_variable(variable_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr, value TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr, value TSRMLS_CC); + } + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_VAR_PTR(free_op_data2); } - FREE_OP_IF_VAR(free_op_data1); + FREE_OP_IF_VAR(free_op_data1); } /* assign_dim has two opcodes! */ @@ -43118,8 +42964,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER UNEXPECTED(!Z_ISREF_P(variable_ptr))) { zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - if ((IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) || - (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET))) { + if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) || + (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); } if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || @@ -43239,7 +43085,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); } ZVAL_MAKE_REF(expr_ptr); @@ -43358,6 +43204,9 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + } if (IS_CV != IS_UNUSED) { ZVAL_DEREF(container); SEPARATE_ZVAL_NOREF(container); @@ -43436,7 +43285,6 @@ numeric_index_dim: break; case IS_STRING: - case IS_STR_OFFSET: zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); ZEND_VM_CONTINUE(); /* bailed out before */ default: @@ -43457,7 +43305,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && Z_TYPE_P(container) == IS_STR_OFFSET) { + if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); } offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); @@ -43661,7 +43509,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS } else { zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); - if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(value_ptr) == IS_STR_OFFSET)) { + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); }