Merge pull request #5396 from kumpera/fix_11696
authorRodrigo Kumpera <kumpera@users.noreply.github.com>
Fri, 18 Aug 2017 20:04:34 +0000 (13:04 -0700)
committerGitHub <noreply@github.com>
Fri, 18 Aug 2017 20:04:34 +0000 (13:04 -0700)
[verifier] Check methodimpl table for duplicated. Fixes #11696

1  2 
mono/metadata/metadata-verify.c

index f0299605583b7a7686f78031422521334b25ee4f,a8bd7e7423e6adced4f0856d1f8819a7228fe376..666c158332e59a59b3bcbb48ea0328defc7a9dd5
@@@ -1894,13 -1894,8 +1894,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;
@@@ -2418,7 -2413,7 +2418,7 @@@ verify_typedef_table (VerifyContext *ct
        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));
@@@ -2967,11 -2962,8 +2967,11 @@@ verify_cattr_table_full (VerifyContext 
                /*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);
 +              }
        }
  }
  
@@@ -3758,6 -3750,54 +3758,54 @@@ verify_typeref_table_global_constraint
        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)
  {
@@@ -3769,6 -3809,7 +3817,7 @@@ verify_tables_data_global_constraints_f
  {
        verify_typeref_table (ctx);
        verify_typeref_table_global_constraints (ctx);
+       verify_methodimpl_table_global_constraints (ctx);
  }
  
  static void