[verifier] Allow byref in PropertySig blobs. Fixes #59180
[mono.git] / mono / metadata / metadata-verify.c
index f0299605583b7a7686f78031422521334b25ee4f..e898178e00a1532a253acbf3adea8e23787c6fd9 100644 (file)
@@ -1514,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;
@@ -1530,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"));
 
@@ -3758,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)
 {
@@ -3769,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