X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmetadata%2Fclass.c;h=c927d3fb8bc2147d8c83c4470e60249909342a6f;hb=933948b3a4a8c4be9d274d433f489be67f4dcd33;hp=abe75cd9ecebd06b9aa51879525b310ea24791e9;hpb=1f47dbf018022996c5bf5d8c914b73c46d2f7672;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index abe75cd9ece..c927d3fb8bc 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -18,7 +18,6 @@ #endif #include #include -#include #include #include #include @@ -31,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -186,6 +187,13 @@ _mono_type_get_assembly_name (MonoClass *klass, GString *str) ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null"); } +static inline void +mono_type_name_check_byref (MonoType *type, GString *str) +{ + if (type->byref) + g_string_append_c (str, '&'); +} + static void mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, MonoTypeNameFormat format) @@ -208,6 +216,9 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, for (i = 1; i < rank; i++) g_string_append_c (str, ','); g_string_append_c (str, ']'); + + mono_type_name_check_byref (type, str); + if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) _mono_type_get_assembly_name (type->data.array->eklass, str); break; @@ -221,6 +232,9 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, mono_type_get_name_recurse ( &type->data.klass->byval_arg, str, FALSE, nested_format); g_string_append (str, "[]"); + + mono_type_name_check_byref (type, str); + if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) _mono_type_get_assembly_name (type->data.klass, str); break; @@ -234,6 +248,9 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, mono_type_get_name_recurse ( type->data.type, str, FALSE, nested_format); g_string_append_c (str, '*'); + + mono_type_name_check_byref (type, str); + if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str); break; @@ -242,6 +259,9 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, case MONO_TYPE_MVAR: g_assert (type->data.generic_param->name); g_string_append (str, type->data.generic_param->name); + + mono_type_name_check_byref (type, str); + break; default: klass = mono_class_from_mono_type (type); @@ -314,6 +334,9 @@ mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed, else g_string_append_c (str, ']'); } + + mono_type_name_check_byref (type, str); + if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) && (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) _mono_type_get_assembly_name (klass, str); @@ -349,9 +372,6 @@ mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format) mono_type_get_name_recurse (type, result, FALSE, format); - if (type->byref) - g_string_append_c (result, '&'); - return g_string_free (result, FALSE); } @@ -1181,15 +1201,18 @@ mono_class_layout_fields (MonoClass *class) break; } +#if NO_UNALIGNED_ACCESS if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) { /* * For small structs, set min_align to at least the struct size, since the * JIT memset/memcpy code assumes this and generates unaligned accesses * otherwise. See #78990 for a testcase. + * FIXME: Fix the memset/memcpy code instead. */ if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer)) class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject)); } +#endif class->size_inited = 1; @@ -1864,6 +1887,18 @@ mono_class_setup_vtable (MonoClass *class) return; } +static void +check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMethod *base) +{ + MonoSecurityCoreCLRLevel override_level = mono_security_core_clr_method_level (override, FALSE); + MonoSecurityCoreCLRLevel base_level = mono_security_core_clr_method_level (base, FALSE); + + if (override_level != base_level && base_level == MONO_SECURITY_CORE_CLR_CRITICAL) { + class->exception_type = MONO_EXCEPTION_TYPE_LOAD; + class->exception_data = NULL; + } +} + /* * LOCKING: this is supposed to be called with the loader lock held. */ @@ -1923,6 +1958,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o override_map = g_hash_table_new (mono_aligned_addr_hash, NULL); g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]); + + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_override_method (class, vtable [dslot], decl); } } @@ -1973,6 +2011,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o mono_secman_inheritancedemand_method (cm, im); } + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_override_method (class, cm, im); + g_assert (io + l <= max_vtsize); vtable [io + l] = cm; } @@ -2023,6 +2064,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o mono_secman_inheritancedemand_method (cm, im); } + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_override_method (class, cm, im); + g_assert (io + l <= max_vtsize); vtable [io + l] = cm; break; @@ -2060,6 +2104,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o mono_secman_inheritancedemand_method (cm, im); } + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_override_method (class, cm, im); + g_assert (io + l <= max_vtsize); vtable [io + l] = cm; break; @@ -2184,6 +2231,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o mono_secman_inheritancedemand_method (cm, m1); } + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_override_method (class, cm, m1); + slot = k->methods [j]->slot; g_assert (cm->slot < max_vtsize); if (!override_map) @@ -2216,6 +2266,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o if (!override_map) override_map = g_hash_table_new (mono_aligned_addr_hash, NULL); g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]); + + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_override_method (class, vtable [decl->slot], decl); } } @@ -2455,6 +2508,24 @@ set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error) } } +static void +check_core_clr_inheritance (MonoClass *class) +{ + MonoSecurityCoreCLRLevel class_level, parent_level; + MonoClass *parent = class->parent; + + if (!parent) + return; + + class_level = mono_security_core_clr_class_level (class); + parent_level = mono_security_core_clr_class_level (parent); + + if (class_level < parent_level) { + class->exception_type = MONO_EXCEPTION_TYPE_LOAD; + class->exception_data = NULL; + } +} + /** * mono_class_init: * @class: the class to initialize @@ -2504,6 +2575,9 @@ mono_class_init (MonoClass *class) mono_secman_inheritancedemand_class (class, class->parent); } + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) + check_core_clr_inheritance (class); + if (mono_debugger_start_class_init_func) mono_debugger_start_class_init_func (class); @@ -3499,7 +3573,7 @@ mono_class_from_mono_type (MonoType *type) * @type_spec: typespec token * @context: the generic context used to evaluate generic instantiations in */ -static MonoClass * +static MonoType * mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context) { MonoType *t = mono_type_create_from_typespec (image, type_spec); @@ -4076,7 +4150,7 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c MonoClass *class = NULL; if (image->dynamic) - return mono_lookup_dynamic_token (image, type_token); + return mono_lookup_dynamic_token (image, type_token, context); switch (type_token & 0xff000000){ case MONO_TOKEN_TYPE_DEF: @@ -4120,7 +4194,7 @@ mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *co //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then? if (image->dynamic) - return mono_class_get_type (mono_lookup_dynamic_token (image, type_token)); + return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context)); if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) { MonoClass *class = mono_class_get_full (image, type_token, context); @@ -4477,6 +4551,24 @@ mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, return FALSE; } +static gboolean +mono_class_has_variant_generic_params (MonoClass *klass) +{ + int i; + MonoGenericContainer *container; + + if (!klass->generic_class) + return FALSE; + + container = klass->generic_class->container_class->generic_container; + + for (i = 0; i < container->type_argc; ++i) + if (container->type_params [i].flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)) + return TRUE; + + return FALSE; +} + gboolean mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) { @@ -4503,6 +4595,52 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id)) return TRUE; + + if (mono_class_has_variant_generic_params (klass)) { + if (oklass->generic_class) { + int i; + gboolean match = FALSE; + MonoClass *container_class1 = klass->generic_class->container_class; + MonoClass *container_class2 = oklass->generic_class->container_class; + + /* + * Check whenever the generic definition of oklass implements the + * generic definition of klass. The IMPLEMENTS_INTERFACE stuff is not usable + * here since the relevant tables are not set up. + */ + for (i = 0; i < container_class2->interface_offsets_count; ++i) + if ((container_class2->interfaces_packed [i] == container_class1) || (container_class2->interfaces_packed [i]->generic_class && (container_class2->interfaces_packed [i]->generic_class->container_class == container_class1))) + match = TRUE; + + if (match) { + MonoGenericContainer *container; + + container = klass->generic_class->container_class->generic_container; + + match = TRUE; + for (i = 0; i < container->type_argc; ++i) { + MonoClass *param1_class = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [i]); + MonoClass *param2_class = mono_class_from_mono_type (oklass->generic_class->context.class_inst->type_argv [i]); + + /* + * The _VARIANT and _COVARIANT constants should read _COVARIANT and + * _CONTRAVARIANT, but they are in a public header so we can't fix it. + */ + if (param1_class != param2_class) { + if ((container->type_params [i].flags & MONO_GEN_PARAM_VARIANT) && mono_class_is_assignable_from (param1_class, param2_class)) + ; + else if (((container->type_params [i].flags & MONO_GEN_PARAM_COVARIANT) && mono_class_is_assignable_from (param2_class, param1_class))) + ; + else + match = FALSE; + } + } + + if (match) + return TRUE; + } + } + } } else if (klass->rank) { MonoClass *eclass, *eoclass; @@ -4673,7 +4811,7 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class, { if (image->dynamic) { MonoClass *tmp_handle_class; - gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class); + gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class, context); g_assert (tmp_handle_class); if (handle_class) @@ -4758,17 +4896,17 @@ mono_install_lookup_dynamic_token (MonoLookupDynamicToken func) } gpointer -mono_lookup_dynamic_token (MonoImage *image, guint32 token) +mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context) { MonoClass *handle_class; - return lookup_dynamic (image, token, &handle_class); + return lookup_dynamic (image, token, &handle_class, context); } gpointer -mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class) +mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class, MonoGenericContext *context) { - return lookup_dynamic (image, token, handle_class); + return lookup_dynamic (image, token, handle_class, context); } static MonoGetCachedClassInfo get_cached_class_info = NULL; @@ -5673,14 +5811,31 @@ can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed) return FALSE; } +/* + * If klass is a generic type or if it is derived from a generic type, return the + * MonoClass of the generic definition + * Returns NULL if not found + */ +static MonoClass* +get_generic_definition_class (MonoClass *klass) +{ + while (klass) { + if (klass->generic_class && klass->generic_class->container_class) + return klass->generic_class->container_class; + klass = klass->parent; + } + return NULL; +} + /* FIXME: check visibility of type, too */ static gboolean can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_level) { - if (access_klass->generic_class && member_klass->generic_class && - access_klass->generic_class->container_class && member_klass->generic_class->container_class) { + MonoClass *member_generic_def; + if (access_klass->generic_class && access_klass->generic_class->container_class && + (member_generic_def = get_generic_definition_class (member_klass))) { if (can_access_member (access_klass->generic_class->container_class, - member_klass->generic_class->container_class, access_level)) + member_generic_def, access_level)) return TRUE; }