Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / metadata-verify.c
index 9b4ca91bc753965ceaba0e55cf9b8f096af0ee08..e898178e00a1532a253acbf3adea8e23787c6fd9 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * metadata-verify.c: Metadata verfication support
+/**
+ * \file
+ * Metadata verfication support
  *
  * Author:
  *     Mono Project (http://www.mono-project.com)
@@ -1513,6 +1514,7 @@ parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end,
 static gboolean
 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
 {
+       unsigned type = 0;
        unsigned sig = 0;
        unsigned param_count = 0, i;
        const char *ptr = *_ptr;
@@ -1529,6 +1531,13 @@ parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end
        if (!parse_custom_mods (ctx, &ptr, end))
                return FALSE;
 
+       if (!safe_read8 (type, ptr, end))
+               FAIL (ctx, g_strdup ("PropertySig: Not enough room for the type"));
+
+       //check if it's a byref. safe_read8 did update ptr, so we rollback if it's not a byref
+       if (type != MONO_TYPE_BYREF)
+               --ptr;
+
        if (!parse_type (ctx, &ptr, end))
                FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
 
@@ -1893,8 +1902,13 @@ handle_enum:
                FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
        }
 
-
        case MONO_TYPE_CLASS:
+               if (klass && klass->enumtype) {
+                       klass = klass->element_class;
+                       type = klass->byval_arg.type;
+                       goto handle_enum;
+               }
+
                if (klass != mono_defaults.systemtype_class)
                        FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
                *_ptr = ptr;
@@ -2412,7 +2426,7 @@ verify_typedef_table (VerifyContext *ctx)
        for (i = 0; i < table->rows; ++i) {
                mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
                if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
-                       ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
+                       ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x rejected bits: 0x%08x", i, data [MONO_TYPEDEF_FLAGS], data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS));
 
                if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
                        ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
@@ -2961,8 +2975,11 @@ verify_cattr_table_full (VerifyContext *ctx)
                /*This can't fail since this is checked in is_valid_cattr_blob*/
                g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
 
-               if (!is_valid_cattr_content (ctx, ctor, ptr, size))
-                       ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
+               if (!is_valid_cattr_content (ctx, ctor, ptr, size)) {
+                       char *ctor_name =  mono_method_full_name (ctor, TRUE);
+                       ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x ctor: %s", i, data [MONO_CUSTOM_ATTR_VALUE], ctor_name));
+                       g_free (ctor_name);
+               }
        }
 }
 
@@ -3749,6 +3766,54 @@ verify_typeref_table_global_constraints (VerifyContext *ctx)
        g_hash_table_destroy (unique_types);
 }
 
+typedef struct {
+       guint32 klass;
+       guint32 method_declaration;
+} MethodImplUniqueId;
+
+static guint
+methodimpl_hash (gconstpointer _key)
+{
+       const MethodImplUniqueId *key = (const MethodImplUniqueId *)_key;
+       return key->klass ^ key->method_declaration;
+}
+
+static gboolean
+methodimpl_equals (gconstpointer _a, gconstpointer _b)
+{
+       const MethodImplUniqueId *a = (const MethodImplUniqueId *)_a;
+       const MethodImplUniqueId *b = (const MethodImplUniqueId *)_b;
+       return a->klass == b->klass && a->method_declaration == b->method_declaration;
+}
+
+static void
+verify_methodimpl_table_global_constraints (VerifyContext *ctx)
+{
+       int i;
+       guint32 data [MONO_METHODIMPL_SIZE];
+       MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
+       GHashTable *unique_impls = g_hash_table_new_full (&methodimpl_hash, &methodimpl_equals, g_free, NULL);
+
+       for (i = 0; i < table->rows; ++i) {
+               MethodImplUniqueId *impl = g_new (MethodImplUniqueId, 1);
+               mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
+
+               impl->klass = data [MONO_METHODIMPL_CLASS];
+               impl->method_declaration = data [MONO_METHODIMPL_DECLARATION];
+
+               if (g_hash_table_lookup (unique_impls, impl)) {
+                       ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("MethodImpl table row %d has duplicate for tuple (0x%x, 0x%x)", impl->klass, impl->method_declaration));
+                       g_hash_table_destroy (unique_impls);
+                       g_free (impl);
+                       return;
+               }
+               g_hash_table_insert (unique_impls, impl, GUINT_TO_POINTER (1));
+       }
+
+       g_hash_table_destroy (unique_impls);
+}
+
+
 static void
 verify_tables_data_global_constraints (VerifyContext *ctx)
 {
@@ -3760,6 +3825,7 @@ verify_tables_data_global_constraints_full (VerifyContext *ctx)
 {
        verify_typeref_table (ctx);
        verify_typeref_table_global_constraints (ctx);
+       verify_methodimpl_table_global_constraints (ctx);
 }
 
 static void
@@ -4055,7 +4121,7 @@ mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoErr
 {
        VerifyContext ctx;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!mono_verifier_is_enabled_for_image (image))
                return TRUE;
@@ -4245,7 +4311,7 @@ mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *erro
        MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
        guint32 data [MONO_TYPEREF_SIZE];
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!mono_verifier_is_enabled_for_image (image))
                return TRUE;
@@ -4288,7 +4354,7 @@ mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *e
        MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
        guint32 data [MONO_METHODIMPL_SIZE];
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!mono_verifier_is_enabled_for_image (image))
                return TRUE;
@@ -4371,7 +4437,7 @@ mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **e
 gboolean
 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        return TRUE;
 }
 
@@ -4421,14 +4487,14 @@ mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMetho
 gboolean
 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        return TRUE;
 }
 
 gboolean
 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        return TRUE;
 }