diff options
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r-- | Zend/zend_execute.c | 153 |
1 files changed, 67 insertions, 86 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 58038c94a4..61a605971e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -547,13 +547,13 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC) return object; } -ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, zend_ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC) +ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC) { zend_string *key; ALLOCA_FLAG(use_heap); STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap); - *pce = zend_fetch_class(key, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); + *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); STR_ALLOCA_FREE(key, use_heap); *class_name = (*pce) ? (*pce)->name->val : (char*)cur_arg_info->class_name; @@ -596,7 +596,7 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uin } } -static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_ulong fetch_type TSRMLS_DC) +static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg TSRMLS_DC) { zend_arg_info *cur_arg_info; char *need_msg; @@ -619,12 +619,12 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, ZVAL_DEREF(arg); if (Z_TYPE_P(arg) == IS_OBJECT) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) { zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC); } } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC); } } else if (cur_arg_info->type_hint) { @@ -645,7 +645,7 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, } } -static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, zend_ulong fetch_type TSRMLS_DC) +static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num TSRMLS_DC) { zend_arg_info *cur_arg_info; char *need_msg; @@ -666,7 +666,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n if (cur_arg_info->class_name) { char *class_name; - need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC); return 0; } else if (cur_arg_info->type_hint) { @@ -687,7 +687,7 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num TSRMLS_DC) { if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) || - zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) { + zend_verify_missing_arg_type(EX(func), arg_num TSRMLS_CC)) { const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : ""; const char *space = EX(func)->common.scope ? "::" : ""; const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main"; @@ -1048,12 +1048,61 @@ str_index: return retval; } -static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC) +static zend_never_inline zend_long zend_check_string_offset(zval *container, zval *dim, int type TSRMLS_DC) +{ + zend_long offset; + + if (dim == NULL) { + zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); + } + + if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { + switch(Z_TYPE_P(dim)) { + case IS_STRING: + if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) { + break; + } + if (type != BP_VAR_UNSET) { + zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim)); + } + break; + case IS_DOUBLE: + case IS_NULL: + case IS_FALSE: + case IS_TRUE: + zend_error(E_NOTICE, "String offset cast occurred"); + break; + default: + zend_error(E_WARNING, "Illegal offset type"); + break; + } + + offset = zval_get_long(dim); + } else { + offset = Z_LVAL_P(dim); + } + + return offset; +} + +static zend_always_inline zend_long zend_fetch_string_offset(zval *container, zval *dim, int type TSRMLS_DC) +{ + zend_long offset = zend_check_string_offset(container, dim, type TSRMLS_CC); + + if (Z_REFCOUNTED_P(container)) { + if (Z_REFCOUNT_P(container) > 1) { + Z_DELREF_P(container); + zval_copy_ctor_func(container); + } + Z_ADDREF_P(container); + } + return offset; +} + +static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC) { zval *retval; - zval *container = container_ptr; - ZVAL_DEREF(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { SEPARATE_ARRAY(container); fetch_from_array: @@ -1066,13 +1115,8 @@ fetch_from_array: } else { retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC); } - if (is_ref) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(result, retval); } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { - zend_long offset; - if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) { zval_ptr_dtor_nogc(container); convert_to_array: @@ -1081,49 +1125,9 @@ convert_to_array: goto fetch_from_array; } - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - - if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { - switch(Z_TYPE_P(dim)) { - case IS_STRING: - if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) { - break; - } - if (type != BP_VAR_UNSET) { - zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim)); - } - break; - case IS_DOUBLE: - case IS_NULL: - case IS_FALSE: - case IS_TRUE: - zend_error(E_NOTICE, "String offset cast occurred"); - break; - default: - zend_error(E_WARNING, "Illegal offset type"); - break; - } - - offset = zval_get_long(dim); - } else { - offset = Z_LVAL_P(dim); - } - - if (allow_str_offset) { - if (Z_REFCOUNTED_P(container)) { - if (Z_REFCOUNT_P(container) > 1) { - Z_DELREF_P(container); - zval_copy_ctor_func(container); - } - Z_ADDREF_P(container); - } - ZVAL_LONG(result, offset); - return container; /* assignment to string offset */ - } else { - ZVAL_INDIRECT(result, NULL); /* wrong string offset */ - } + zend_check_string_offset(container, dim, type TSRMLS_CC); + + ZVAL_INDIRECT(result, NULL); /* wrong string offset */ } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (!Z_OBJ_HT_P(container)->read_dimension) { zend_error_noreturn(E_ERROR, "Cannot use object as array"); @@ -1154,9 +1158,6 @@ convert_to_array: } } if (result != retval) { - if (is_ref) { - ZVAL_MAKE_REF(retval); - } ZVAL_INDIRECT(result, retval); } } else { @@ -1185,32 +1186,21 @@ convert_to_array: ZVAL_INDIRECT(result, &EG(error_zval)); } } - return NULL; /* not an assignment to string offset */ } static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC); -} - -static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) -{ - return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC); -} - -static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) -{ - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW TSRMLS_CC); } static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC) { - zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC); + zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET TSRMLS_CC); } static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC) @@ -1302,7 +1292,7 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval * zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR TSRMLS_CC); } -static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, void **cache_slot, int type, int is_ref TSRMLS_DC) +static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, void **cache_slot, int type TSRMLS_DC) { if (container_op_type != IS_UNUSED) { ZVAL_DEREF(container); @@ -1332,26 +1322,17 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c if (Z_OBJ_HT_P(container)->read_property && (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC)) != NULL) { if (ptr != result) { - if (is_ref && ptr != &EG(uninitialized_zval)) { - ZVAL_MAKE_REF(ptr); - } ZVAL_INDIRECT(result, ptr); } } else { zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access"); } } else { - if (is_ref) { - ZVAL_MAKE_REF(ptr); - } ZVAL_INDIRECT(result, ptr); } } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) { zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC); if (ptr != result) { - if (is_ref && ptr != &EG(uninitialized_zval)) { - ZVAL_MAKE_REF(ptr); - } ZVAL_INDIRECT(result, ptr); } } else { |