mirror of
https://github.com/php/php-src.git
synced 2024-11-28 04:14:26 +08:00
Removed IS_STR_OFFSET type and corresponding macros. Optimized string offset handling in ASSIGN_DIM opcode.
This commit is contained in:
parent
be835b2d70
commit
e85545eca5
@ -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);
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 (!IS_INTERNED(Z_STR_P(container))) zend_string_addref(Z_STR_P(container));
|
||||
ZVAL_STR_OFFSET(result, container, offset);
|
||||
|
||||
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)
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
@ -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 ((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);
|
||||
}
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user