mono_class_alloc (MonoClass *class, int size)
{
if (class->generic_class)
- /*
- * This should be freed in free_generic_class () in metadata.c.
- * FIXME: It would be better to allocate this from the image set mempool, by
- * adding an image_set field to MonoGenericClass.
- */
- return g_malloc (size);
+ return mono_image_set_alloc (class->generic_class->owner, size);
else
return mono_image_alloc (class->image, size);
}
}
}
-/* useful until we keep track of gc-references in corlib etc. */
-#ifdef HAVE_SGEN_GC
-#define IS_GC_REFERENCE(t) FALSE
-#else
-#define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U && class->image == mono_defaults.corlib)
-#endif
-
/*
* mono_type_get_basic_type_from_generic:
* @type: a type
mono_loader_unlock ();
}
+void
+mono_unload_interface_id (MonoClass *class)
+{
+ if (class->interface_id) {
+ mono_loader_lock ();
+ mono_bitset_clear (global_interface_bitset, class->interface_id);
+ mono_loader_unlock ();
+ }
+}
+
/*
* mono_get_unique_iid:
* @class: interface
}
mono_bitset_set (global_interface_bitset, iid);
/* set the bit also in the per-image set */
- if (class->image->interface_bitset) {
- if (iid >= mono_bitset_size (class->image->interface_bitset)) {
- MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
- mono_bitset_free (class->image->interface_bitset);
- class->image->interface_bitset = new_set;
+ if (!class->generic_class) {
+ if (class->image->interface_bitset) {
+ if (iid >= mono_bitset_size (class->image->interface_bitset)) {
+ MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
+ mono_bitset_free (class->image->interface_bitset);
+ class->image->interface_bitset = new_set;
+ }
+ } else {
+ class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
}
- } else {
- class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
+ mono_bitset_set (class->image->interface_bitset, iid);
}
- mono_bitset_set (class->image->interface_bitset, iid);
#ifndef MONO_SMALL_CONFIG
if (mono_print_vtable) {
}
#endif
+static gboolean
+is_wcf_hack_disabled (void)
+{
+ static gboolean disabled;
+ static gboolean inited = FALSE;
+ if (!inited) {
+ disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
+ inited = TRUE;
+ }
+ return disabled;
+}
+
static gboolean
check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
MonoMethodSignature *cmsig, *imsig;
if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
mono_security_core_clr_check_override (class, cm, im);
TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
+ if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
+ char *body_name = mono_method_full_name (cm, TRUE);
+ char *decl_name = mono_method_full_name (im, TRUE);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
+ g_free (body_name);
+ g_free (decl_name);
+ return FALSE;
+ }
+
return TRUE;
} else {
MonoClass *ic = im->klass;
TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
return FALSE;
}
- if (! mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
+ cmsig = mono_method_signature (cm);
+ imsig = mono_method_signature (im);
+ if (!cmsig || !imsig) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
+ return FALSE;
+ }
+
+ if (! mono_metadata_signature_equal (cmsig, imsig)) {
TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
TRACE_INTERFACE_VTABLE (printf ("]"));
mono_security_core_clr_check_override (class, cm, im);
TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
+ if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
+ char *body_name = mono_method_full_name (cm, TRUE);
+ char *decl_name = mono_method_full_name (im, TRUE);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
+ g_free (body_name);
+ g_free (decl_name);
+ return FALSE;
+ }
+
return TRUE;
}
}
}
}
+static MonoMethod*
+mono_method_get_method_definition (MonoMethod *method)
+{
+ while (method->is_inflated)
+ method = ((MonoMethodInflated*)method)->declaring;
+ return method;
+}
+
static gboolean
verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
{
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
return FALSE;
}
+
+ body = mono_method_get_method_definition (body);
+ decl = mono_method_get_method_definition (decl);
+
+ if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
+ char *body_name = mono_method_full_name (body, TRUE);
+ char *decl_name = mono_method_full_name (decl, TRUE);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
+ g_free (body_name);
+ g_free (decl_name);
+ return FALSE;
+ }
}
return TRUE;
}
if (slot == -1)
goto fail;
+ if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
+ char *body_name = mono_method_full_name (cm, TRUE);
+ char *decl_name = mono_method_full_name (m1, TRUE);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
+ g_free (body_name);
+ g_free (decl_name);
+ goto fail;
+ }
+
g_assert (cm->slot < max_vtsize);
if (!override_map)
override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
/* AOT case */
class->vtable_size = cached_info.vtable_size;
class->has_finalize = cached_info.has_finalize;
+ class->has_finalize_inited = TRUE;
class->ghcimpl = cached_info.ghcimpl;
class->has_cctor = cached_info.has_cctor;
} else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
} else {
class->vtable_size = szarray_vtable_size[slot];
}
+ class->has_finalize_inited = TRUE;
} else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
MonoClass *gklass = class->generic_class->container_class;
/* Generic instance case */
class->ghcimpl = gklass->ghcimpl;
- class->has_finalize = gklass->has_finalize;
+ class->has_finalize = mono_class_has_finalizer (gklass);
+ class->has_finalize_inited = TRUE;
class->has_cctor = gklass->has_cctor;
mono_class_setup_vtable (gklass);
}
*/
- /* Interfaces and valuetypes are not supposed to have finalizers */
- if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
- MonoMethod *cmethod = NULL;
-
- if (class->parent && class->parent->has_finalize) {
- class->has_finalize = 1;
- } else {
- if (class->type_token) {
- cmethod = find_method_in_metadata (class, "Finalize", 0, METHOD_ATTRIBUTE_VIRTUAL);
- } else if (class->parent) {
- /* FIXME: Optimize this */
- mono_class_setup_vtable (class);
- if (class->exception_type || mono_loader_get_last_error ())
- goto leave;
- cmethod = class->vtable [finalize_slot];
- }
-
- if (cmethod) {
- /* Check that this is really the finalizer method */
- mono_class_setup_vtable (class);
- if (class->exception_type || mono_loader_get_last_error ())
- goto leave;
-
- g_assert (class->vtable_size > finalize_slot);
-
- class->has_finalize = 0;
- if (class->parent) {
- cmethod = class->vtable [finalize_slot];
- g_assert (cmethod);
- if (cmethod->is_inflated)
- cmethod = ((MonoMethodInflated*)cmethod)->declaring;
- if (cmethod != default_finalize) {
- class->has_finalize = 1;
- }
- }
- }
- }
- }
-
/* C# doesn't allow interfaces to have cctors */
if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
MonoMethod *cmethod = NULL;
mono_loader_clear_error ();
}
+ if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
+
goto leave;
leave:
return class->exception_type == MONO_EXCEPTION_NONE;
}
+/*
+ * mono_class_has_finalizer:
+ *
+ * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
+ * process.
+ */
+gboolean
+mono_class_has_finalizer (MonoClass *klass)
+{
+ if (!klass->has_finalize_inited) {
+ MonoClass *class = klass;
+
+ mono_loader_lock ();
+
+ /* Interfaces and valuetypes are not supposed to have finalizers */
+ if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
+ MonoMethod *cmethod = NULL;
+
+ if (class->parent && class->parent->has_finalize) {
+ class->has_finalize = 1;
+ } else {
+ if (class->parent) {
+ /*
+ * Can't search in metadata for a method named Finalize, because that
+ * ignores overrides.
+ */
+ mono_class_setup_vtable (class);
+ if (class->exception_type || mono_loader_get_last_error ())
+ goto leave;
+ cmethod = class->vtable [finalize_slot];
+ }
+
+ if (cmethod) {
+ g_assert (class->vtable_size > finalize_slot);
+
+ class->has_finalize = 0;
+ if (class->parent) {
+ if (cmethod->is_inflated)
+ cmethod = ((MonoMethodInflated*)cmethod)->declaring;
+ if (cmethod != default_finalize) {
+ class->has_finalize = 1;
+ }
+ }
+ }
+ }
+ }
+
+ mono_memory_barrier ();
+ klass->has_finalize_inited = TRUE;
+
+ mono_loader_unlock ();
+ }
+
+ return klass->has_finalize;
+
+ leave:
+ mono_loader_unlock ();
+ return FALSE;
+}
+
gboolean
mono_is_corlib_image (MonoImage *image)
{
if (class->enumtype) {
MonoType *enum_basetype = mono_class_find_enum_basetype (class);
if (!enum_basetype) {
+ /*set it to a default value as the whole runtime can't handle this to be null*/
+ class->cast_class = class->element_class = mono_defaults.int32_class;
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
{
MonoClass *klass, *gklass;
+ if (gclass->cached_class)
+ return gclass->cached_class;
+
mono_loader_lock ();
if (gclass->cached_class) {
mono_loader_unlock ();
return gclass->cached_class;
}
- gclass->cached_class = g_malloc0 (sizeof (MonoClass));
- klass = gclass->cached_class;
+ klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
gklass = gclass->container_class;
*/
if (gklass->parent) {
- klass->parent = mono_class_inflate_generic_class (gklass->parent, mono_generic_class_get_context (gclass));
+ MonoError error;
+ klass->parent = mono_class_inflate_generic_class_checked (gklass->parent, mono_generic_class_get_context (gclass), &error);
+ if (!mono_error_ok (&error)) {
+ /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
+ klass->parent = mono_defaults.object_class;
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ mono_error_cleanup (&error);
+ }
}
if (klass->parent)
}
}
+ mono_memory_barrier ();
+ gclass->cached_class = klass;
+
mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
inflated_classes ++;
if (count - pos > 0) {
mono_class_setup_vtable (klass->parent);
- g_assert (!klass->parent->exception_type);
- setup_interface_offsets (klass, klass->parent->vtable_size);
+ if (klass->parent->exception_type)
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
+ else
+ setup_interface_offsets (klass, klass->parent->vtable_size);
}
return klass;
}
#define FAST_CACHE_SIZE 16
-static MonoClass *var_cache_fast [FAST_CACHE_SIZE];
-static MonoClass *mvar_cache_fast [FAST_CACHE_SIZE];
-static GHashTable *var_cache_slow;
-static GHashTable *mvar_cache_slow;
static MonoClass *
get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
{
int n = mono_generic_param_num (param);
+ MonoImage *image = param->image;
GHashTable *ht;
- if (n < FAST_CACHE_SIZE)
- return (is_mvar ? mvar_cache_fast : var_cache_fast) [n];
- ht = is_mvar ? mvar_cache_slow : var_cache_slow;
- return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
+ g_assert (image);
+
+ if (n < FAST_CACHE_SIZE) {
+ if (is_mvar)
+ return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
+ else
+ return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
+ } else {
+ ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+ return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
+ }
}
+/*
+ * LOCKING: Acquires the loader lock.
+ */
static void
set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
{
int n = mono_generic_param_num (param);
+ MonoImage *image = param->image;
GHashTable *ht;
+ g_assert (image);
+
if (n < FAST_CACHE_SIZE) {
- (is_mvar ? mvar_cache_fast : var_cache_fast) [n] = klass;
+ if (is_mvar) {
+ /* No locking needed */
+ if (!image->mvar_cache_fast)
+ image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
+ image->mvar_cache_fast [n] = klass;
+ } else {
+ if (!image->var_cache_fast)
+ image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
+ image->var_cache_fast [n] = klass;
+ }
return;
}
- ht = is_mvar ? mvar_cache_slow : var_cache_slow;
+ ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
if (!ht) {
- ht = g_hash_table_new (NULL, NULL);
- if (is_mvar)
- mvar_cache_slow = ht;
- else
- var_cache_slow = ht;
+ mono_loader_lock ();
+ ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
+ if (!ht) {
+ ht = g_hash_table_new (NULL, NULL);
+ mono_memory_barrier ();
+ if (is_mvar)
+ image->mvar_cache_slow = ht;
+ else
+ image->var_cache_slow = ht;
+ }
+ mono_loader_unlock ();
}
g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
name = buf;
}
- if (get_class_from_name) {
+ /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
+ if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
gboolean res = get_class_from_name (image, name_space, name, &class);
if (res) {
if (!class)
MonoGenericContainer *container = klass_gtd->generic_container;
/*Viable candidates are instances of the same generic interface*/
- if (mono_class_get_generic_type_definition (oklass) != klass_gtd)
+ if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
return FALSE;
klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
MonoGenericContainer *container = klass_gtd->generic_container;
/*Viable candidates are instances of the same generic interface*/
- if (mono_class_get_generic_type_definition (oklass) != klass_gtd)
+ if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
return FALSE;
klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
if (tb && tb->interfaces) {
for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
- MonoClass *iface_class = mono_class_from_mono_type (iface->type);
+ MonoClass *iface_class;
+
+ /* we can't realize the type here since it can do pretty much anything. */
+ if (!iface->type)
+ continue;
+ iface_class = mono_class_from_mono_type (iface->type);
if (iface_class == target)
return TRUE;
if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
if (!klass->inited)
mono_class_init (klass);
- if (!klass->has_finalize)
+ if (!mono_class_has_finalizer (klass))
return NULL;
if (mono_class_get_cached_class_info (klass, &cached_info))
method++;
}
while (method < &klass->methods [klass->method.count]) {
- if (((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
+ if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
break;
method ++;
}
for (i = 0; i < klass->method.count; ++i) {
guint32 cols [MONO_METHOD_SIZE];
MonoMethod *method;
+ MonoMethodSignature *sig;
/* class->method.first points into the methodptr table */
mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
- if ((param_count == -1) || mono_method_signature (method)->param_count == param_count) {
+ if (param_count == -1) {
+ res = method;
+ break;
+ }
+ sig = mono_method_signature (method);
+ if (sig && sig->param_count == param_count) {
res = method;
break;
}
{
int access_level;
+ if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
+ return TRUE;
+
if (access_klass->element_class && !access_klass->enumtype)
access_klass = access_klass->element_class;
can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
{
MonoClass *member_generic_def;
+ if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
+ return TRUE;
+
if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
access_klass->generic_container) &&
(member_generic_def = get_generic_definition_class (member_klass))) {
klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
if (!mono_error_ok (error)) {
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
- g_free (klass->interfaces);
klass->interfaces = NULL;
return;
}