From: Dmitry Stogov Date: Fri, 14 Dec 2007 14:14:50 +0000 (+0000) Subject: executor optimization X-Git-Tag: RELEASE_1_3_1~507 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f817a1ce6a18a7751f69d7d52781b54a399080e5;p=php executor optimization --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 508cc974c5..5d41457623 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -102,6 +102,10 @@ static inline void zend_pzval_unlock_free_func(zval *z) (ai).ptr = NULL; \ } +#define AI_SET_PTR(ai, val) \ + (ai).ptr = (val); \ + (ai).ptr_ptr = &((ai).ptr); + #define FREE_OP(should_free) \ if (should_free.var) { \ if ((zend_uintptr_t)should_free.var & 1L) { \ @@ -198,9 +202,7 @@ static inline zval *_get_zval_ptr_var(znode *node, temp_variable *Ts, zend_free_ ptr->value.str.val = STR_EMPTY_ALLOC(); ptr->value.str.len = 0; } else { - char c = str->value.str.val[T->str_offset.offset]; - - ptr->value.str.val = estrndup(&c, 1); + ptr->value.str.val = estrndup(str->value.str.val + T->str_offset.offset, 1); ptr->value.str.len = 1; } PZVAL_UNLOCK_FREE(str); @@ -367,27 +369,22 @@ static inline zval *_get_obj_zval_ptr(znode *op, temp_variable *Ts, zend_free_op return get_zval_ptr(op, Ts, should_free, type); } -static inline void zend_switch_free(zend_op *opline, temp_variable *Ts TSRMLS_DC) +static inline void zend_switch_free(temp_variable *T, int type, int extended_value TSRMLS_DC) { - switch (opline->op1.op_type) { - case IS_VAR: - if (!T(opline->op1.u.var).var.ptr_ptr) { - temp_variable *T = &T(opline->op1.u.var); - /* perform the equivalent of equivalent of a - * quick & silent get_zval_ptr, and FREE_OP - */ - PZVAL_UNLOCK_FREE(T->str_offset.str); - } else if (T(opline->op1.u.var).var.ptr) { - zval_ptr_dtor(&T(opline->op1.u.var).var.ptr); - if (opline->extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */ - zval_ptr_dtor(&T(opline->op1.u.var).var.ptr); - } + if (type == IS_VAR) { + if (T->var.ptr) { + if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */ + Z_DELREF_P(T->var.ptr); } - break; - case IS_TMP_VAR: - zendi_zval_dtor(T(opline->op1.u.var).tmp_var); - break; - EMPTY_SWITCH_DEFAULT_CASE() + zval_ptr_dtor(&T->var.ptr); + } else if (!T->var.ptr_ptr) { + /* perform the equivalent of equivalent of a + * quick & silent get_zval_ptr, and FREE_OP + */ + PZVAL_UNLOCK_FREE(T->str_offset.str); + } + } else { /* IS_TMP_VAR */ + zendi_zval_dtor(T->tmp_var); } } @@ -532,11 +529,10 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva } -static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode *op2, znode *value_op, temp_variable *Ts, int opcode TSRMLS_DC) +static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval *property_name, znode *value_op, temp_variable *Ts, int opcode TSRMLS_DC) { zval *object; - zend_free_op free_op2, free_value; - zval *property_name = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R); + zend_free_op free_value; zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R); zval **retval = &T(result->u.var).var.ptr; @@ -544,31 +540,35 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - if (*object_ptr == EG(error_zval_ptr)) { - FREE_OP(free_op2); - if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + if (Z_TYPE_P(*object_ptr) != IS_OBJECT) { + if (*object_ptr == EG(error_zval_ptr)) { + if (!RETURN_VALUE_UNUSED(result)) { + *retval = EG(uninitialized_zval_ptr); + PZVAL_LOCK(*retval); + } + FREE_OP(free_value); + return; } - FREE_OP(free_value); - return; - } - - make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ - object = *object_ptr; - - if (Z_TYPE_P(object) != IS_OBJECT || (opcode == ZEND_ASSIGN_OBJ && !Z_OBJ_HT_P(object)->write_property)) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - FREE_OP(free_op2); - if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + if (Z_TYPE_PP(object_ptr) == IS_NULL || + (Z_TYPE_PP(object_ptr) == IS_BOOL && Z_LVAL_PP(object_ptr) == 0) || + (Z_TYPE_PP(object_ptr) == IS_STRING && Z_STRLEN_PP(object_ptr) == 0)) { + zend_error(E_STRICT, "Creating default object from empty value"); + SEPARATE_ZVAL_IF_NOT_REF(object_ptr); + zval_dtor(*object_ptr); + object_init(*object_ptr); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (!RETURN_VALUE_UNUSED(result)) { + *retval = EG(uninitialized_zval_ptr); + PZVAL_LOCK(*retval); + } + FREE_OP(free_value); + return; } - FREE_OP(free_value); - return; } /* here we are sure we are dealing with an object */ + object = *object_ptr; /* separate our value if necessary */ if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { @@ -610,8 +610,14 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode Z_ADDREF_P(value); if (opcode == ZEND_ASSIGN_OBJ) { - if (IS_TMP_FREE(free_op2)) { - MAKE_REAL_ZVAL_PTR(property_name); + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (!RETURN_VALUE_UNUSED(result)) { + *retval = EG(uninitialized_zval_ptr); + PZVAL_LOCK(*retval); + } + FREE_OP(free_value); + return; } Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC); } else { @@ -619,118 +625,83 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode if (!Z_OBJ_HT_P(object)->write_dimension) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); } - if (IS_TMP_FREE(free_op2)) { - MAKE_REAL_ZVAL_PTR(property_name); - } Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC); } - if (result && !RETURN_VALUE_UNUSED(result) && !EG(exception)) { - T(result->u.var).var.ptr = value; - T(result->u.var).var.ptr_ptr = &T(result->u.var).var.ptr; /* this is so that we could use it in FETCH_DIM_R, etc. - see bug #27876 */ + if (!RETURN_VALUE_UNUSED(result) && !EG(exception)) { + AI_SET_PTR(T(result->u.var).var, value); PZVAL_LOCK(value); } - if (IS_TMP_FREE(free_op2)) { - zval_ptr_dtor(&property_name); - } else { - FREE_OP(free_op2); - } zval_ptr_dtor(&value); FREE_OP_IF_VAR(free_value); } - -static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2, zval *value, int type, temp_variable *Ts TSRMLS_DC) +static inline void zend_assign_to_string_offset(temp_variable *T, zval *value, int value_type TSRMLS_DC) { - zend_free_op free_op1; - zval **variable_ptr_ptr = get_zval_ptr_ptr(op1, Ts, &free_op1, BP_VAR_W); - zval *variable_ptr; - - if (!variable_ptr_ptr) { - temp_variable *T = &T(op1->u.var); + if (Z_TYPE_P(T->str_offset.str) == IS_STRING) { + zval tmp; + zval *final_value = value; - if (Z_TYPE_P(T->str_offset.str) == IS_STRING) - do { - zval tmp; - zval *final_value = value; + if (((int)T->str_offset.offset < 0)) { + zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset); + return; + } + if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) { + zend_uint i; - if (((int)T->str_offset.offset < 0)) { - zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset); - break; + if (Z_STRLEN_P(T->str_offset.str)==0) { + STR_FREE(Z_STRVAL_P(T->str_offset.str)); + Z_STRVAL_P(T->str_offset.str) = (char *) emalloc(T->str_offset.offset+1+1); + } else { + Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1); } - if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) { - zend_uint i; - - if (Z_STRLEN_P(T->str_offset.str)==0) { - STR_FREE(Z_STRVAL_P(T->str_offset.str)); - Z_STRVAL_P(T->str_offset.str) = (char *) emalloc(T->str_offset.offset+1+1); - } else { - Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1); - } - for (i=Z_STRLEN_P(T->str_offset.str); istr_offset.offset; i++) { - Z_STRVAL_P(T->str_offset.str)[i] = ' '; - } - Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0; - Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1; + for (i=Z_STRLEN_P(T->str_offset.str); istr_offset.offset; i++) { + Z_STRVAL_P(T->str_offset.str)[i] = ' '; } + Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0; + Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1; + } - if (Z_TYPE_P(value)!=IS_STRING) { - tmp = *value; - if (op2->op_type & (IS_VAR|IS_CV)) { - zval_copy_ctor(&tmp); - } - convert_to_string(&tmp); - final_value = &tmp; + if (Z_TYPE_P(value)!=IS_STRING) { + tmp = *value; + if (value_type & (IS_VAR|IS_CV)) { + zval_copy_ctor(&tmp); } + convert_to_string(&tmp); + final_value = &tmp; + } - Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(final_value)[0]; + Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(final_value)[0]; - if (op2->op_type == IS_TMP_VAR) { - if (final_value == &T(op2->u.var).tmp_var) { - /* we can safely free final_value here - * because separation is done only - * in case op2->op_type == IS_VAR */ - STR_FREE(Z_STRVAL_P(final_value)); - } - } - if (final_value == &tmp) { - zval_dtor(final_value); - } - /* - * the value of an assignment to a string offset is undefined - T(result->u.var).var = &T->str_offset.str; - */ - } while (0); - /* zval_ptr_dtor(&T->str_offset.str); Nuke this line if it doesn't cause a leak */ - -/* T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); */ - if (!RETURN_VALUE_UNUSED(result)) { - T(result->u.var).var.ptr_ptr = &value; - PZVAL_LOCK(*T(result->u.var).var.ptr_ptr); - AI_USE_PTR(T(result->u.var).var); + if (final_value == &tmp) { + zval_dtor(final_value); + } else if (value_type == IS_TMP_VAR) { + /* we can safely free final_value here + * because separation is done only + * in case value_type == IS_VAR */ + STR_FREE(Z_STRVAL_P(final_value)); } - FREE_OP_VAR_PTR(free_op1); - return; + /* + * the value of an assignment to a string offset is undefined + T(result->u.var).var = &T->str_offset.str; + */ } +} - variable_ptr = *variable_ptr_ptr; +static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC) +{ + zval *variable_ptr = *variable_ptr_ptr; if (variable_ptr == EG(error_zval_ptr)) { - if (result && !RETURN_VALUE_UNUSED(result)) { - T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*T(result->u.var).var.ptr_ptr); - AI_USE_PTR(T(result->u.var).var); - } - if (type==IS_TMP_VAR) { + if (is_tmp_var) { zval_dtor(value); } - FREE_OP_VAR_PTR(free_op1); - return; + return EG(uninitialized_zval_ptr); } if (Z_TYPE_P(variable_ptr) == IS_OBJECT && Z_OBJ_HANDLER_P(variable_ptr, set)) { Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC); - goto done_setting_var; + return value; } if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { @@ -747,7 +718,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 zend_uint refcount = Z_REFCOUNT_P(variable_ptr); zval garbage; - if (type != IS_TMP_VAR) { + if (!is_tmp_var) { Z_ADDREF_P(value); } garbage = *variable_ptr; @@ -756,7 +727,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 Z_SET_ISREF_P(variable_ptr); zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); - if (type != IS_TMP_VAR) { + if (!is_tmp_var) { Z_DELREF_P(value); } zendi_zval_dtor(garbage); @@ -786,86 +757,65 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 zend_uint refcount = Z_REFCOUNT_P(variable_ptr); zval garbage; - if (type!=IS_TMP_VAR) { + if (!is_tmp_var) { Z_ADDREF_P(value); } garbage = *variable_ptr; *variable_ptr = *value; Z_SET_REFCOUNT_P(variable_ptr, refcount); Z_SET_ISREF_P(variable_ptr); - if (type!=IS_TMP_VAR) { + if (!is_tmp_var) { zendi_zval_copy_ctor(*variable_ptr); Z_DELREF_P(value); } zendi_zval_dtor(garbage); } } else { - Z_DELREF_P(variable_ptr); - if (Z_REFCOUNT_P(variable_ptr)==0) { - switch (type) { - case IS_CV: - case IS_VAR: - /* break missing intentionally */ - case IS_CONST: - if (variable_ptr==value) { - Z_ADDREF_P(variable_ptr); - } else if (PZVAL_IS_REF(value)) { - zval tmp; - - tmp = *value; - zval_copy_ctor(&tmp); - Z_SET_REFCOUNT(tmp, 1); - zendi_zval_dtor(*variable_ptr); - *variable_ptr = tmp; - } else { - Z_ADDREF_P(value); - zendi_zval_dtor(*variable_ptr); - safe_free_zval_ptr(variable_ptr); - *variable_ptr_ptr = value; - } - break; - case IS_TMP_VAR: + if (Z_DELREF_P(variable_ptr)==0) { + if (!is_tmp_var) { + if (variable_ptr==value) { + Z_ADDREF_P(variable_ptr); + } else if (PZVAL_IS_REF(value)) { + zval tmp; + + tmp = *value; + zval_copy_ctor(&tmp); + Z_SET_REFCOUNT(tmp, 1); zendi_zval_dtor(*variable_ptr); - Z_SET_REFCOUNT_P(value, 1); - *variable_ptr = *value; - break; - EMPTY_SWITCH_DEFAULT_CASE() - } + *variable_ptr = tmp; + } else { + Z_ADDREF_P(value); + zendi_zval_dtor(*variable_ptr); + safe_free_zval_ptr(variable_ptr); + *variable_ptr_ptr = value; + } + } else { + zendi_zval_dtor(*variable_ptr); + Z_SET_REFCOUNT_P(value, 1); + *variable_ptr = *value; + } } else { /* we need to split */ - switch (type) { - case IS_CV: - case IS_VAR: - /* break missing intentionally */ - case IS_CONST: - if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) { - ALLOC_ZVAL(variable_ptr); - *variable_ptr_ptr = variable_ptr; - *variable_ptr = *value; - zval_copy_ctor(variable_ptr); - Z_SET_REFCOUNT_P(variable_ptr, 1); - break; - } + if (!is_tmp_var) { + if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) { + ALLOC_ZVAL(variable_ptr); + *variable_ptr_ptr = variable_ptr; + *variable_ptr = *value; + zval_copy_ctor(variable_ptr); + Z_SET_REFCOUNT_P(variable_ptr, 1); + } else { *variable_ptr_ptr = value; Z_ADDREF_P(value); - break; - case IS_TMP_VAR: - ALLOC_ZVAL(*variable_ptr_ptr); - Z_SET_REFCOUNT_P(value, 1); - **variable_ptr_ptr = *value; - break; - EMPTY_SWITCH_DEFAULT_CASE() - } + } + } else { + ALLOC_ZVAL(*variable_ptr_ptr); + Z_SET_REFCOUNT_P(value, 1); + **variable_ptr_ptr = *value; + } } Z_UNSET_ISREF_PP(variable_ptr_ptr); } -done_setting_var: - if (result && !RETURN_VALUE_UNUSED(result)) { - T(result->u.var).var.ptr_ptr = variable_ptr_ptr; - PZVAL_LOCK(*variable_ptr_ptr); - AI_USE_PTR(T(result->u.var).var); - } - FREE_OP_VAR_PTR(free_op1); + return *variable_ptr_ptr; } @@ -1055,7 +1005,7 @@ static void zend_fetch_dimension_address(temp_variable *result, zval **container switch (Z_TYPE_P(container)) { case IS_ARRAY: - if ((type==BP_VAR_W || type==BP_VAR_RW) && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) { + if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) { SEPARATE_ZVAL(container_ptr); container = *container_ptr; } @@ -1075,9 +1025,6 @@ fetch_from_array: if (result) { result->var.ptr_ptr = retval; PZVAL_LOCK(*retval); - if (type == BP_VAR_R || type == BP_VAR_IS) { - AI_USE_PTR(result->var); - } } return; break; @@ -1087,11 +1034,8 @@ fetch_from_array: if (result) { result->var.ptr_ptr = &EG(error_zval_ptr); PZVAL_LOCK(EG(error_zval_ptr)); - if (type == BP_VAR_R || type == BP_VAR_IS) { - AI_USE_PTR(result->var); - } } - } else if (type == BP_VAR_RW || type == BP_VAR_W) { + } else if (type != BP_VAR_UNSET) { convert_to_array: if (!PZVAL_IS_REF(container)) { SEPARATE_ZVAL(container_ptr); @@ -1101,12 +1045,9 @@ convert_to_array: array_init(container); goto fetch_from_array; } else if (result) { - /* for read-mode only */ + /* for read-mode only */ result->var.ptr_ptr = &EG(uninitialized_zval_ptr); PZVAL_LOCK(EG(uninitialized_zval_ptr)); - if (type == BP_VAR_R || type == BP_VAR_IS) { - AI_USE_PTR(result->var); - } } return; break; @@ -1114,7 +1055,7 @@ convert_to_array: case IS_STRING: { zval tmp; - if ((type == BP_VAR_RW || type == BP_VAR_W) && Z_STRLEN_P(container)==0) { + if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) { goto convert_to_array; } if (dim == NULL) { @@ -1140,15 +1081,8 @@ convert_to_array: convert_to_long(&tmp); dim = &tmp; } - switch (type) { - case BP_VAR_R: - case BP_VAR_IS: - case BP_VAR_UNSET: - /* do nothing... */ - break; - default: - SEPARATE_ZVAL_IF_NOT_REF(container_ptr); - break; + if (type != BP_VAR_UNSET) { + SEPARATE_ZVAL_IF_NOT_REF(container_ptr); } if (result) { container = *container_ptr; @@ -1156,9 +1090,7 @@ convert_to_array: PZVAL_LOCK(container); result->str_offset.offset = Z_LVAL_P(dim); result->var.ptr_ptr = NULL; - if (type == BP_VAR_R || type == BP_VAR_IS) { - AI_USE_PTR(result->var); - } + result->var.ptr = NULL; } return; } @@ -1178,8 +1110,7 @@ convert_to_array: overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC); if (overloaded_result) { - if (!Z_ISREF_P(overloaded_result) && - (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET)) { + if (!Z_ISREF_P(overloaded_result)) { if (Z_REFCOUNT_P(overloaded_result) > 0) { zval *tmp = overloaded_result; @@ -1199,9 +1130,8 @@ convert_to_array: retval = &EG(error_zval_ptr); } if (result) { - result->var.ptr_ptr = retval; - AI_USE_PTR(result->var); - PZVAL_LOCK(*result->var.ptr_ptr); + AI_SET_PTR(result->var, *retval); + PZVAL_LOCK(*retval); } else if (Z_REFCOUNT_PP(retval) == 0) { /* Destroy unused result from offsetGet() magic method */ Z_SET_REFCOUNT_PP(retval, 1); @@ -1215,37 +1145,150 @@ convert_to_array: break; case IS_BOOL: - if ((type == BP_VAR_RW || type == BP_VAR_W) && Z_LVAL_P(container)==0) { + if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) { goto convert_to_array; } /* break missing intentionally */ default: - switch (type) { - case BP_VAR_UNSET: - zend_error(E_WARNING, "Cannot unset offset in a non-array variable"); - /* break missing intentionally */ - case BP_VAR_R: - case BP_VAR_IS: - if (result) { - result->var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(EG(uninitialized_zval_ptr)); - AI_USE_PTR(result->var); + if (type == BP_VAR_UNSET) { + zend_error(E_WARNING, "Cannot unset offset in a non-array variable"); + if (result) { + AI_SET_PTR(result->var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); + if (result) { + result->var.ptr_ptr = &EG(error_zval_ptr); + PZVAL_LOCK(EG(error_zval_ptr)); + } + } + break; + } +} + +static void zend_fetch_dimension_address_read(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC) +{ + zval *container; + zval **retval; + + if (!container_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); + } + + container = *container_ptr; + switch (Z_TYPE_P(container)) { + + case IS_ARRAY: + if (dim == NULL) { + zval *new_zval = &EG(uninitialized_zval); + + Z_ADDREF_P(new_zval); + if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + retval = &EG(error_zval_ptr); + Z_DELREF_P(new_zval); + } + } else { + retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC); + } + if (result) { + AI_SET_PTR(result->var, *retval); + PZVAL_LOCK(*retval); + } + return; + break; + + case IS_NULL: + if (container == EG(error_zval_ptr)) { + if (result) { + AI_SET_PTR(result->var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); + } + } else if (result) { + AI_SET_PTR(result->var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } + return; + break; + + case IS_STRING: { + zval tmp; + + if (dim == NULL) { + zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); + } + + if (Z_TYPE_P(dim) != IS_LONG) { + switch(Z_TYPE_P(dim)) { + /* case IS_LONG: */ + case IS_STRING: + case IS_DOUBLE: + case IS_NULL: + case IS_BOOL: + /* do nothing */ + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + break; } - return; - break; - case BP_VAR_W: - case BP_VAR_RW: - zend_error(E_WARNING, "Cannot use a scalar value as an array"); - /* break missing intentionally */ - default: + + tmp = *dim; + zval_copy_ctor(&tmp); + convert_to_long(&tmp); + dim = &tmp; + } + if (result) { + result->str_offset.str = container; + PZVAL_LOCK(container); + result->str_offset.offset = Z_LVAL_P(dim); + result->var.ptr_ptr = NULL; + result->var.ptr = NULL; + } + return; + } + break; + + case IS_OBJECT: + if (!Z_OBJ_HT_P(container)->read_dimension) { + zend_error_noreturn(E_ERROR, "Cannot use object as array"); + } else { + zval *overloaded_result; + + if (dim_is_tmp_var) { + zval *orig = dim; + MAKE_REAL_ZVAL_PTR(dim); + ZVAL_NULL(orig); + } + overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC); + + if (overloaded_result) { if (result) { - result->var.ptr_ptr = &EG(error_zval_ptr); - PZVAL_LOCK(EG(error_zval_ptr)); + AI_SET_PTR(result->var, overloaded_result); + PZVAL_LOCK(overloaded_result); + } else if (Z_REFCOUNT_P(overloaded_result) == 0) { + /* Destroy unused result from offsetGet() magic method */ + Z_SET_REFCOUNT_P(overloaded_result, 1); + zval_ptr_dtor(&overloaded_result); } - return; - break; + } else if (result) { + AI_SET_PTR(result->var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); + } + if (dim_is_tmp_var) { + zval_ptr_dtor(&dim); + } } + return; + break; + + default: + if (result) { + AI_SET_PTR(result->var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } + return; break; } } @@ -1264,39 +1307,32 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_ } container = *container_ptr; - if (container == EG(error_zval_ptr)) { - if (result) { - result->var.ptr_ptr = &EG(error_zval_ptr); - PZVAL_LOCK(*result->var.ptr_ptr); - } - return; - } - /* this should modify object only if it's empty */ - if (Z_TYPE_P(container) == IS_NULL - || (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) - || (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)) { - switch (type) { - case BP_VAR_RW: - case BP_VAR_W: - if (!PZVAL_IS_REF(container)) { - SEPARATE_ZVAL(container_ptr); - container = *container_ptr; - } - object_init(container); - break; + if (Z_TYPE_P(container) != IS_OBJECT) { + if (container == EG(error_zval_ptr)) { + if (result) { + result->var.ptr_ptr = &EG(error_zval_ptr); + PZVAL_LOCK(*result->var.ptr_ptr); + } + return; } - } - if (Z_TYPE_P(container) != IS_OBJECT) { - if (result) { - if (type == BP_VAR_R || type == BP_VAR_IS) { - result->var.ptr_ptr = &EG(uninitialized_zval_ptr); - } else { + /* this should modify object only if it's empty */ + if (type != BP_VAR_UNSET && + ((Z_TYPE_P(container) == IS_NULL || + (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) || + (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) { + if (!PZVAL_IS_REF(container)) { + SEPARATE_ZVAL(container_ptr); + container = *container_ptr; + } + object_init(container); + } else { + if (result) { result->var.ptr_ptr = &EG(error_zval_ptr); + PZVAL_LOCK(EG(error_zval_ptr)); } - PZVAL_LOCK(*result->var.ptr_ptr); + return; } - return; } if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) { @@ -1307,30 +1343,30 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_ if (Z_OBJ_HT_P(container)->read_property && (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC)) != NULL) { if (result) { - result->var.ptr = ptr; - result->var.ptr_ptr = &result->var.ptr; + AI_SET_PTR(result->var, ptr); + PZVAL_LOCK(ptr); } } else { zend_error(E_ERROR, "Cannot access undefined property for object with overloaded property access"); } } else if (result) { result->var.ptr_ptr = ptr_ptr; + PZVAL_LOCK(*ptr_ptr); } } else if (Z_OBJ_HT_P(container)->read_property) { + zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC); + if (result) { - result->var.ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC); - result->var.ptr_ptr = &result->var.ptr; + AI_SET_PTR(result->var, ptr); + PZVAL_LOCK(ptr); } } else { zend_error(E_WARNING, "This object doesn't support property references"); if (result) { result->var.ptr_ptr = &EG(error_zval_ptr); + PZVAL_LOCK(EG(error_zval_ptr)); } } - - if (result) { - PZVAL_LOCK(*result->var.ptr_ptr); - } } static inline zend_brk_cont_element* zend_brk_cont(zval *nest_levels_zval, int array_offset, zend_op_array *op_array, temp_variable *Ts TSRMLS_DC) @@ -1358,7 +1394,7 @@ static inline zend_brk_cont_element* zend_brk_cont(zval *nest_levels_zval, int a switch (brk_opline->opcode) { case ZEND_SWITCH_FREE: - zend_switch_free(brk_opline, Ts TSRMLS_CC); + zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC); break; case ZEND_FREE: zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 51f0efe3f8..747e5a7b10 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -291,7 +291,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -304,8 +303,9 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -323,8 +323,9 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -366,15 +367,17 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -420,7 +423,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW), dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -438,9 +441,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } FREE_OP2(); FREE_OP1_VAR_PTR(); @@ -465,9 +467,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } FREE_OP2(); @@ -729,9 +730,8 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) } if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); @@ -752,9 +752,8 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } FREE_OP1_VAR_PTR(); @@ -772,9 +771,8 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) } if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); @@ -795,9 +793,8 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } FREE_OP1_VAR_PTR(); @@ -984,16 +981,16 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type if (opline->extended_value & ZEND_FETCH_MAKE_REF) { SEPARATE_ZVAL_TO_MAKE_IS_REF(retval); } - EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_LOCK(*retval); switch (type) { case BP_VAR_R: case BP_VAR_IS: - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *retval); break; case BP_VAR_UNSET: { zend_free_op free_res; + EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res); if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr); @@ -1001,6 +998,9 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); FREE_OP_VAR_PTR(free_res); break; + default: + EX_T(opline->result.u.var).var.ptr_ptr = retval; + break; } } } @@ -1049,7 +1049,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VAR|CV, CONST|TMP|VAR|CV) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_R), dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_R), dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC); FREE_OP2(); FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); @@ -1111,7 +1111,7 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV) zend_free_op free_op1, free_op2; zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS), dim, IS_OP2_TMP_FREE(), BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS), dim, IS_OP2_TMP_FREE(), BP_VAR_IS TSRMLS_CC); FREE_OP2(); FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); @@ -1121,24 +1121,26 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV) { zend_op *opline = EX(opline); zend_free_op free_op1, free_op2; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; + zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - if (OP2_TYPE == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(type), dim, IS_OP2_TMP_FREE(), type TSRMLS_CC); - FREE_OP2(); - if (OP1_TYPE == IS_VAR && type == BP_VAR_W && OP1_FREE && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_W), dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC); + if (OP1_TYPE == IS_VAR && OP1_FREE && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } + } + } else { + if (OP2_TYPE == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), GET_OP1_ZVAL_PTR_PTR(BP_VAR_R), dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC); } + FREE_OP2(); FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE(); } @@ -1190,20 +1192,13 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) ZEND_VM_HELPER_EX(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV, int type) { zend_op *opline = EX(opline); - zval *container; - zval **retval; zend_free_op free_op1; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = GET_OP1_OBJ_ZVAL_PTR(type); + zval *container = GET_OP1_OBJ_ZVAL_PTR(type); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } FREE_OP1(); ZEND_VM_NEXT_OPCODE(); @@ -1214,26 +1209,30 @@ ZEND_VM_HELPER_EX(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST| if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval *retval; if (IS_OP2_TMP_FREE()) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (IS_OP2_TMP_FREE()) { @@ -1409,18 +1408,17 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_DIM_TMP_VAR, CONST|TMP, CONST) if (Z_TYPE_P(container) != IS_ARRAY) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { zend_free_op free_op2; zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - EX_T(opline->result.u.var).var.ptr_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result); + AI_SET_PTR(EX_T(opline->result.u.var).var, *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC)); + SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr, &opline->result); FREE_OP2(); } - AI_USE_PTR(EX_T(opline->result.u.var).var); ZEND_VM_NEXT_OPCODE(); } @@ -1428,10 +1426,19 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W); + zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (IS_OP2_TMP_FREE()) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (IS_OP2_TMP_FREE()) { + zval_ptr_dtor(&property_name); + } else { + FREE_OP2(); + } FREE_OP1_VAR_PTR(); /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -1453,17 +1460,39 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + zend_free_op free_op2; + zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + + if (IS_OP2_TMP_FREE()) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (IS_OP2_TMP_FREE()) { + zval_ptr_dtor(&property_name); + } else { + FREE_OP2(); + } } else { - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC); FREE_OP2(); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } FREE_OP1_VAR_PTR(); @@ -1475,10 +1504,23 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) { zend_op *opline = EX(opline); - zend_free_op free_op2; + zend_free_op free_op1, free_op2; zval *value = GET_OP2_ZVAL_PTR(BP_VAR_R); + zval **variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, OP2_TYPE TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_OP2_TMP_FREE() TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + + FREE_OP1_VAR_PTR(); - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (IS_OP2_TMP_FREE()?IS_TMP_VAR:OP2_TYPE), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ FREE_OP2_IF_VAR(); @@ -1511,9 +1553,8 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC); if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = variable_ptr_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr); PZVAL_LOCK(*variable_ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } FREE_OP1_VAR_PTR(); @@ -2456,7 +2497,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) { zend_op *opline = EX(opline); - zval **param, *assignment_value; + zval **param, *assignment_value, **var_ptr; zend_uint arg_num = Z_LVAL(opline->op1.u.constant); zend_free_op free_res; @@ -2480,10 +2521,11 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) assignment_value = &opline->op2.u.constant; } zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); - zend_assign_to_variable(NULL, &opline->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); + + var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W); + zend_assign_to_variable(var_ptr, assignment_value, 0 TSRMLS_CC); } else { - zval **var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W); - + var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W); assignment_value = *param; zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); if (PZVAL_IS_REF(assignment_value)) { @@ -2560,14 +2602,14 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) */ FREE_OP1(); EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HANDLER(49, ZEND_SWITCH_FREE, TMP|VAR, ANY) { - zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC); + zend_switch_free(&EX_T(EX(opline)->op1.u.var), OP1_TYPE, EX(opline)->extended_value TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } @@ -2595,16 +2637,16 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY) if (constructor == NULL) { if (RETURN_VALUE_USED(opline)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr = object_zval; + AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval); } else { zval_ptr_dtor(&object_zval); } ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.u.opline_num); } else { - SELECTIVE_PZVAL_LOCK(object_zval, &opline->result); - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr = object_zval; + if (RETURN_VALUE_USED(opline)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval); + PZVAL_LOCK(object_zval); + } zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline))); @@ -3292,9 +3334,8 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } } + AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr); PZVAL_LOCK(array_ptr); - EX_T(opline->result.u.var).var.ptr = array_ptr; - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; if (iter) { iter->index = 0; @@ -3478,9 +3519,8 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) EX_T(opline->result.u.var).var.ptr_ptr = value; Z_ADDREF_PP(value); } else { - EX_T(opline->result.u.var).var.ptr_ptr = value; - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *value); + PZVAL_LOCK(*value); } if (use_key) { @@ -3948,7 +3988,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) switch (brk_opline->opcode) { case ZEND_SWITCH_FREE: - zend_switch_free(brk_opline, EX(Ts) TSRMLS_CC); + zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC); break; case ZEND_FREE: zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 10a569f5a7..951ff462f2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -398,16 +398,16 @@ static int ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (constructor == NULL) { if (RETURN_VALUE_USED(opline)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr = object_zval; + AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval); } else { zval_ptr_dtor(&object_zval); } ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.u.opline_num); } else { - SELECTIVE_PZVAL_LOCK(object_zval, &opline->result); - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr = object_zval; + if (RETURN_VALUE_USED(opline)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval); + PZVAL_LOCK(object_zval); + } zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline))); @@ -566,7 +566,7 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) switch (brk_opline->opcode) { case ZEND_SWITCH_FREE: - zend_switch_free(brk_opline, EX(Ts) TSRMLS_CC); + zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->op1.op_type, brk_opline->extended_value TSRMLS_CC); break; case ZEND_FREE: zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var); @@ -715,7 +715,7 @@ static int ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG static int ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval **param, *assignment_value; + zval **param, *assignment_value, **var_ptr; zend_uint arg_num = Z_LVAL(opline->op1.u.constant); zend_free_op free_res; @@ -739,10 +739,11 @@ static int ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) assignment_value = &opline->op2.u.constant; } zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); - zend_assign_to_variable(NULL, &opline->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); - } else { - zval **var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W); + var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W); + zend_assign_to_variable(var_ptr, assignment_value, 0 TSRMLS_CC); + } else { + var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W); assignment_value = *param; zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); if (PZVAL_IS_REF(assignment_value)) { @@ -1235,16 +1236,16 @@ static int zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLE if (opline->extended_value & ZEND_FETCH_MAKE_REF) { SEPARATE_ZVAL_TO_MAKE_IS_REF(retval); } - EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_LOCK(*retval); switch (type) { case BP_VAR_R: case BP_VAR_IS: - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *retval); break; case BP_VAR_UNSET: { zend_free_op free_res; + EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res); if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr); @@ -1252,6 +1253,9 @@ static int zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLE PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); FREE_OP_VAR_PTR(free_res); break; + default: + EX_T(opline->result.u.var).var.ptr_ptr = retval; + break; } } } @@ -1919,9 +1923,8 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } + AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr); PZVAL_LOCK(array_ptr); - EX_T(opline->result.u.var).var.ptr = array_ptr; - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; if (iter) { iter->index = 0; @@ -2351,18 +2354,17 @@ static int ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_A if (Z_TYPE_P(container) != IS_ARRAY) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { zval *dim = &opline->op2.u.constant; - EX_T(opline->result.u.var).var.ptr_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result); + AI_SET_PTR(EX_T(opline->result.u.var).var, *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC)); + SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr, &opline->result); } - AI_USE_PTR(EX_T(opline->result.u.var).var); ZEND_VM_NEXT_OPCODE(); } @@ -2481,7 +2483,7 @@ static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -3035,7 +3037,7 @@ static int ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -3483,7 +3485,7 @@ static int ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -4112,7 +4114,7 @@ static int ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -4336,16 +4338,16 @@ static int zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_ if (opline->extended_value & ZEND_FETCH_MAKE_REF) { SEPARATE_ZVAL_TO_MAKE_IS_REF(retval); } - EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_LOCK(*retval); switch (type) { case BP_VAR_R: case BP_VAR_IS: - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *retval); break; case BP_VAR_UNSET: { zend_free_op free_res; + EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res); if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr); @@ -4353,6 +4355,9 @@ static int zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_ PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); FREE_OP_VAR_PTR(free_res); break; + default: + EX_T(opline->result.u.var).var.ptr_ptr = retval; + break; } } } @@ -4634,7 +4639,7 @@ static int ZEND_BOOL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_SWITCH_FREE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC); + zend_switch_free(&EX_T(EX(opline)->op1.u.var), IS_TMP_VAR, EX(opline)->extended_value TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } @@ -5022,9 +5027,8 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } + AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr); PZVAL_LOCK(array_ptr); - EX_T(opline->result.u.var).var.ptr = array_ptr; - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; if (iter) { iter->index = 0; @@ -5478,18 +5482,17 @@ static int ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG if (Z_TYPE_P(container) != IS_ARRAY) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { zval *dim = &opline->op2.u.constant; - EX_T(opline->result.u.var).var.ptr_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &opline->result); + AI_SET_PTR(EX_T(opline->result.u.var).var, *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC)); + SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr, &opline->result); } - AI_USE_PTR(EX_T(opline->result.u.var).var); ZEND_VM_NEXT_OPCODE(); } @@ -5598,7 +5601,7 @@ static int ZEND_CASE_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ zval_dtor(free_op1.var); EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -6045,7 +6048,7 @@ static int ZEND_CASE_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ zval_dtor(free_op1.var); EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -6492,7 +6495,7 @@ static int ZEND_CASE_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ zval_dtor(free_op1.var); EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -7029,7 +7032,7 @@ static int ZEND_CASE_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ zval_dtor(free_op1.var); EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -7160,9 +7163,8 @@ static int ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -7183,9 +7185,8 @@ static int ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -7203,9 +7204,8 @@ static int ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -7226,9 +7226,8 @@ static int ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -7415,16 +7414,16 @@ static int zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_ if (opline->extended_value & ZEND_FETCH_MAKE_REF) { SEPARATE_ZVAL_TO_MAKE_IS_REF(retval); } - EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_LOCK(*retval); switch (type) { case BP_VAR_R: case BP_VAR_IS: - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *retval); break; case BP_VAR_UNSET: { zend_free_op free_res; + EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res); if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr); @@ -7432,6 +7431,9 @@ static int zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_ PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); FREE_OP_VAR_PTR(free_res); break; + default: + EX_T(opline->result.u.var).var.ptr_ptr = retval; + break; } } } @@ -7812,7 +7814,7 @@ static int ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_SWITCH_FREE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC); + zend_switch_free(&EX_T(EX(opline)->op1.u.var), IS_VAR, EX(opline)->extended_value TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } @@ -8200,9 +8202,8 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } + AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr); PZVAL_LOCK(array_ptr); - EX_T(opline->result.u.var).var.ptr = array_ptr; - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; if (iter) { iter->index = 0; @@ -8386,9 +8387,8 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->result.u.var).var.ptr_ptr = value; Z_ADDREF_PP(value); } else { - EX_T(opline->result.u.var).var.ptr_ptr = value; - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *value); + PZVAL_LOCK(*value); } if (use_key) { @@ -8787,7 +8787,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval zval *property = &opline->op2.u.constant; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -8800,8 +8799,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -8819,8 +8819,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -8862,15 +8863,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -8916,7 +8919,7 @@ static int zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *re zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -8934,9 +8937,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *re if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -8961,9 +8963,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *re } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -9224,7 +9225,7 @@ static int ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -9286,7 +9287,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; zval *dim = &opline->op2.u.constant; - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -9296,24 +9297,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR { zend_op *opline = EX(opline); zend_free_op free_op1; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; - - if (IS_CONST == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = &opline->op2.u.constant; - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, type TSRMLS_CC); + zval *dim = &opline->op2.u.constant; - if (IS_VAR == IS_VAR && type == BP_VAR_W && (free_op1.var != NULL) && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && (free_op1.var != NULL) && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } } + } else { + if (IS_CONST == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); } @@ -9365,20 +9368,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_VAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; zend_free_op free_op1; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -9389,26 +9385,30 @@ static int zend_fetch_property_address_read_helper_SPEC_VAR_CONST(int type, ZEND if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zval *offset = &opline->op2.u.constant; + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -9582,8 +9582,17 @@ static int ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *op_data = opline+1; zend_free_op free_op1; zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *property_name = &opline->op2.u.constant; + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -9605,16 +9614,38 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + + zval *property_name = &opline->op2.u.constant; + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } } else { - zend_free_op free_op_data1; + zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = &opline->op2.u.constant; + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -9626,10 +9657,23 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - + zend_free_op free_op1; zval *value = &opline->op2.u.constant; + zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CONST TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (0?IS_TMP_VAR:IS_CONST), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE(); @@ -9806,7 +9850,7 @@ static int ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -10482,7 +10526,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval * zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -10495,8 +10538,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval * FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -10514,8 +10558,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval * have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -10557,15 +10602,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval * break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -10611,7 +10658,7 @@ static int zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_op)(zval *resu zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -10629,9 +10676,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_op)(zval *resu if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -10656,9 +10702,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_op)(zval *resu } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } zval_dtor(free_op2.var); @@ -10920,7 +10965,7 @@ static int ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_R TSRMLS_CC); zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -10982,7 +11027,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1, free_op2; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_IS TSRMLS_CC); zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -10992,24 +11037,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS { zend_op *opline = EX(opline); zend_free_op free_op1, free_op2; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; + zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (IS_TMP_VAR == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, type TSRMLS_CC); - zval_dtor(free_op2.var); - if (IS_VAR == IS_VAR && type == BP_VAR_W && (free_op1.var != NULL) && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && (free_op1.var != NULL) && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } + } + } else { + if (IS_TMP_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 1, BP_VAR_R TSRMLS_CC); } + zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); } @@ -11061,20 +11108,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_VAR_TMP(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; zend_free_op free_op1; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -11085,26 +11125,30 @@ static int zend_fetch_property_address_read_helper_SPEC_VAR_TMP(int type, ZEND_O if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval *retval; if (1) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (1) { @@ -11276,10 +11320,19 @@ static int ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (1) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (1) { + zval_ptr_dtor(&property_name); + } else { + zval_dtor(free_op2.var); + } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -11301,17 +11354,39 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (1) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (1) { + zval_ptr_dtor(&property_name); + } else { + zval_dtor(free_op2.var); + } } else { - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 1, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11323,10 +11398,23 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_free_op free_op2; + zend_free_op free_op1, free_op2; zval *value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_TMP_VAR TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 1 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (1?IS_TMP_VAR:IS_TMP_VAR), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE(); @@ -11505,7 +11593,7 @@ static int ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -12109,7 +12197,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval * zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -12122,8 +12209,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval * FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -12141,8 +12229,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval * have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -12184,15 +12273,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval * break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -12238,7 +12329,7 @@ static int zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_op)(zval *resu zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -12256,9 +12347,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_op)(zval *resu if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12283,9 +12373,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_op)(zval *resu } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -12547,7 +12636,7 @@ static int ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -12609,7 +12698,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1, free_op2; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -12619,24 +12708,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS { zend_op *opline = EX(opline); zend_free_op free_op1, free_op2; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; + zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (IS_VAR == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, type TSRMLS_CC); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (IS_VAR == IS_VAR && type == BP_VAR_W && (free_op1.var != NULL) && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && (free_op1.var != NULL) && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } } + } else { + if (IS_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); } @@ -12688,20 +12779,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_VAR_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; zend_free_op free_op1; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -12712,26 +12796,30 @@ static int zend_fetch_property_address_read_helper_SPEC_VAR_VAR(int type, ZEND_O if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -12903,10 +12991,19 @@ static int ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - zend_free_op free_op1; + zend_free_op free_op1, free_op2; zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -12928,17 +13025,39 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } } else { - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12950,10 +13069,23 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_free_op free_op2; + zend_free_op free_op1, free_op2; zval *value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_VAR TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (0?IS_TMP_VAR:IS_VAR), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -12986,9 +13118,8 @@ static int ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC); if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = variable_ptr_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr); PZVAL_LOCK(*variable_ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -13170,7 +13301,7 @@ static int ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -13540,7 +13671,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zva zval *property = NULL; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -13553,8 +13683,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zva FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -13572,8 +13703,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zva have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -13615,15 +13747,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zva break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -13669,7 +13803,7 @@ static int zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *r zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -13687,9 +13821,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *r if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -13714,9 +13847,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *r } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -13837,24 +13969,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_A { zend_op *opline = EX(opline); zend_free_op free_op1; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; - - if (IS_UNUSED == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = NULL; - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, type TSRMLS_CC); + zval *dim = NULL; - if (IS_VAR == IS_VAR && type == BP_VAR_W && (free_op1.var != NULL) && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && (free_op1.var != NULL) && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } } + } else { + if (IS_UNUSED == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); } @@ -13874,17 +14008,39 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + + zval *property_name = NULL; + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } } else { - zend_free_op free_op_data1; + zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = NULL; + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); - FREE_OP_IF_VAR(free_op_data1); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); + FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* assign_dim has two opcodes! */ @@ -14318,7 +14474,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *r zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -14331,8 +14486,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *r FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -14350,8 +14506,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *r have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -14393,15 +14550,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *r break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -14447,7 +14606,7 @@ static int zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_op)(zval *resul zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -14465,9 +14624,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_op)(zval *resul if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -14492,9 +14650,8 @@ static int zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_op)(zval *resul } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -14755,7 +14912,7 @@ static int ZEND_FETCH_DIM_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -14817,7 +14974,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -14827,24 +14984,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_free_op free_op1; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; - - if (IS_CV == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, type TSRMLS_CC); + zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (IS_VAR == IS_VAR && type == BP_VAR_W && (free_op1.var != NULL) && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_VAR == IS_VAR && (free_op1.var != NULL) && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } + } + } else { + if (IS_CV == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); } @@ -14896,20 +15055,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_VAR_CV(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; zend_free_op free_op1; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; ZEND_VM_NEXT_OPCODE(); @@ -14920,26 +15072,30 @@ static int zend_fetch_property_address_read_helper_SPEC_VAR_CV(int type, ZEND_OP if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -15113,8 +15269,17 @@ static int ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *op_data = opline+1; zend_free_op free_op1; zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -15136,16 +15301,38 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + + zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } } else { - zend_free_op free_op_data1; + zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -15157,10 +15344,23 @@ static int ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - + zend_free_op free_op1; zval *value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CV TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (0?IS_TMP_VAR:IS_CV), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE(); @@ -15192,9 +15392,8 @@ static int ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC); if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = variable_ptr_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr); PZVAL_LOCK(*variable_ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -15373,7 +15572,7 @@ static int ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -15825,7 +16024,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(z zval *property = &opline->op2.u.constant; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -15838,8 +16036,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(z FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -15857,8 +16056,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(z have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -15900,15 +16100,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(z break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -15953,7 +16155,7 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), NULL, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -15971,9 +16173,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -15998,9 +16199,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -16253,20 +16453,13 @@ static int ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *container = _get_obj_zval_ptr_unused(TSRMLS_C); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -16277,26 +16470,30 @@ static int zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(int type, Z if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zval *offset = &opline->op2.u.constant; + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -16467,8 +16664,17 @@ static int ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *op_data = opline+1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); + zval *property_name = &opline->op2.u.constant; - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -16884,7 +17090,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zva zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -16897,8 +17102,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zva FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -16916,8 +17122,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zva have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -16959,15 +17166,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zva break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -17012,7 +17221,7 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *r zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), NULL, dim, 1, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -17030,9 +17239,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *r if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } zval_dtor(free_op2.var); @@ -17057,9 +17265,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *r } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } zval_dtor(free_op2.var); @@ -17313,20 +17520,13 @@ static int ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *container = _get_obj_zval_ptr_unused(TSRMLS_C); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -17337,26 +17537,30 @@ static int zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(int type, ZEN if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval *retval; if (1) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (1) { @@ -17525,10 +17729,19 @@ static int ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - + zend_free_op free_op2; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); + zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (1) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (1) { + zval_ptr_dtor(&property_name); + } else { + zval_dtor(free_op2.var); + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -17873,7 +18086,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zva zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -17886,8 +18098,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zva FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -17905,8 +18118,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zva have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -17948,15 +18162,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zva break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -18001,7 +18217,7 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *r zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), NULL, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -18019,9 +18235,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *r if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -18046,9 +18261,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *r } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -18302,20 +18516,13 @@ static int ZEND_POST_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - container = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *container = _get_obj_zval_ptr_unused(TSRMLS_C); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -18326,26 +18533,30 @@ static int zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(int type, ZEN if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -18514,10 +18725,19 @@ static int ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - + zend_free_op free_op2; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); + zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -18862,7 +19082,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)( zval *property = NULL; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -18875,8 +19094,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)( FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -18894,8 +19114,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)( have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -18937,15 +19158,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)( break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -18990,7 +19213,7 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), NULL, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -19008,9 +19231,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -19035,9 +19257,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -19128,7 +19349,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -19141,8 +19361,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -19160,8 +19381,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -19203,15 +19425,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -19256,7 +19480,7 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *re zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), NULL, dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -19274,9 +19498,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *re if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -19301,9 +19524,8 @@ static int zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *re } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -19556,20 +19778,13 @@ static int ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_obj_zval_ptr_unused(TSRMLS_C); + zval *container = _get_obj_zval_ptr_unused(TSRMLS_C); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -19580,26 +19795,30 @@ static int zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(int type, ZEND if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -19770,8 +19989,17 @@ static int ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *op_data = opline+1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); + zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -20138,9 +20366,8 @@ static int ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -20161,9 +20388,8 @@ static int ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } ZEND_VM_NEXT_OPCODE(); @@ -20180,9 +20406,8 @@ static int ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -20203,9 +20428,8 @@ static int ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } ZEND_VM_NEXT_OPCODE(); @@ -20388,16 +20612,16 @@ static int zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_A if (opline->extended_value & ZEND_FETCH_MAKE_REF) { SEPARATE_ZVAL_TO_MAKE_IS_REF(retval); } - EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_LOCK(*retval); switch (type) { case BP_VAR_R: case BP_VAR_IS: - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, *retval); break; case BP_VAR_UNSET: { zend_free_op free_res; + EX_T(opline->result.u.var).var.ptr_ptr = retval; PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res); if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr); @@ -20405,6 +20629,9 @@ static int zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_A PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); FREE_OP_VAR_PTR(free_res); break; + default: + EX_T(opline->result.u.var).var.ptr_ptr = retval; + break; } } } @@ -21160,9 +21387,8 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } + AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr); PZVAL_LOCK(array_ptr); - EX_T(opline->result.u.var).var.ptr = array_ptr; - EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; if (iter) { iter->index = 0; @@ -21598,7 +21824,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval zval *property = &opline->op2.u.constant; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -21611,8 +21836,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -21630,8 +21856,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -21673,15 +21900,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -21726,7 +21955,7 @@ static int zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *res zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -21744,9 +21973,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *res if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -21771,9 +21999,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *res } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -22034,7 +22261,7 @@ static int ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); @@ -22095,7 +22322,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *dim = &opline->op2.u.constant; - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); @@ -22105,25 +22332,27 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG { zend_op *opline = EX(opline); zend_free_op free_op1; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; - - if (IS_CONST == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = &opline->op2.u.constant; - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC), dim, 0, type TSRMLS_CC); + zval *dim = &opline->op2.u.constant; - if (IS_CV == IS_VAR && type == BP_VAR_W && 0 && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_CV == IS_VAR && 0 && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } + } + } else { + if (IS_CONST == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + ZEND_VM_NEXT_OPCODE(); } @@ -22174,20 +22403,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_CV_CONST(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); + zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -22198,26 +22420,30 @@ static int zend_fetch_property_address_read_helper_SPEC_CV_CONST(int type, ZEND_ if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zval *offset = &opline->op2.u.constant; + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -22388,8 +22614,17 @@ static int ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *op_data = opline+1; zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + zval *property_name = &opline->op2.u.constant; + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -22411,16 +22646,38 @@ static int ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + + zval *property_name = &opline->op2.u.constant; + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } } else { - zend_free_op free_op_data1; + zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = &opline->op2.u.constant; + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } @@ -22434,8 +22691,19 @@ static int ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *opline = EX(opline); zval *value = &opline->op2.u.constant; + zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CONST TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (0?IS_TMP_VAR:IS_CONST), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE(); @@ -22522,7 +22790,7 @@ static int ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -23122,7 +23390,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *r zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -23135,8 +23402,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *r FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -23154,8 +23422,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *r have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -23197,15 +23466,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *r break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -23250,7 +23521,7 @@ static int zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_op)(zval *resul zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC), dim, 1, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -23268,9 +23539,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_op)(zval *resul if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } zval_dtor(free_op2.var); @@ -23295,9 +23565,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_op)(zval *resul } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } zval_dtor(free_op2.var); @@ -23559,7 +23828,7 @@ static int ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 1, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 1, BP_VAR_R TSRMLS_CC); zval_dtor(free_op2.var); ZEND_VM_NEXT_OPCODE(); @@ -23620,7 +23889,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op2; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 1, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 1, BP_VAR_IS TSRMLS_CC); zval_dtor(free_op2.var); ZEND_VM_NEXT_OPCODE(); @@ -23630,24 +23899,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_free_op free_op1, free_op2; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; + zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (IS_TMP_VAR == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC), dim, 1, type TSRMLS_CC); - zval_dtor(free_op2.var); - if (IS_CV == IS_VAR && type == BP_VAR_W && 0 && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC), dim, 1, BP_VAR_W TSRMLS_CC); + if (IS_CV == IS_VAR && 0 && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } + } + } else { + if (IS_TMP_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 1, BP_VAR_R TSRMLS_CC); } + zval_dtor(free_op2.var); ZEND_VM_NEXT_OPCODE(); } @@ -23699,20 +23970,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_CV_TMP(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); + zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -23723,26 +23987,30 @@ static int zend_fetch_property_address_read_helper_SPEC_CV_TMP(int type, ZEND_OP if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval *retval; if (1) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (1) { @@ -23911,10 +24179,19 @@ static int ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - + zend_free_op free_op2; zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (1) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (1) { + zval_ptr_dtor(&property_name); + } else { + zval_dtor(free_op2.var); + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -23936,17 +24213,39 @@ static int ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (1) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (1) { + zval_ptr_dtor(&property_name); + } else { + zval_dtor(free_op2.var); + } } else { - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 1, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } @@ -23960,8 +24259,19 @@ static int ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *opline = EX(opline); zend_free_op free_op2; zval *value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_TMP_VAR TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 1 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (1?IS_TMP_VAR:IS_TMP_VAR), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE(); @@ -24050,7 +24360,7 @@ static int ZEND_CASE_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -24650,7 +24960,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*binary_op)(zval *r zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -24663,8 +24972,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*binary_op)(zval *r FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -24682,8 +24992,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*binary_op)(zval *r have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -24725,15 +25036,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*binary_op)(zval *r break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -24778,7 +25091,7 @@ static int zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_op)(zval *resul zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -24796,9 +25109,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_op)(zval *resul if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -24823,9 +25135,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_op)(zval *resul } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -25087,7 +25398,7 @@ static int ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; ZEND_VM_NEXT_OPCODE(); @@ -25148,7 +25459,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op2; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; ZEND_VM_NEXT_OPCODE(); @@ -25158,24 +25469,26 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_free_op free_op1, free_op2; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; + zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - if (IS_VAR == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC), dim, 0, type TSRMLS_CC); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (IS_CV == IS_VAR && type == BP_VAR_W && 0 && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_CV == IS_VAR && 0 && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } } + } else { + if (IS_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; ZEND_VM_NEXT_OPCODE(); } @@ -25227,20 +25540,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_CV_VAR(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); + zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -25251,26 +25557,30 @@ static int zend_fetch_property_address_read_helper_SPEC_CV_VAR(int type, ZEND_OP if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zend_free_op free_op2; zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -25439,10 +25749,19 @@ static int ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_op *op_data = opline+1; - + zend_free_op free_op2; zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -25464,17 +25783,39 @@ static int ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } } else { - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } @@ -25488,8 +25829,19 @@ static int ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *opline = EX(opline); zend_free_op free_op2; zval *value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); + zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_VAR TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (0?IS_TMP_VAR:IS_VAR), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -25522,9 +25874,8 @@ static int ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC); if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = variable_ptr_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr); PZVAL_LOCK(*variable_ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -25615,7 +25966,7 @@ static int ZEND_CASE_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); } @@ -25981,7 +26332,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval zval *property = NULL; zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -25994,8 +26344,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -26013,8 +26364,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -26056,15 +26408,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -26109,7 +26463,7 @@ static int zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *re zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -26127,9 +26481,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *re if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -26154,9 +26507,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *re } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -26276,25 +26628,27 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_AR { zend_op *opline = EX(opline); zend_free_op free_op1; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; - - if (IS_UNUSED == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = NULL; - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC), dim, 0, type TSRMLS_CC); + zval *dim = NULL; - if (IS_CV == IS_VAR && type == BP_VAR_W && 0 && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_CV == IS_VAR && 0 && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } } + } else { + if (IS_UNUSED == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + ZEND_VM_NEXT_OPCODE(); } @@ -26313,16 +26667,38 @@ static int ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + + zval *property_name = NULL; + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } } else { - zend_free_op free_op_data1; + zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = NULL; + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } @@ -26668,7 +27044,6 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *re zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); znode *result = &opline->result; - zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; EX_T(result->u.var).var.ptr_ptr = NULL; @@ -26681,8 +27056,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *re FREE_OP(free_op_data1); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } else { /* here we are sure we are dealing with an object */ @@ -26700,8 +27076,9 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *re have_get_ptr = 1; binary_op(*zptr, *zptr, value TSRMLS_CC); if (!RETURN_VALUE_UNUSED(result)) { - *retval = *zptr; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = *zptr; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(*zptr); } } } @@ -26743,15 +27120,17 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *re break; } if (!RETURN_VALUE_UNUSED(result)) { - *retval = z; - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = z; + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(z); } zval_ptr_dtor(&z); } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); if (!RETURN_VALUE_UNUSED(result)) { - *retval = EG(uninitialized_zval_ptr); - PZVAL_LOCK(*retval); + EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr); + EX_T(result->u.var).var.ptr_ptr = NULL; + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } } } @@ -26796,7 +27175,7 @@ static int zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC), dim, 0, BP_VAR_RW TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - var_ptr = get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW); + var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); increment_opline = 1; } } @@ -26814,9 +27193,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result if (*var_ptr == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); - PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); } @@ -26841,9 +27219,8 @@ static int zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result } if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = var_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr); PZVAL_LOCK(*var_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } if (increment_opline) { @@ -27104,7 +27481,7 @@ static int ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) EX_T(opline->op1.u.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr); } - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); @@ -27165,7 +27542,7 @@ static int ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC), dim, 0, BP_VAR_IS TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); @@ -27175,25 +27552,27 @@ static int ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); zend_free_op free_op1; - int type = ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)?BP_VAR_W:BP_VAR_R; - zval *dim; - - if (IS_CV == IS_UNUSED && type == BP_VAR_R) { - zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); - } - dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC), dim, 0, type TSRMLS_CC); + zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - if (IS_CV == IS_VAR && type == BP_VAR_W && 0 && - READY_TO_DESTROY(free_op1.var) && - !RETURN_VALUE_UNUSED(&opline->result)) { - AI_USE_PTR(EX_T(opline->result.u.var).var); - if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && - Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { - SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) { + zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC), dim, 0, BP_VAR_W TSRMLS_CC); + if (IS_CV == IS_VAR && 0 && + READY_TO_DESTROY(free_op1.var) && + !RETURN_VALUE_UNUSED(&opline->result)) { + AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) && + Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) { + SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr); + } + } + } else { + if (IS_CV == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } + zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC), dim, 0, BP_VAR_R TSRMLS_CC); } + ZEND_VM_NEXT_OPCODE(); } @@ -27244,20 +27623,13 @@ static int ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int zend_fetch_property_address_read_helper_SPEC_CV_CV(int type, ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zval *container; - zval **retval; - - retval = &EX_T(opline->result.u.var).var.ptr; - EX_T(opline->result.u.var).var.ptr_ptr = retval; - - container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); + zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC); if (container == EG(error_zval_ptr)) { if (!RETURN_VALUE_UNUSED(&opline->result)) { - *retval = EG(error_zval_ptr); - PZVAL_LOCK(*retval); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(error_zval_ptr)); + PZVAL_LOCK(EG(error_zval_ptr)); } ZEND_VM_NEXT_OPCODE(); @@ -27268,26 +27640,30 @@ static int zend_fetch_property_address_read_helper_SPEC_CV_CV(int type, ZEND_OPC if (type != BP_VAR_IS) { zend_error(E_NOTICE, "Trying to get property of non-object"); } - *retval = EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr)); + PZVAL_LOCK(EG(uninitialized_zval_ptr)); + } } else { zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval *retval; if (0) { MAKE_REAL_ZVAL_PTR(offset); } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); - if (RETURN_VALUE_UNUSED(&opline->result) && (Z_REFCOUNT_PP(retval) == 0)) { - zval_dtor(*retval); - FREE_ZVAL(*retval); + if (RETURN_VALUE_UNUSED(&opline->result)) { + if (Z_REFCOUNT_P(retval) == 0) { + zval_dtor(retval); + FREE_ZVAL(retval); + } } else { - SELECTIVE_PZVAL_LOCK(*retval, &opline->result); - AI_USE_PTR(EX_T(opline->result.u.var).var); + AI_SET_PTR(EX_T(opline->result.u.var).var, retval); + PZVAL_LOCK(retval); } if (0) { @@ -27458,8 +27834,17 @@ static int ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *op_data = opline+1; zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC); + } /* assign_obj has two opcodes! */ ZEND_VM_INC_OPCODE(); @@ -27481,16 +27866,38 @@ static int ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (object_ptr && Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zend_assign_to_object(&opline->result, object_ptr, &opline->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + + zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + + if (0) { + MAKE_REAL_ZVAL_PTR(property_name); + } + zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC); + if (0) { + zval_ptr_dtor(&property_name); + } else { + + } } else { - zend_free_op free_op_data1; + zend_free_op free_op_data1, free_op_data2; zval *value; zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC); value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R); - zend_assign_to_variable(&opline->result, &op_data->op2, &op_data->op1, value, (IS_TMP_FREE(free_op_data1)?IS_TMP_VAR:op_data->op1.op_type), EX(Ts) TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC); + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC); + } + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } + FREE_OP_VAR_PTR(free_op_data2); FREE_OP_IF_VAR(free_op_data1); } @@ -27504,8 +27911,19 @@ static int ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_op *opline = EX(opline); zval *value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC); + + if (!variable_ptr_ptr) { + zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CV TSRMLS_CC); + } else { + value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC); + } + + if (!RETURN_VALUE_UNUSED(&opline->result)) { + AI_SET_PTR(EX_T(opline->result.u.var).var, value); + PZVAL_LOCK(value); + } - zend_assign_to_variable(&opline->result, &opline->op1, &opline->op2, value, (0?IS_TMP_VAR:IS_CV), EX(Ts) TSRMLS_CC); /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE(); @@ -27537,9 +27955,8 @@ static int ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC); if (!RETURN_VALUE_UNUSED(&opline->result)) { - EX_T(opline->result.u.var).var.ptr_ptr = variable_ptr_ptr; + AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr); PZVAL_LOCK(*variable_ptr_ptr); - AI_USE_PTR(EX_T(opline->result.u.var).var); } @@ -27627,7 +28044,7 @@ static int ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) */ EX_T(opline->op1.u.var).var.ptr_ptr = NULL; - AI_USE_PTR(EX_T(opline->op1.u.var).var); + EX_T(opline->op1.u.var).var.ptr = NULL; } ZEND_VM_NEXT_OPCODE(); }