#include <mono/metadata/verify-internals.h>
#include <mono/metadata/mono-debug.h>
#include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-string.h>
+#include <mono/utils/mono-error-internals.h>
MonoStats mono_stats;
}
static MonoType*
-inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context)
+inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
{
+ mono_error_init (error);
+
switch (type->type) {
case MONO_TYPE_MVAR: {
MonoType *nt;
return NULL;
if (num >= inst->type_argc) {
MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
- g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations",
+ mono_error_set_bad_image (error, image->module_name, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
num, info ? info->name : "", inst->type_argc);
+ return NULL;
}
/*
return NULL;
if (num >= inst->type_argc) {
MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
- g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations",
+ mono_error_set_bad_image (error, image->module_name, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
num, info ? info->name : "", inst->type_argc);
+ return NULL;
}
nt = mono_metadata_type_dup (image, inst->type_argv [num]);
nt->byref = type->byref;
}
case MONO_TYPE_SZARRAY: {
MonoClass *eclass = type->data.klass;
- MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context);
- if (!inflated)
+ MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
+ if (!inflated || !mono_error_ok (error))
return NULL;
nt = mono_metadata_type_dup (image, type);
nt->data.klass = mono_class_from_mono_type (inflated);
}
case MONO_TYPE_ARRAY: {
MonoClass *eclass = type->data.array->eklass;
- MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context);
- if (!inflated)
+ MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
+ if (!inflated || !mono_error_ok (error))
return NULL;
nt = mono_metadata_type_dup (image, type);
nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
* @mempool: a mempool
* @type: a type
* @context: a generics context
+ * @error: error context
*
* The same as mono_class_inflate_generic_type, but allocates the MonoType
* from mempool if it is non-NULL. If it is NULL, the MonoType is
* modified by the caller, and it should be freed using mono_metadata_free_type ().
*/
MonoType*
-mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context)
+mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
{
- MonoType *inflated = NULL;
+ MonoType *inflated = NULL;
+ mono_error_init (error);
if (context)
- inflated = inflate_generic_type (image, type, context);
+ inflated = inflate_generic_type (image, type, context, error);
+ if (!mono_error_ok (error))
+ return NULL;
if (!inflated) {
MonoType *shared = mono_metadata_get_shared_type (type);
* generics context @context.
*
* Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
- * on the heap and is owned by the caller.
+ * on the heap and is owned by the caller. Returns NULL on error.
+ *
+ * @deprecated Please use mono_class_inflate_generic_type_checked instead
*/
MonoType*
mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
{
- return mono_class_inflate_generic_type_with_mempool (NULL, type, context);
+ MonoError error;
+ MonoType *result;
+ result = mono_class_inflate_generic_type_checked (type, context, &error);
+
+ if (!mono_error_ok (&error)) {
+ mono_error_cleanup (&error);
+ return NULL;
+ }
+ return result;
+}
+
+/*
+ * mono_class_inflate_generic_type:
+ * @type: a type
+ * @context: a generics context
+ * @error: error context to use
+ *
+ * If @type is a generic type and @context is not NULL, instantiate it using the
+ * generics context @context.
+ *
+ * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
+ * on the heap and is owned by the caller.
+ */
+MonoType*
+mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
+{
+ return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
}
/*
static MonoType*
mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context)
{
+ MonoError error;
MonoType *inflated = NULL;
- if (context)
- inflated = inflate_generic_type (image, type, context);
+ if (context) {
+ inflated = inflate_generic_type (image, type, context, &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+ }
if (!inflated)
return type;
MonoClass*
mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
{
+ MonoError error;
MonoClass *res;
MonoType *inflated;
- inflated = mono_class_inflate_generic_type (&gklass->byval_arg, context);
+ inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
res = mono_class_from_mono_type (inflated);
mono_metadata_free_type (inflated);
result->klass = klass_hint;
if (!result->klass) {
- MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context);
+ MonoError error;
+ MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, &error);
+
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+
result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
if (inflated)
mono_metadata_free_type (inflated);
gboolean explicit_size;
MonoClassField *field;
MonoGenericContainer *container = NULL;
- MonoClass *gklass = NULL;
+ MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
if (class->size_inited)
return;
return;
}
- if (class->generic_class) {
- MonoClass *gklass = class->generic_class->container_class;
- mono_class_setup_fields (gklass);
- top = gklass->field.count;
- class->field.first = gklass->field.first;
- class->field.count = gklass->field.count;
+ if (gtd) {
+ mono_class_setup_fields (gtd);
+ if (gtd->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return;
+ }
+
+ top = gtd->field.count;
+ class->field.first = gtd->field.first;
+ class->field.count = gtd->field.count;
}
class->instance_size = 0;
if (class->parent) {
/* For generic instances, class->parent might not have been initialized */
mono_class_init (class->parent);
- if (!class->parent->size_inited)
+ if (!class->parent->size_inited) {
mono_class_setup_fields (class->parent);
+ if (class->parent->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return;
+ }
+ }
class->instance_size += class->parent->instance_size;
class->min_align = class->parent->min_align;
/* we use |= since it may have been set already */
if (class->generic_container) {
container = class->generic_container;
- } else if (class->generic_class) {
- gklass = class->generic_class->container_class;
- container = gklass->generic_container;
+ } else if (gtd) {
+ container = gtd->generic_container;
g_assert (container);
-
- mono_class_setup_fields (gklass);
-
- if (gklass->exception_type) {
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
- return;
- }
}
/*
field->parent = class;
- if (class->generic_class) {
- MonoClassField *gfield = &gklass->fields [i];
+ if (gtd) {
+ MonoClassField *gfield = >d->fields [i];
field->name = mono_field_get_name (gfield);
/*This memory must come from the image mempool as we don't have a chance to free it.*/
blittable = FALSE;
} else {
MonoClass *field_class = mono_class_from_mono_type (field->type);
- if (field_class)
+ if (field_class) {
mono_class_setup_fields (field_class);
+ if (field_class->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ break;
+ }
+ }
if (!field_class || !field_class->blittable)
blittable = FALSE;
}
}
}
- if (MONO_CLASS_IS_INTERFACE (class))
- for (i = 0; i < class->method.count; ++i)
- methods [i]->slot = i;
+ if (MONO_CLASS_IS_INTERFACE (class)) {
+ int slot = 0;
+ /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
+ for (i = 0; i < class->method.count; ++i) {
+ if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
+ methods [i]->slot = slot++;
+ }
+ }
/* Needed because of the double-checking locking pattern */
mono_memory_barrier ();
return -1;
}
+/*
+ * Return the number of virtual methods.
+ * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
+ * FIXME It would be nice if this information could be cached somewhere.
+ */
+static int
+count_virtual_methods (MonoClass *class)
+{
+ int i, count = 0;
+ guint32 flags;
+ class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
+
+ if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
+ mono_class_setup_methods (class);
+
+ for (i = 0; i < class->method.count; ++i) {
+ flags = class->methods [i]->flags;
+ if (flags & METHOD_ATTRIBUTE_VIRTUAL)
+ ++count;
+ }
+ } else {
+ for (i = 0; i < class->method.count; ++i) {
+ flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
+
+ if (flags & METHOD_ATTRIBUTE_VIRTUAL)
+ ++count;
+ }
+ }
+ return count;
+}
+
/*
* LOCKING: this is supposed to be called with the loader lock held.
*/
interface_offsets_full [i] = -1;
}
+ for (k = class->parent; k ; k = k->parent) {
+ ifaces = mono_class_get_implemented_interfaces (k);
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; ++i) {
+ int io;
+ ic = g_ptr_array_index (ifaces, i);
+
+ /*Force the sharing of interface offsets between parent and subtypes.*/
+ io = mono_class_interface_offset (k, ic);
+ g_assert (io >= 0);
+ interfaces_full [ic->interface_id] = ic;
+ interface_offsets_full [ic->interface_id] = io;
+ }
+ g_ptr_array_free (ifaces, TRUE);
+ }
+ }
+
+
ifaces = mono_class_get_implemented_interfaces (class);
if (ifaces) {
for (i = 0; i < ifaces->len; ++i) {
continue;
interfaces_full [ic->interface_id] = ic;
interface_offsets_full [ic->interface_id] = cur_slot;
- cur_slot += ic->method.count;
+ cur_slot += count_virtual_methods (ic);
}
g_ptr_array_free (ifaces, TRUE);
}
- for (k = class->parent; k ; k = k->parent) {
- ifaces = mono_class_get_implemented_interfaces (k);
- if (ifaces) {
- for (i = 0; i < ifaces->len; ++i) {
- ic = g_ptr_array_index (ifaces, i);
-
- if (interface_offsets_full [ic->interface_id] == -1) {
- int io = mono_class_interface_offset (k, ic);
-
- g_assert (io >= 0);
-
- interfaces_full [ic->interface_id] = ic;
- interface_offsets_full [ic->interface_id] = io;
- }
- }
- g_ptr_array_free (ifaces, TRUE);
- }
- }
-
if (MONO_CLASS_IS_INTERFACE (class)) {
interfaces_full [class->interface_id] = class;
interface_offsets_full [class->interface_id] = cur_slot;
#define DEBUG_INTERFACE_VTABLE_CODE 0
#define TRACE_INTERFACE_VTABLE_CODE 0
#define VERIFY_INTERFACE_VTABLE_CODE 0
+#define VTABLE_SELECTOR (1)
#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
#define DEBUG_INTERFACE_VTABLE(stmt) do {\
+ if (!(VTABLE_SELECTOR)) break; \
stmt;\
} while (0)
#else
#if TRACE_INTERFACE_VTABLE_CODE
#define TRACE_INTERFACE_VTABLE(stmt) do {\
+ if (!(VTABLE_SELECTOR)) break; \
stmt;\
} while (0)
#else
#if VERIFY_INTERFACE_VTABLE_CODE
#define VERIFY_INTERFACE_VTABLE(stmt) do {\
+ if (!(VTABLE_SELECTOR)) break; \
stmt;\
} while (0)
#else
}
static gboolean
-verify_class_overrides (MonoClass *class, GPtrArray *ifaces, MonoMethod **overrides, int onum)
+verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
{
int i;
- gboolean found;
for (i = 0; i < onum; ++i) {
MonoMethod *decl = overrides [i * 2];
}
if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
- if (body->flags & METHOD_ATTRIBUTE_STATIC)
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
- else
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
- return FALSE;
- }
-
- found = FALSE;
- /*We can't use mono_class_is_assignable_from since it requires the class to be fully initialized*/
- if (ifaces) {
- int j;
- for (j = 0; j < ifaces->len; j++) {
- MonoClass *ic = g_ptr_array_index (ifaces, j);
- if (decl->klass == ic) {
- found = TRUE;
- break;
- }
- }
- }
-
- if (!found) {
- MonoClass *parent = class;
- while (parent) {
- if (decl->klass == parent) {
- found = TRUE;
- break;
- }
- parent = parent->parent;
- }
+ if (body->flags & METHOD_ATTRIBUTE_STATIC)
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
+ else
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
+ return FALSE;
}
- if (!found) {
+ if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
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;
}
if (class->vtable)
return;
- ifaces = mono_class_get_implemented_interfaces (class);
-
- if (overrides && !verify_class_overrides (class, ifaces, overrides, onum)) {
- if (ifaces)
- g_ptr_array_free (ifaces, TRUE);
+ if (overrides && !verify_class_overrides (class, overrides, onum))
return;
- }
+
+ ifaces = mono_class_get_implemented_interfaces (class);
if (ifaces) {
for (i = 0; i < ifaces->len; i++) {
for (i = 0; i < parent->interface_offsets_count; i++) {
MonoClass *parent_interface = parent->interfaces_packed [i];
int interface_offset = mono_class_interface_offset (class, parent_interface);
-
+ /*FIXME this is now dead code as this condition will never hold true.
+ Since interface offsets are inherited then the offset of an interface implemented
+ by a parent will never be the out of it's vtable boundary.
+ */
if (interface_offset >= parent->vtable_size) {
int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
int j;
cm->slot = slot;
}
+ /*Non final newslot methods must be given a non-interface vtable slot*/
+ if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
+ cm->slot = -1;
+
if (cm->slot < 0)
cm->slot = cur_slot++;
g_hash_table_destroy (override_map);
}
+ /* Ensure that all vtable slots are filled with concrete instance methods */
+ if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+ for (i = 0; i < cur_slot; ++i) {
+ if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
+ char *type_name = mono_type_get_full_name (class);
+ char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
+ g_free (type_name);
+ g_free (method_name);
+ return;
+ }
+ }
+ }
+
if (class->generic_class) {
MonoClass *gklass = class->generic_class->container_class;
printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
class->vtable_size, icount);
- for (i = 0; i < class->vtable_size; ++i) {
+ for (i = 0; i < cur_slot; ++i) {
MonoMethod *cm;
cm = vtable [i];
ic = class->interfaces [i];
printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
mono_class_interface_offset (class, ic),
- ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
+ count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
}
for (k = class->parent; k ; k = k->parent) {
for (i = 0; i < k->interface_count; i++) {
ic = k->interfaces [i];
- printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
+ printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
mono_class_interface_offset (class, ic),
- ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
+ count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
}
}
}
class->init_pending = 1;
+ if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
+ MonoClass *element_class = class->element_class;
+ if (!element_class->inited)
+ mono_class_init (element_class);
+ if (element_class->exception_type != MONO_EXCEPTION_NONE) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ goto fail;
+ }
+ }
+
/* CAS - SecurityAction.InheritanceDemand */
if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
mono_secman_inheritancedemand_class (class, class->parent);
class->has_cctor = gklass->has_cctor;
mono_class_setup_vtable (gklass);
- if (gklass->exception_type)
+ if (gklass->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
goto fail;
+ }
class->vtable_size = gklass->vtable_size;
} else {
if (class->parent) {
/* This will compute class->parent->vtable_size for some classes */
mono_class_init (class->parent);
- if (class->parent->exception_type || mono_loader_get_last_error ())
+ if (class->parent->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ goto fail;
+ }
+ if (mono_loader_get_last_error ())
goto fail;
if (!class->parent->vtable_size) {
/* FIXME: Get rid of this somehow */
mono_class_setup_vtable (class->parent);
- if (class->parent->exception_type || mono_loader_get_last_error ())
+ if (class->parent->exception_type) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ goto fail;
+ }
+ if (mono_loader_get_last_error ())
goto fail;
}
setup_interface_offsets (class, class->parent->vtable_size);
}
+/*
+ * COM initialization (using mono_init_com_types) is delayed until needed.
+ * However when a [ComImport] attribute is present on a type it will trigger
+ * the initialization. This is not a problem unless the BCL being executed
+ * lacks the types that COM depends on (e.g. Variant on Silverlight).
+ */
+static void
+init_com_from_comimport (MonoClass *class)
+{
+ /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
+ if ((mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)) {
+ /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
+ if (!mono_security_core_clr_determine_platform_image (class->image)) {
+ /* but it can not be made available for application (i.e. user code) since all COM calls
+ * are considered native calls. In this case we fail with a TypeLoadException (just like
+ * Silverlight 2 does */
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return;
+ }
+ }
+ /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
+ mono_init_com_types ();
+}
+
/*
* LOCKING: this assumes the loader lock is held
*/
if (!MONO_CLASS_IS_INTERFACE (class)) {
/* Imported COM Objects always derive from __ComObject. */
if (MONO_CLASS_IS_IMPORT (class)) {
- mono_init_com_types ();
+ init_com_from_comimport (class);
if (parent == mono_defaults.object_class)
parent = mono_defaults.com_object_class;
}
} else {
/* initialize com types if COM interfaces are present */
if (MONO_CLASS_IS_IMPORT (class))
- mono_init_com_types ();
+ init_com_from_comimport (class);
class->parent = NULL;
}
/* uses ->valuetype, which is initialized by mono_class_setup_parent above */
mono_class_setup_mono_type (class);
+ if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
+ class->unicode = 1;
+
+#ifdef PLATFORM_WIN32
+ if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
+ class->unicode = 1;
+#endif
+
+ class->cast_class = class->element_class = class;
+
if (!class->enumtype) {
if (!mono_metadata_interfaces_from_typedef_full (
image, type_token, &interfaces, &icount, FALSE, context)){
class->interfaces_inited = 1;
}
- if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
- class->unicode = 1;
-
-#if PLATFORM_WIN32
- if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
- class->unicode = 1;
-#endif
-
- class->cast_class = class->element_class = class;
-
/*g_print ("Load class %s\n", name);*/
/*
static MonoType *
mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate)
{
+ MonoError error;
MonoType *t = mono_type_create_from_typespec (image, type_spec);
if (!t)
return NULL;
if (context && (context->class_inst || context->method_inst)) {
- MonoType *inflated = inflate_generic_type (NULL, t, context);
+ MonoType *inflated = inflate_generic_type (NULL, t, context, &error);
+ g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
+
if (inflated) {
t = inflated;
*did_inflate = TRUE;
mono_class_init (eclass);
if (!eclass->size_inited)
mono_class_setup_fields (eclass);
+ if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+
class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
class->rank = rank;
mono_class_get_field_idx (MonoClass *class, int idx)
{
mono_class_setup_fields_locking (class);
+ if (class->exception_type)
+ return NULL;
while (class) {
if (class->image->uncompressed_metadata) {
int i;
mono_class_setup_fields_locking (klass);
+ if (klass->exception_type)
+ return NULL;
+
while (klass) {
for (i = 0; i < klass->field.count; ++i) {
MonoClassField *field = &klass->fields [i];
int i;
mono_class_setup_fields_locking (klass);
+ if (klass->exception_type)
+ return 0;
+
while (klass) {
for (i = 0; i < klass->field.count; ++i) {
if (&klass->fields [i] == field) {
if (!type) {
char *name = mono_class_name_from_token (image, type_token);
char *assembly = mono_assembly_name_from_token (image, type_token);
- if (inflated)
- mono_metadata_free_type (type);
mono_loader_set_error_type_load (name, assembly);
+ return NULL;
}
if (inflated) {
{
GHashTable *nspace_table;
GHashTable *name_cache;
+ guint32 old_index;
mono_image_lock (image);
nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
}
+
+ if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
+ g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
+
g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
mono_image_unlock (image);
char *name = (char*)key;
FindUserData *data = (FindUserData*)user_data;
- if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
+ if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
data->value = value;
}
continue;
n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
- if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
+ if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
}
return NULL;
return mono_class_has_parent (oklass, klass);
}
+/*Check if @candidate implements the interface @target*/
+static gboolean
+mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
+{
+ int i;
+
+ do {
+ if (candidate == target)
+ return TRUE;
+
+ /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
+ if (candidate->image->dynamic && !candidate->wastypebuilder) {
+ MonoReflectionTypeBuilder *tb = candidate->reflection_info;
+ int j;
+ if (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);
+ if (iface_class == target || mono_class_implement_interface_slow (target, iface_class))
+ return TRUE;
+ }
+ }
+ } else {
+ /*setup_interfaces don't mono_class_init anything*/
+ mono_class_setup_interfaces (candidate);
+ for (i = 0; i < candidate->interface_count; ++i) {
+ if (candidate->interfaces [i] == target || mono_class_implement_interface_slow (target, candidate->interfaces [i]))
+ return TRUE;
+ }
+ }
+ candidate = candidate->parent;
+ } while (candidate);
+
+ return FALSE;
+}
+
+/*
+ * Check if @oklass can be assigned to @klass.
+ * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
+ */
+gboolean
+mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
+{
+ if (candidate == target)
+ return TRUE;
+ if (target == mono_defaults.object_class)
+ return TRUE;
+
+ /*setup_supertypes don't mono_class_init anything */
+ mono_class_setup_supertypes (candidate);
+ mono_class_setup_supertypes (target);
+
+ if (mono_class_has_parent (candidate, target))
+ return TRUE;
+
+ /*If target is not an interface there is no need to check them.*/
+ if (!MONO_CLASS_IS_INTERFACE (target))
+ return FALSE;
+ return mono_class_implement_interface_slow (target, candidate);
+}
+
/**
* mono_class_get_cctor:
* @klass: A MonoClass pointer
return TRUE;
if (!accessed || !accessing)
return FALSE;
+
+ /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
+ * anywhere so untrusted friends are not safe to access platform's code internals */
+ if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+ if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
+ return FALSE;
+ }
+
mono_assembly_load_friends (accessed);
for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
MonoAssemblyName *friend = tmp->data;
if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
return FALSE;
+ /*Non nested type with nested visibility. We just fail it.*/
+ if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
+ return FALSE;
+
switch (access_level) {
case TYPE_ATTRIBUTE_NOT_PUBLIC:
return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);