int i;
mono_class_setup_methods (klass);
+ if (klass->exception_type)
+ return FALSE;
for (i = 0; i < klass->method.count; ++i) {
method = klass->methods [i];
return FALSE;
}
-static gboolean
-mono_class_interface_implements_interface (MonoClass *candidate, MonoClass *iface)
-{
- int i;
- do {
- if (candidate == iface)
- return TRUE;
- mono_class_setup_interfaces (candidate);
- for (i = 0; i < candidate->interface_count; ++i) {
- if (candidate->interfaces [i] == iface || mono_class_interface_implements_interface (candidate->interfaces [i], iface))
- return TRUE;
- }
- candidate = candidate->parent;
- } while (candidate);
- return FALSE;
-}
-
/*
* Verify if @type is valid for the given @ctx verification context.
* this function checks for VAR and MVAR types that are invalid under the current verifier,
}
return result;
}
-/*
- * Test if @candidate is a subtype of @target using the minimal possible information
- * TODO move the code for non finished TypeBuilders to here.
- */
-static gboolean
-mono_class_is_constraint_compatible (MonoClass *candidate, MonoClass *target)
-{
- 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 a supertype it must be an interface
- if (!MONO_CLASS_IS_INTERFACE (target))
- return FALSE;
-
- 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 *ifaceClass = mono_class_from_mono_type (iface->type);
- if (mono_class_is_constraint_compatible (ifaceClass, target)) {
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- return mono_class_interface_implements_interface (candidate, target);
-}
static gboolean
is_valid_generic_instantiation (MonoGenericContainer *gc, MonoGenericContext *context, MonoGenericInst *ginst)
ctr = mono_class_from_mono_type (inflated);
mono_metadata_free_type (inflated);
- if (!mono_class_is_constraint_compatible (paramClass, ctr))
+ if (!mono_class_is_assignable_from_slow (ctr, paramClass))
return FALSE;
}
}
}
default:
- VERIFIER_DEBUG ( printf ("unknown type %02x in eval stack type\n", type->type); );
- g_assert_not_reached ();
- return 0;
+ return TYPE_INV;
}
}
return;
}
+ if (!ctx->max_stack) {
+ ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack overflow at 0x%04x", ctx->ip_offset));
+ return;
+ }
+
stack_init (ctx, code);
set_stack_value (ctx, code->stack, type, FALSE);
ctx->exception_types = g_slist_prepend (ctx->exception_types, type);
static void
do_ldstr (VerifyContext *ctx, guint32 token)
{
+ GSList *error = NULL;
if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid string token %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
return;
}
- if (!ctx->image->dynamic && mono_metadata_token_index (token) >= ctx->image->heap_us.size) {
+ if (!ctx->image->dynamic && !mono_verifier_verify_string_signature (ctx->image, mono_metadata_token_index (token), &error)) {
+ if (error)
+ ctx->list = g_slist_concat (ctx->list, error);
ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid string index %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
return;
}
for (i = 0; i < ctx.num_locals; ++i) {
if (!mono_type_is_valid_in_context (&ctx, ctx.locals [i]))
break;
+ if (get_stack_type (ctx.locals [i]) == TYPE_INV) {
+ char *name = mono_type_full_name (ctx.locals [i]);
+ ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid local %i of type %s", i, name));
+ g_free (name);
+ break;
+ }
+
}
for (i = 0; i < ctx.max_args; ++i) {
if (!mono_type_is_valid_in_context (&ctx, ctx.params [i]))
break;
+
+ if (get_stack_type (ctx.params [i]) == TYPE_INV) {
+ char *name = mono_type_full_name (ctx.params [i]);
+ ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid parameter %i of type %s", i, name));
+ g_free (name);
+ break;
+ }
}
if (!ctx.valid)
ip += 2;
break;
- /* FIXME: warn/error instead? */
case CEE_UNUSED99:
+ ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
++ip;
break;
case CEE_UNUSED58:
case CEE_UNUSED1:
- ++ip; /* warn, error ? */
+ ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
+ ++ip;
break;
case CEE_UNBOX:
ip += 5;
break;
- case CEE_UNUSED56:
- ++ip;
- break;
-
case CEE_LDARG:
case CEE_LDARGA:
code_bounds_check (3);
++ip;
break;
+ case CEE_UNUSED56:
case CEE_UNUSED57:
+ case CEE_UNUSED70:
+ case CEE_UNUSED:
+ ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
++ip;
break;
case CEE_ENDFILTER:
start = 1;
++ip;
break;
- case CEE_UNUSED:
- ++ip;
- break;
case CEE_SIZEOF:
code_bounds_check (5);
field_class = mono_class_get_generic_type_definition (mono_class_from_mono_type (field->type));
- if (field_class == target_class || !verify_valuetype_layout_with_target (field_class, target_class))
+ if (field_class == target_class || class == field_class || !verify_valuetype_layout_with_target (field_class, target_class))
return FALSE;
}
gboolean
mono_verifier_verify_class (MonoClass *class)
{
+ /*Neither <Module>, object or ifaces have parent.*/
+ if (!class->parent &&
+ class != mono_defaults.object_class &&
+ !MONO_CLASS_IS_INTERFACE (class) &&
+ (!class->image->dynamic && class->type_token != 0x2000001)) /*<Module> is the first type in the assembly*/
+ return FALSE;
+ if (class->parent && MONO_CLASS_IS_INTERFACE (class->parent))
+ return FALSE;
if (class->generic_container && (class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
return FALSE;
if (!verify_class_for_overlapping_reference_fields (class))