summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c242
1 files changed, 77 insertions, 165 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 3ad663445b..ad788aff44 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -607,25 +607,6 @@ static inline int make_real_object(zval *object)
return 1;
}
-static zend_class_entry *zend_verify_internal_arg_class_kind(
- const zend_internal_arg_info *cur_arg_info)
-{
- zend_string *key;
- zend_class_entry *ce;
- ALLOCA_FLAG(use_heap);
-
- ZSTR_ALLOCA_INIT(key, cur_arg_info->class_name, strlen(cur_arg_info->class_name), use_heap);
- ce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
- ZSTR_ALLOCA_FREE(key, use_heap);
-
- return ce;
-}
-
-static zend_always_inline zend_class_entry* zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info)
-{
- return zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
-}
-
static ZEND_COLD void zend_verify_type_error_common(
const zend_function *zf, const zend_arg_info *arg_info,
const zend_class_entry *ce, zval *value,
@@ -644,46 +625,46 @@ static ZEND_COLD void zend_verify_type_error_common(
*fclass = "";
}
- switch (arg_info->type_hint) {
- case IS_OBJECT:
- if (ce) {
- if (ce->ce_flags & ZEND_ACC_INTERFACE) {
- *need_msg = "implement interface ";
- is_interface = 1;
- } else {
- *need_msg = "be an instance of ";
- }
- *need_kind = ZSTR_VAL(ce->name);
+ if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
+ if (ce) {
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ *need_msg = "implement interface ";
+ is_interface = 1;
} else {
- /* We don't know whether it's a class or interface, assume it's a class */
*need_msg = "be an instance of ";
- *need_kind = zf->common.type == ZEND_INTERNAL_FUNCTION
- ? ((zend_internal_arg_info *) arg_info)->class_name
- : ZSTR_VAL(arg_info->class_name);
}
- break;
- case IS_CALLABLE:
- *need_msg = "be callable";
- *need_kind = "";
- break;
- case IS_ITERABLE:
- *need_msg = "be iterable";
- *need_kind = "";
- break;
- default:
- *need_msg = "be of the type ";
- *need_kind = zend_get_type_by_const(arg_info->type_hint);
- break;
+ *need_kind = ZSTR_VAL(ce->name);
+ } else {
+ /* We don't know whether it's a class or interface, assume it's a class */
+
+ *need_msg = "be an instance of ";
+ *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type));
+ }
+ } else {
+ switch (ZEND_TYPE_CODE(arg_info->type)) {
+ case IS_CALLABLE:
+ *need_msg = "be callable";
+ *need_kind = "";
+ break;
+ case IS_ITERABLE:
+ *need_msg = "be iterable";
+ *need_kind = "";
+ break;
+ default:
+ *need_msg = "be of the type ";
+ *need_kind = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type));
+ break;
+ }
}
- if (arg_info->allow_null) {
+ if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
*need_or_null = is_interface ? " or be null" : " or null";
} else {
*need_or_null = "";
}
if (value) {
- if (arg_info->type_hint == IS_OBJECT && Z_TYPE_P(value) == IS_OBJECT) {
+ if (ZEND_TYPE_IS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) {
*given_msg = "instance of ";
*given_kind = ZSTR_VAL(Z_OBJCE_P(value)->name);
} else {
@@ -803,137 +784,48 @@ static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, z
return zend_verify_weak_scalar_type_hint(type_hint, arg);
}
-static zend_always_inline zend_bool zend_check_internal_type(
- const zend_function *zf, const zend_internal_arg_info *arg_info,
- zval *arg, zend_class_entry **ce, zend_bool is_return_type)
-{
- if (!arg_info->type_hint) {
- return 1;
- }
-
- ZVAL_DEREF(arg);
- if (EXPECTED(arg_info->type_hint == Z_TYPE_P(arg))) {
- if (arg_info->class_name) {
- *ce = zend_verify_internal_arg_class_kind(arg_info);
- return *ce && instanceof_function(Z_OBJCE_P(arg), *ce);
- }
- return 1;
- }
-
- if (Z_TYPE_P(arg) == IS_NULL && arg_info->allow_null) {
- return 1;
- }
-
- if (arg_info->class_name) {
- *ce = zend_verify_internal_arg_class_kind(arg_info);
- return 0;
- } else if (arg_info->type_hint == IS_CALLABLE) {
- return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL);
- } else if (arg_info->type_hint == IS_ITERABLE) {
- return zend_is_iterable(arg);
- } else if (arg_info->type_hint == _IS_BOOL &&
- EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
- return 1;
- } else if (is_return_type) {
- /* Internal return types are always strict */
- return 0;
- } else {
- /* Internal parameter types honor strict_types */
- return zend_verify_scalar_type_hint(arg_info->type_hint, arg, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)));
- }
-}
-
-static int zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
-{
- const zend_internal_arg_info *cur_arg_info;
- zend_class_entry *ce = NULL;
-
- if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
- cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
- } else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
- cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args];
- } else {
- return 1;
- }
-
- if (UNEXPECTED(!zend_check_internal_type(zf, cur_arg_info, arg, &ce, 0))) {
- zend_verify_arg_error(zf, (const zend_arg_info *) cur_arg_info, arg_num, ce, arg);
- return 0;
- }
-
- return 1;
-}
-
-static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
-{
- uint32_t i;
- uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
- zval *p = ZEND_CALL_ARG(call, 1);
-
- for (i = 0; i < num_args; ++i) {
- if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) {
- EG(current_execute_data) = call->prev_execute_data;
- zend_vm_stack_free_args(call);
- return 0;
- }
- p++;
- }
- return 1;
-}
-
static zend_always_inline zend_bool zend_check_type(
- const zend_function *zf, const zend_arg_info *arg_info,
+ zend_type type,
zval *arg, zend_class_entry **ce, void **cache_slot,
- zval *default_value, zend_bool is_return_type)
+ zval *default_value, zend_class_entry *scope,
+ zend_bool is_return_type)
{
- if (!arg_info->type_hint) {
+ if (!ZEND_TYPE_IS_SET(type)) {
return 1;
}
ZVAL_DEREF(arg);
- if (EXPECTED(arg_info->type_hint == Z_TYPE_P(arg))) {
- if (arg_info->class_name) {
- if (EXPECTED(*cache_slot)) {
- *ce = (zend_class_entry *) *cache_slot;
- } else {
- *ce = zend_verify_arg_class_kind(arg_info);
- if (UNEXPECTED(!*ce)) {
- return 0;
- }
- *cache_slot = (void *) *ce;
- }
- if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(arg), *ce))) {
+ if (ZEND_TYPE_IS_CLASS(type)) {
+ if (EXPECTED(*cache_slot)) {
+ *ce = (zend_class_entry *) *cache_slot;
+ } else {
+ *ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
+ if (UNEXPECTED(!*ce)) {
return 0;
}
+ *cache_slot = (void *) *ce;
+ }
+ if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
+ return instanceof_function(Z_OBJCE_P(arg), *ce);
}
+ } else if (EXPECTED(ZEND_TYPE_CODE(type) == Z_TYPE_P(arg))) {
return 1;
}
- if (Z_TYPE_P(arg) == IS_NULL && (arg_info->allow_null || (default_value && is_null_constant(zf->common.scope, default_value)))) {
+ if (Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)))) {
/* Null passed to nullable type */
return 1;
}
- if (UNEXPECTED(arg_info->class_name)) {
- /* This is always an error - we fetch the class name for the error message here */
- if (EXPECTED(*cache_slot)) {
- *ce = (zend_class_entry *) *cache_slot;
- } else {
- *ce = zend_verify_arg_class_kind(arg_info);
- if (*ce) {
- *cache_slot = (void *) *ce;
- }
- }
- return 0;
- } else if (arg_info->type_hint == IS_CALLABLE) {
+ if (ZEND_TYPE_CODE(type) == IS_CALLABLE) {
return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL);
- } else if (arg_info->type_hint == IS_ITERABLE) {
+ } else if (ZEND_TYPE_CODE(type) == IS_ITERABLE) {
return zend_is_iterable(arg);
- } else if (arg_info->type_hint == _IS_BOOL &&
+ } else if (ZEND_TYPE_CODE(type) == _IS_BOOL &&
EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
return 1;
} else {
- return zend_verify_scalar_type_hint(arg_info->type_hint, arg,
+ return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(type), arg,
is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES());
}
@@ -954,7 +846,7 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a
return 1;
}
- if (UNEXPECTED(!zend_check_type(zf, cur_arg_info, arg, &ce, cache_slot, default_value, 0))) {
+ if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) {
zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg);
return 0;
}
@@ -962,6 +854,25 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a
return 1;
}
+static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
+{
+ uint32_t i;
+ uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
+ zval *p = ZEND_CALL_ARG(call, 1);
+ void *dummy_cache_slot;
+
+ for (i = 0; i < num_args; ++i) {
+ dummy_cache_slot = NULL;
+ if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot))) {
+ EG(current_execute_data) = call->prev_execute_data;
+ zend_vm_stack_free_args(call);
+ return 0;
+ }
+ p++;
+ }
+ return 1;
+}
+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
{
zend_execute_data *ptr = EX(prev_execute_data);
@@ -1040,13 +951,14 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
{
zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
zend_class_entry *ce = NULL;
+ void *dummy_cache_slot = NULL;
- if (UNEXPECTED(ret_info->type_hint == IS_VOID && Z_TYPE_P(ret) != IS_NULL)) {
+ if (UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) == IS_VOID && Z_TYPE_P(ret) != IS_NULL)) {
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
return 0;
}
- if (UNEXPECTED(!zend_check_internal_type(zf, ret_info, ret, &ce, 1))) {
+ if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, &dummy_cache_slot, NULL, NULL, 1))) {
zend_verify_internal_return_error(zf, ce, ret);
return 0;
}
@@ -1060,7 +972,7 @@ static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *
zend_arg_info *ret_info = zf->common.arg_info - 1;
zend_class_entry *ce = NULL;
- if (UNEXPECTED(!zend_check_type(zf, ret_info, ret, &ce, cache_slot, NULL, 1))) {
+ if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, cache_slot, NULL, NULL, 1))) {
zend_verify_return_error(zf, ce, ret);
}
}
@@ -1069,13 +981,13 @@ static ZEND_COLD int zend_verify_missing_return_type(zend_function *zf, void **c
{
zend_arg_info *ret_info = zf->common.arg_info - 1;
- if (ret_info->type_hint && UNEXPECTED(ret_info->type_hint != IS_VOID)) {
+ if (ZEND_TYPE_IS_SET(ret_info->type) && UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) != IS_VOID)) {
zend_class_entry *ce = NULL;
- if (ret_info->class_name) {
+ if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
if (EXPECTED(*cache_slot)) {
ce = (zend_class_entry*) *cache_slot;
} else {
- ce = zend_verify_arg_class_kind(ret_info);
+ ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
if (ce) {
*cache_slot = (void*)ce;
}
@@ -3072,7 +2984,7 @@ ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_e
ZEND_API void ZEND_FASTCALL zend_check_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
{
- zend_verify_internal_arg_type(zf, arg_num, arg);
+ zend_verify_arg_type(zf, arg_num, arg, NULL, NULL);
}
ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)