diff options
-rw-r--r-- | Zend/zend_API.c | 10 | ||||
-rw-r--r-- | Zend/zend_API.h | 2 | ||||
-rw-r--r-- | Zend/zend_compile.h | 16 | ||||
-rw-r--r-- | Zend/zend_execute.c | 230 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 75 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 197 |
6 files changed, 280 insertions, 250 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 1ef695dd4e..c626a8ddd7 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -151,7 +151,7 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) / ZEND_API void zend_wrong_param_count(void) /* {{{ */ { - if (EX_PREV_USES_STRICT_TYPES()) { + if (ZEND_ARG_USES_STRICT_TYPES()) { zend_wrong_param_count_ex(1); } else { zend_wrong_param_count_ex(0); @@ -802,7 +802,7 @@ ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_ va_list va; int retval; - if (EX_PREV_USES_STRICT_TYPES()) { + if (ZEND_ARG_USES_STRICT_TYPES()) { flags |= ZEND_PARSE_PARAMS_STRICT; } @@ -822,7 +822,7 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /* int retval; int flags = 0; - if (EX_PREV_USES_STRICT_TYPES()) { + if (ZEND_ARG_USES_STRICT_TYPES()) { flags |= ZEND_PARSE_PARAMS_STRICT; } @@ -851,7 +851,7 @@ ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const ch * wrong branch here. */ zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL; - if (EX_PREV_USES_STRICT_TYPES()) { + if (ZEND_ARG_USES_STRICT_TYPES()) { flags |= ZEND_PARSE_PARAMS_STRICT; } @@ -891,7 +891,7 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this zval **object; zend_class_entry *ce; - if (EX_PREV_USES_STRICT_TYPES()) { + if (ZEND_ARG_USES_STRICT_TYPES()) { flags |= ZEND_PARSE_PARAMS_STRICT; } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index e0f39e98a2..4da7002477 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -720,7 +720,7 @@ ZEND_API void zend_wrong_callback_error(int severity, int num, char *error, zend #define ZPP_ERROR_WRONG_COUNT 5 #define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \ - zend_bool _strict = EX_PREV_USES_STRICT_TYPES(); \ + zend_bool _strict = ZEND_ARG_USES_STRICT_TYPES(); \ const int _flags = (flags) | (_strict ? ZEND_PARSE_PARAMS_STRICT : 0); \ int _min_num_args = (min_num_args); \ int _max_num_args = (max_num_args); \ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index cedd5d6808..c53833f149 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -462,9 +462,19 @@ struct _zend_execute_data { #define EX_CALL_KIND() ZEND_CALL_KIND(execute_data) #define EX_NUM_ARGS() ZEND_CALL_NUM_ARGS(execute_data) -#define EX_USES_STRICT_TYPES() _EX_USES_STRICT_TYPES(EG(current_execute_data)) -#define EX_PREV_USES_STRICT_TYPES() _EX_USES_STRICT_TYPES(EG(current_execute_data)->prev_execute_data) -#define _EX_USES_STRICT_TYPES(ex_data) ((ex_data) && (ex_data)->func && ZEND_USER_CODE((ex_data)->func->type) && ((ex_data)->func->op_array.fn_flags & ZEND_ACC_STRICT_TYPES) ? 1 : 0) +#define ZEND_CALL_USES_STRICT_TYPES(call) \ + (((call)->func->common.fn_flags & ZEND_ACC_STRICT_TYPES) != 0) + +#define EX_USES_STRICT_TYPES() \ + ZEND_CALL_USES_STRICT_TYPES(execute_data) + +#define ZEND_ARG_USES_STRICT_TYPES() \ + (EG(current_execute_data)->prev_execute_data && \ + EG(current_execute_data)->prev_execute_data->func && \ + ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)->prev_execute_data)) + +#define ZEND_RET_USES_STRICT_TYPES() \ + ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)) #define EX_VAR(n) ZEND_CALL_VAR(execute_data, n) #define EX_VAR_NUM(n) ZEND_CALL_VAR_NUM(execute_data, n) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 699c1ca3de..b98d7cec47 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -651,8 +651,10 @@ static int is_null_constant(zval *default_value) return 0; } -static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict) +static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg) { + zend_bool strict = 0; + switch (type_hint) { case _IS_BOOL: { zend_bool dest; @@ -698,24 +700,24 @@ static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, z } } -static inline int zend_verify_scalar_type_error(zend_uchar type_hint, zend_uchar allow_null, zval *arg, zval *default_value, zend_bool strict) +static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict) { - if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(type_hint, Z_TYPE_P(arg)))) { - if (Z_TYPE_P(arg) == IS_NULL) { - if (!allow_null && (!default_value || !is_null_constant(default_value))) { - return 1; - } - } else if (!zend_verify_scalar_type_hint(type_hint, arg, strict)) { - return 1; + if (UNEXPECTED(strict)) { + /* SSTH Exception: IS_LONG ma be accepted instead as IS_DOUBLE */ + if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) { + return 0; } + } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) { + /* FIXME: Is this exception on purpose ??? */ + return 0; } - return 0; + return zend_verify_weak_scalar_type_hint(type_hint, arg); } -static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_bool strict) +static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg) { zend_internal_arg_info *cur_arg_info; - char *need_msg; + char *need_msg, *class_name; zend_class_entry *ce; if (EXPECTED(arg_num <= zf->internal_function.num_args)) { @@ -726,39 +728,37 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z return; } - if (cur_arg_info->class_name) { - char *class_name; - + if (cur_arg_info->type_hint) { ZVAL_DEREF(arg); - if (Z_TYPE_P(arg) == IS_OBJECT) { - need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); - if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { - zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) { + if (cur_arg_info->class_name) { + need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); + if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { + zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + } } } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { - need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); - zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); - } - } else if (cur_arg_info->type_hint) { - ZVAL_DEREF(arg); - if (cur_arg_info->type_hint == IS_ARRAY) { - if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); - } - } else if (cur_arg_info->type_hint == IS_CALLABLE) { - if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + if (cur_arg_info->class_name) { + need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + } else if (cur_arg_info->type_hint == IS_CALLABLE) { + if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) { + zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + } + } else if (cur_arg_info->type_hint == _IS_BOOL && + EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) { + /* pass */ + } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) { + zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg); } - } else if (UNEXPECTED(zend_verify_scalar_type_error(cur_arg_info->type_hint, cur_arg_info->allow_null, arg, NULL, strict))) { - zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg); } } } -static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, zend_bool strict) +static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value) { zend_arg_info *cur_arg_info; - char *need_msg; + char *need_msg, *class_name; zend_class_entry *ce; if (EXPECTED(arg_num <= zf->common.num_args)) { @@ -769,31 +769,29 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, return; } - if (cur_arg_info->class_name) { - char *class_name; - + if (cur_arg_info->type_hint) { ZVAL_DEREF(arg); - if (Z_TYPE_P(arg) == IS_OBJECT) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { - zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) { + if (cur_arg_info->class_name) { + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); + if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { + zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + } } } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) { - need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); - } - } else if (cur_arg_info->type_hint) { - ZVAL_DEREF(arg); - if (cur_arg_info->type_hint == IS_ARRAY) { - if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) { - zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); - } - } else if (cur_arg_info->type_hint == IS_CALLABLE) { - if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) { - zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + if (cur_arg_info->class_name) { + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + } else if (cur_arg_info->type_hint == IS_CALLABLE) { + if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) { + zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + } + } else if (cur_arg_info->type_hint == _IS_BOOL && + EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) { + /* pass */ + } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_ARG_USES_STRICT_TYPES()))) { + zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg); } - } else if (UNEXPECTED(zend_verify_scalar_type_error(cur_arg_info->type_hint, cur_arg_info->allow_null, arg, default_value, strict))) { - zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg); } } } @@ -812,15 +810,13 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n return 1; } - if (cur_arg_info->class_name) { - char *class_name; + if (cur_arg_info->type_hint) { + if (cur_arg_info->class_name) { + char *class_name; - need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL); - return 0; - } else if (cur_arg_info->type_hint) { - if (cur_arg_info->type_hint == IS_ARRAY) { - zend_verify_arg_error(zf, arg_num, "be of the type array", "", "none", "", NULL); + need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL); + return 0; } else if (cur_arg_info->type_hint == IS_CALLABLE) { zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL); } else { @@ -891,75 +887,73 @@ ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const c } #if ZEND_DEBUG -static int zend_verify_internal_return_type(zend_function *zf, zval *ret, zend_bool strict) +static int zend_verify_internal_return_type(zend_function *zf, zval *ret) { zend_arg_info *ret_info = zf->common.arg_info - 1; - char *need_msg; + char *need_msg, *class_name; zend_class_entry *ce; - if (ret_info->class_name) { - char *class_name; - if (Z_TYPE_P(ret) == IS_OBJECT) { - need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce); - if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { - zend_verify_internal_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); - return 0; + if (ret_info->type_hint) { + if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) { + if (ret_info->class_name) { + need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce); + if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { + zend_verify_internal_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + return 0; + } } } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) { - need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce); - zend_verify_internal_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); - return 0; - } - } else if (ret_info->type_hint) { - if (ret_info->type_hint == IS_ARRAY) { - if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { - zend_verify_internal_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), ""); - return 0; - } - } else if (ret_info->type_hint == IS_CALLABLE) { - if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { - zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); + if (ret_info->class_name) { + need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce); + zend_verify_internal_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); + } else if (ret_info->type_hint == IS_CALLABLE) { + if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { + zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); + return 0; + } + } else if (ret_info->type_hint == _IS_BOOL && + EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) { + /* pass */ + } else { + /* Use strict check to verify return value of internal function */ + zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); return 0; } - } else if (UNEXPECTED(zend_verify_scalar_type_error(ret_info->type_hint, ret_info->allow_null, ret, NULL, strict))) { - zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); - return 0; } } return 1; } #endif -static void zend_verify_return_type(zend_function *zf, zval *ret, zend_bool strict) +static void zend_verify_return_type(zend_function *zf, zval *ret) { zend_arg_info *ret_info = zf->common.arg_info - 1; - char *need_msg; + char *need_msg, *class_name; zend_class_entry *ce; - if (ret_info->class_name) { - char *class_name; - - if (Z_TYPE_P(ret) == IS_OBJECT) { - need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { - zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + if (ret_info->type_hint) { + if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) { + if (ret_info->class_name) { + need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); + if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { + zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + } } } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) { - need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); - } - } else if (ret_info->type_hint) { - if (ret_info->type_hint == IS_ARRAY) { - if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { - zend_verify_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), ""); - } - } else if (ret_info->type_hint == IS_CALLABLE) { - if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) { - zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); + if (ret_info->class_name) { + need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); + zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); + } else if (ret_info->type_hint == IS_CALLABLE) { + if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL)) { + zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); + } + } else if (ret_info->type_hint == _IS_BOOL && + EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) { + /* pass */ + } else if (UNEXPECTED(!zend_verify_scalar_type_hint(ret_info->type_hint, ret, ZEND_RET_USES_STRICT_TYPES()))) { + zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); } - } else if (UNEXPECTED(zend_verify_scalar_type_error(ret_info->type_hint, ret_info->allow_null, ret, NULL, strict))) { - zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); } } } @@ -970,15 +964,13 @@ static inline int zend_verify_missing_return_type(zend_function *zf) char *need_msg; zend_class_entry *ce; - if (ret_info->class_name) { - char *class_name; + if (ret_info->type_hint) { + if (ret_info->class_name) { + char *class_name; - need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(zf, need_msg, class_name, "none", ""); - return 0; - } else if (ret_info->type_hint) { - if (ret_info->type_hint == IS_ARRAY) { - zend_verify_return_error(zf, "be of the type array", "", "none", ""); + need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); + zend_verify_return_error(zf, need_msg, class_name, "none", ""); + return 0; } else if (ret_info->type_hint == IS_CALLABLE) { zend_verify_return_error(zf, "be callable", "", "none", ""); } else { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2cc3588606..fd586e79cb 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3232,7 +3232,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES())); + zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3339,7 +3339,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < num_args; ++i) { - zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES()); + zend_verify_internal_arg_type(fbc, i + 1, p); p++; } if (UNEXPECTED(EG(exception) != NULL)) { @@ -3360,7 +3360,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES())); + zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3465,7 +3465,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < num_args; ++i) { - zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES()); + zend_verify_internal_arg_type(fbc, i + 1, p); if (UNEXPECTED(EG(exception) != NULL)) { EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3497,7 +3497,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES())); + zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3615,7 +3615,7 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED) } } - zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES()); + zend_verify_return_type(EX(func), retval_ptr); #endif } CHECK_EXCEPTION(); @@ -4387,7 +4387,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var); - zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_PREV_USES_STRICT_TYPES()); + zend_verify_arg_type(EX(func), arg_num, param, NULL); CHECK_EXCEPTION(); } @@ -4415,7 +4415,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_PREV_USES_STRICT_TYPES()); + zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2)); } CHECK_EXCEPTION(); @@ -4442,7 +4442,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_USES_STRICT_TYPES()); + zend_verify_arg_type(EX(func), arg_num, param, NULL); if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; @@ -7268,35 +7268,42 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY) ZEND_VM_C_LABEL(try_strlen): if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else if (EXPECTED(!EX_USES_STRICT_TYPES())) { + } else { + zend_bool strict; + if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); ZEND_VM_C_GOTO(try_strlen); - } else if (Z_TYPE_P(value) < IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 0); - } else if (Z_TYPE_P(value) == IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 1); - } else if (Z_TYPE_P(value) <= IS_DOUBLE) { - zend_string *str = zval_get_string(value); - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); - } else if (Z_TYPE_P(value) == IS_OBJECT) { - zend_string *str; - zval tmp; - - ZVAL_COPY(&tmp, value); - if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) { - ZEND_VM_C_GOTO(strlen_error); - } - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zval_dtor(&tmp); - } else { -ZEND_VM_C_LABEL(strlen_error): - zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); } - } else { - zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + if (Z_TYPE_P(value) < IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 0); + break; + } else if (Z_TYPE_P(value) == IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 1); + break; + } else if (Z_TYPE_P(value) <= IS_DOUBLE) { + zend_string *str = zval_get_string(value); + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zend_string_release(str); + break; + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_string *str; + zval tmp; + + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) { + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zval_dtor(&tmp); + break; + } + } + } + zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_NULL(EX_VAR(opline->result.var)); + } while (0); } FREE_OP1(); CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2ee2cf4d53..ebc21017ac 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -563,7 +563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES())); + zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -670,7 +670,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < num_args; ++i) { - zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES()); + zend_verify_internal_arg_type(fbc, i + 1, p); p++; } if (UNEXPECTED(EG(exception) != NULL)) { @@ -691,7 +691,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES())); + zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -796,7 +796,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC zval *p = ZEND_CALL_ARG(call, 1); for (i = 0; i < num_args; ++i) { - zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES()); + zend_verify_internal_arg_type(fbc, i + 1, p); if (UNEXPECTED(EG(exception) != NULL)) { EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -828,7 +828,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES())); + zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -1218,7 +1218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_ } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var); - zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_PREV_USES_STRICT_TYPES()); + zend_verify_arg_type(EX(func), arg_num, param, NULL); CHECK_EXCEPTION(); } @@ -1245,7 +1245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEN param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { do { - zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_USES_STRICT_TYPES()); + zend_verify_arg_type(EX(func), arg_num, param, NULL); if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); ZEND_HASH_FILL_ADD(param); param++; @@ -2078,7 +2078,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z } if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { - zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_PREV_USES_STRICT_TYPES()); + zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2)); } CHECK_EXCEPTION(); @@ -3809,35 +3809,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else if (EXPECTED(!EX_USES_STRICT_TYPES())) { + } else { + zend_bool strict; + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; - } else if (Z_TYPE_P(value) < IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 0); - } else if (Z_TYPE_P(value) == IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 1); - } else if (Z_TYPE_P(value) <= IS_DOUBLE) { - zend_string *str = zval_get_string(value); - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); - } else if (Z_TYPE_P(value) == IS_OBJECT) { - zend_string *str; - zval tmp; - - ZVAL_COPY(&tmp, value); - if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) { - goto strlen_error; - } - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zval_dtor(&tmp); - } else { -strlen_error: - zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); } - } else { - zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + if (Z_TYPE_P(value) < IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 0); + break; + } else if (Z_TYPE_P(value) == IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 1); + break; + } else if (Z_TYPE_P(value) <= IS_DOUBLE) { + zend_string *str = zval_get_string(value); + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zend_string_release(str); + break; + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_string *str; + zval tmp; + + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) { + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zval_dtor(&tmp); + break; + } + } + } + zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_NULL(EX_VAR(opline->result.var)); + } while (0); } CHECK_EXCEPTION(); @@ -6988,7 +6995,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_ } } - zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES()); + zend_verify_return_type(EX(func), retval_ptr); #endif } CHECK_EXCEPTION(); @@ -11949,7 +11956,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } } - zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES()); + zend_verify_return_type(EX(func), retval_ptr); #endif } CHECK_EXCEPTION(); @@ -17310,7 +17317,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } } - zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES()); + zend_verify_return_type(EX(func), retval_ptr); #endif } CHECK_EXCEPTION(); @@ -22928,7 +22935,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } } - zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES()); + zend_verify_return_type(EX(func), retval_ptr); #endif } CHECK_EXCEPTION(); @@ -27324,35 +27331,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else if (EXPECTED(!EX_USES_STRICT_TYPES())) { + } else { + zend_bool strict; + if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; - } else if (Z_TYPE_P(value) < IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 0); - } else if (Z_TYPE_P(value) == IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 1); - } else if (Z_TYPE_P(value) <= IS_DOUBLE) { - zend_string *str = zval_get_string(value); - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); - } else if (Z_TYPE_P(value) == IS_OBJECT) { - zend_string *str; - zval tmp; - - ZVAL_COPY(&tmp, value); - if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) { - goto strlen_error; - } - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zval_dtor(&tmp); - } else { -strlen_error: - zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); } - } else { - zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + if (Z_TYPE_P(value) < IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 0); + break; + } else if (Z_TYPE_P(value) == IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 1); + break; + } else if (Z_TYPE_P(value) <= IS_DOUBLE) { + zend_string *str = zval_get_string(value); + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zend_string_release(str); + break; + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_string *str; + zval tmp; + + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) { + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zval_dtor(&tmp); + break; + } + } + } + zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_NULL(EX_VAR(opline->result.var)); + } while (0); } CHECK_EXCEPTION(); @@ -31875,7 +31889,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } } - zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES()); + zend_verify_return_type(EX(func), retval_ptr); #endif } CHECK_EXCEPTION(); @@ -37592,35 +37606,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN try_strlen: if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); - } else if (EXPECTED(!EX_USES_STRICT_TYPES())) { + } else { + zend_bool strict; + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); goto try_strlen; - } else if (Z_TYPE_P(value) < IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 0); - } else if (Z_TYPE_P(value) == IS_TRUE) { - ZVAL_LONG(EX_VAR(opline->result.var), 1); - } else if (Z_TYPE_P(value) <= IS_DOUBLE) { - zend_string *str = zval_get_string(value); - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zend_string_release(str); - } else if (Z_TYPE_P(value) == IS_OBJECT) { - zend_string *str; - zval tmp; - - ZVAL_COPY(&tmp, value); - if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) { - goto strlen_error; - } - ZVAL_LONG(EX_VAR(opline->result.var), str->len); - zval_dtor(&tmp); - } else { -strlen_error: - zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); - ZVAL_NULL(EX_VAR(opline->result.var)); } - } else { - zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + if (Z_TYPE_P(value) < IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 0); + break; + } else if (Z_TYPE_P(value) == IS_TRUE) { + ZVAL_LONG(EX_VAR(opline->result.var), 1); + break; + } else if (Z_TYPE_P(value) <= IS_DOUBLE) { + zend_string *str = zval_get_string(value); + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zend_string_release(str); + break; + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_string *str; + zval tmp; + + ZVAL_COPY(&tmp, value); + if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) { + ZVAL_LONG(EX_VAR(opline->result.var), str->len); + zval_dtor(&tmp); + break; + } + } + } + zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value))); + ZVAL_NULL(EX_VAR(opline->result.var)); + } while (0); } zval_ptr_dtor_nogc(free_op1); CHECK_EXCEPTION(); |