Implement better explicit override checks.
authorRodrigo Kumpera <kumpera@gmail.com>
Tue, 19 Oct 2010 18:31:08 +0000 (16:31 -0200)
committerRodrigo Kumpera <kumpera@gmail.com>
Wed, 20 Oct 2010 03:44:09 +0000 (01:44 -0200)
* metadata-verify.c: Add mono_verifier_verify_methodimpl_row.

* metadata.c (mono_class_get_overrides_full): Call in the
verifier.

* verify.c: Add mono_verifier_is_signature_compatible that
does propery signature variance checking.

mono/metadata/metadata-internals.h
mono/metadata/metadata-verify.c
mono/metadata/metadata.c
mono/metadata/verify-internals.h
mono/metadata/verify.c

index 03fbd802f80a16624de4714a2c7febbb34c4c251..0ed09eaaa0b2b48cb288fcfb29ec7c5b346e2a14 100644 (file)
@@ -701,5 +701,7 @@ MonoException *mono_get_exception_field_access_msg (const char *msg) MONO_INTERN
 
 MonoException *mono_get_exception_method_access_msg (const char *msg) MONO_INTERNAL;
 
+MonoMethod* method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context) MONO_INTERNAL;
+
 #endif /* __MONO_METADATA_INTERNALS_H__ */
 
index 91572036699bccd95b411494589b0d2cb8b13bb5..ca2a15a7e03f6f33c2758061302e3aca75b83820 100644 (file)
@@ -4211,6 +4211,64 @@ mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *erro
        return TRUE;
 }
 
+/*Perform additional verification including metadata ones*/
+gboolean
+mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
+{
+       MonoMethod *declaration, *body;
+       MonoMethodSignature *body_sig, *decl_sig;
+       MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
+       guint32 data [MONO_METHODIMPL_SIZE];
+
+       mono_error_init (error);
+
+       if (!mono_verifier_is_enabled_for_image (image))
+               return TRUE;
+
+       if (row >= table->rows) {
+               mono_error_set_bad_image (error, image, "Invalid methodimpl row %d - table has %d rows", row, table->rows);
+               return FALSE;
+       }
+
+       mono_metadata_decode_row (table, row, data, MONO_METHODIMPL_SIZE);
+
+       body = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_BODY], NULL);
+       if (mono_loader_get_last_error ()) {
+               mono_loader_clear_error ();
+               mono_error_set_bad_image (error, image, "Invalid methodimpl body for row %x", row);
+               return FALSE;
+       }
+
+       declaration = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_DECLARATION], NULL);
+       if (mono_loader_get_last_error ()) {
+               mono_loader_clear_error ();
+               mono_error_set_bad_image (error, image, "Invalid methodimpl declaration for row %x", row);
+               return FALSE;
+       }
+
+       /* FIXME
+       mono_class_setup_supertypes (class);
+       if (!mono_class_has_parent (class, body->klass)) {
+               mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
+               return FALSE;
+       }*/
+
+       if (!(body_sig = mono_method_signature_checked (body, error))) {
+               return FALSE;
+       }
+
+       if (!(decl_sig = mono_method_signature_checked (declaration, error))) {
+               return FALSE;
+       }
+
+       if (!mono_verifier_is_signature_compatible (decl_sig, body_sig)) {
+               mono_error_set_bad_image (error, image, "Invalid methodimpl body signature not compatible with declaration row %x", row);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 #else
 gboolean
 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
@@ -4308,6 +4366,14 @@ gboolean
 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
 {
        mono_error_init (error);
+       return TRUE;
+}
+
+gboolean
+mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
+{
+       mono_error_init (error);
+       return TRUE;
 }
 
 #endif /* DISABLE_VERIFIER */
index e2ed9c7749f22e4faa2fbd57b635da71127c86cc..ddbc47982ab625d906bfa756255717b2d9bb9de6 100644 (file)
@@ -5581,7 +5581,7 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
        return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
 }
 
-static MonoMethod*
+MonoMethod*
 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
 {
        guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
@@ -5608,6 +5608,7 @@ gboolean
 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
                               MonoGenericContext *generic_context)
 {
+       MonoError error;
        locator_t loc;
        MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
        guint32 start, end;
@@ -5652,6 +5653,12 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod
        for (i = 0; i < num; ++i) {
                MonoMethod *method;
 
+               if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
+                       mono_error_cleanup (&error);
+                       ok = FALSE;
+                       break;
+               }
+
                mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
                method = method_from_method_def_or_ref (
                        image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
index bf4ad8dd9eebcf771bac77abed1d53ddaefaea57..214ecd554556534fe1f2faef83481163e386ea2a 100644 (file)
@@ -45,6 +45,8 @@ gboolean mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor,
 gboolean mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature) MONO_INTERNAL;
 
 gboolean mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error) MONO_INTERNAL;
+gboolean mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error) MONO_INTERNAL;
+gboolean mono_verifier_is_signature_compatible (MonoMethodSignature *target, MonoMethodSignature *candidate) MONO_INTERNAL;
 G_END_DECLS
 
 #endif  /* __MONO_METADATA_VERIFY_INTERNAL_H__ */
index 08a4ab6921f8f5fdd6c6aab92e84994eb6d30f75..0d6cc12fea467abd71ce1036e9bf43191b914d90 100644 (file)
@@ -2426,6 +2426,12 @@ mono_delegate_signature_equal (MonoMethodSignature *delegate_sig, MonoMethodSign
        return TRUE;
 }
 
+gboolean
+mono_verifier_is_signature_compatible (MonoMethodSignature *target, MonoMethodSignature *candidate)
+{
+       return mono_delegate_signature_equal (target, candidate, FALSE);
+}
+
 /* 
  * verify_ldftn_delegate:
  *