Mon Apr 15 11:37:33 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / verify.c
index 70daf7ba0f0786b7338e88dfd53c33158f99f76a..7015fd825eacb23886cf7940a5b7bb498e065146 100644 (file)
@@ -1,7 +1,9 @@
 
 #include <mono/metadata/object.h>
 #include <mono/metadata/verify.h>
+#include <mono/metadata/opcodes.h>
 #include <mono/metadata/tabledefs.h>
+#include <mono/metadata/reflection.h>
 #include <mono/metadata/mono-endian.h>
 #include <string.h>
 #include <signal.h>
@@ -49,7 +51,7 @@ mono_free_verify_list (GSList *list)
                (list) = g_slist_prepend ((list), vinfo);       \
        } while (0)
 
-static const char*
+static const char* const
 valid_cultures[] = {
        "ar-SA", "ar-IQ", "ar-EG", "ar-LY",
        "ar-DZ", "ar-MA", "ar-TN", "ar-OM",
@@ -111,16 +113,16 @@ is_valid_assembly_flags (guint32 flags) {
 }
 
 static int
-is_valid_blob (MonoImage *image, guint32 index, int notnull)
+is_valid_blob (MonoImage *image, guint32 blob_index, int notnull)
 {
        guint32 size;
-       const char *p, *send;
+       const char *p, *blob_end;
        
-       if (index >= image->heap_blob.size)
+       if (blob_index >= image->heap_blob.size)
                return 0;
-       p = mono_metadata_blob_heap (image, index);
-       size = mono_metadata_decode_blob_size (p, &send);
-       if (index + size + (send-p) > image->heap_blob.size)
+       p = mono_metadata_blob_heap (image, blob_index);
+       size = mono_metadata_decode_blob_size (p, &blob_end);
+       if (blob_index + size + (blob_end-p) > image->heap_blob.size)
                return 0;
        if (notnull && !size)
                return 0;
@@ -128,20 +130,20 @@ is_valid_blob (MonoImage *image, guint32 index, int notnull)
 }
 
 static const char*
-is_valid_string (MonoImage *image, guint32 index, int notnull)
+is_valid_string (MonoImage *image, guint32 str_index, int notnull)
 {
-       const char *p, *send, *res;
+       const char *p, *blob_end, *res;
        
-       if (index >= image->heap_strings.size)
+       if (str_index >= image->heap_strings.size)
                return NULL;
-       res = p = mono_metadata_string_heap (image, index);
-       send = mono_metadata_string_heap (image, image->heap_strings.size - 1);
+       res = p = mono_metadata_string_heap (image, str_index);
+       blob_end = mono_metadata_string_heap (image, image->heap_strings.size - 1);
        if (notnull && !*p)
                return 0;
        /* 
         * FIXME: should check it's a valid utf8 string, too.
         */
-       while (p <= send) {
+       while (p <= blob_end) {
                if (!*p)
                        return res;
                ++p;
@@ -880,7 +882,7 @@ mono_method_verify (MonoMethod *method, int level)
 
        while (ip < end) {
                ip_offset = ip - header->code;
-               g_print ("IL_%04x: %02x\n", ip_offset, *ip);
+               g_print ("IL_%04x: %02x %s\n", ip_offset, *ip, mono_opcode_names [*ip]);
                if (start || !(code [ip_offset].flags & CODE_SEEN)) {
                        if (start) {
                                code [ip_offset].stack_count = 0;
@@ -1680,3 +1682,384 @@ invalid_cil:
        g_free (code);
        return list;
 }
+
+typedef struct {
+       const char *name;
+       guint64 offset;
+} FieldDesc;
+
+typedef struct {
+       const char *name;
+       const FieldDesc *fields;
+} ClassDesc;
+
+static const FieldDesc 
+typebuilder_fields[] = {
+       {"tname", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, name)},
+       {"nspace", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, nspace)},
+       {"parent", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, parent)},
+       {"interfaces", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, interfaces)},
+       {"methods", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, methods)},
+       {"properties", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, properties)},
+       {"fields", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, fields)},
+       {"attrs", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, attrs)},
+       {"table_idx", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, table_idx)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+modulebuilder_fields[] = {
+       {"types", G_STRUCT_OFFSET (MonoReflectionModuleBuilder, types)},
+       {"table_idx", G_STRUCT_OFFSET (MonoReflectionModuleBuilder, table_idx)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+assemblybuilder_fields[] = {
+       {"entry_point", G_STRUCT_OFFSET (MonoReflectionAssemblyBuilder, entry_point)},
+       {"modules", G_STRUCT_OFFSET (MonoReflectionAssemblyBuilder, modules)},
+       {"name", G_STRUCT_OFFSET (MonoReflectionAssemblyBuilder, name)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+ctorbuilder_fields[] = {
+       {"ilgen", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, ilgen)},
+       {"parameters", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, parameters)},
+       {"attrs", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, attrs)},
+       {"iattrs", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, iattrs)},
+       {"table_idx", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, table_idx)},
+       {"call_conv", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, call_conv)},
+       {"type", G_STRUCT_OFFSET (MonoReflectionCtorBuilder, type)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+methodbuilder_fields[] = {
+       {"mhandle", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, mhandle)},
+       {"rtype", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, rtype)},
+       {"parameters", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, parameters)},
+       {"attrs", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, attrs)},
+       {"iattrs", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, iattrs)},
+       {"name", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, name)},
+       {"table_idx", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, table_idx)},
+       {"code", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, code)},
+       {"ilgen", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, ilgen)},
+       {"type", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, type)},
+       {"pinfo", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, pinfo)},
+       {"pi_dll", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, dll)},
+       {"pi_entry", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, dllentry)},
+       {"ncharset", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, charset)},
+       {"native_cc", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, native_cc)},
+       {"call_conv", G_STRUCT_OFFSET (MonoReflectionMethodBuilder, call_conv)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+fieldbuilder_fields[] = {
+       {"attrs", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, attrs)},
+       {"type", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, type)},
+       {"name", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, name)},
+       {"def_value", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, def_value)},
+       {"offset", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, offset)},
+       {"table_idx", G_STRUCT_OFFSET (MonoReflectionFieldBuilder, table_idx)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+propertybuilder_fields[] = {
+       {"attrs", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, attrs)},
+       {"name", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, name)},
+       {"type", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, type)},
+       {"parameters", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, parameters)},
+       {"def_value", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, def_value)},
+       {"set_method", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, set_method)},
+       {"get_method", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, get_method)},
+       {"table_idx", G_STRUCT_OFFSET (MonoReflectionPropertyBuilder, table_idx)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+ilgenerator_fields[] = {
+       {"code", G_STRUCT_OFFSET (MonoReflectionILGen, code)},
+       {"mbuilder", G_STRUCT_OFFSET (MonoReflectionILGen, mbuilder)},
+       {"code_len", G_STRUCT_OFFSET (MonoReflectionILGen, code_len)},
+       {"max_stack", G_STRUCT_OFFSET (MonoReflectionILGen, max_stack)},
+       {"cur_stack", G_STRUCT_OFFSET (MonoReflectionILGen, cur_stack)},
+       {"locals", G_STRUCT_OFFSET (MonoReflectionILGen, locals)},
+       {"ex_handlers", G_STRUCT_OFFSET (MonoReflectionILGen, ex_handlers)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+ilexinfo_fields[] = {
+       {"handlers", G_STRUCT_OFFSET (MonoILExceptionInfo, handlers)},
+       {"start", G_STRUCT_OFFSET (MonoILExceptionInfo, start)},
+       {"len", G_STRUCT_OFFSET (MonoILExceptionInfo, len)},
+       {"end", G_STRUCT_OFFSET (MonoILExceptionInfo, label)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+ilexblock_fields[] = {
+       {"extype", G_STRUCT_OFFSET (MonoILExceptionBlock, extype)},
+       {"type", G_STRUCT_OFFSET (MonoILExceptionBlock, type)},
+       {"start", G_STRUCT_OFFSET (MonoILExceptionBlock, start)},
+       {"len", G_STRUCT_OFFSET (MonoILExceptionBlock, len)},
+       {"filter_offset", G_STRUCT_OFFSET (MonoILExceptionBlock, filter_offset)},
+       {NULL, 0}
+};
+
+static const ClassDesc
+emit_classes_to_check [] = {
+       {"TypeBuilder", typebuilder_fields},
+       {"ModuleBuilder", modulebuilder_fields},
+       {"AssemblyBuilder", assemblybuilder_fields},
+       {"ConstructorBuilder", ctorbuilder_fields},
+       {"MethodBuilder", methodbuilder_fields},
+       {"FieldBuilder", fieldbuilder_fields},
+       {"PropertyBuilder", propertybuilder_fields},
+       {"ILGenerator", ilgenerator_fields},
+       {"ILExceptionBlock", ilexblock_fields},
+       {"ILExceptionInfo", ilexinfo_fields},
+       {NULL, NULL}
+};
+
+static const FieldDesc 
+monoevent_fields[] = {
+       {"klass", G_STRUCT_OFFSET (MonoReflectionEvent, klass)},
+       {"handle", G_STRUCT_OFFSET (MonoReflectionEvent, event)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monoproperty_fields[] = {
+       {"klass", G_STRUCT_OFFSET (MonoReflectionProperty, klass)},
+       {"prop", G_STRUCT_OFFSET (MonoReflectionProperty, property)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monofield_fields[] = {
+       {"klass", G_STRUCT_OFFSET (MonoReflectionField, klass)},
+       {"fhandle", G_STRUCT_OFFSET (MonoReflectionField, field)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monomethodinfo_fields[] = {
+       {"parent", G_STRUCT_OFFSET (MonoMethodInfo, parent)},
+       {"ret", G_STRUCT_OFFSET (MonoMethodInfo, ret)},
+       {"name", G_STRUCT_OFFSET (MonoMethodInfo, name)},
+       {"attrs", G_STRUCT_OFFSET (MonoMethodInfo, attrs)},
+       {"iattrs", G_STRUCT_OFFSET (MonoMethodInfo, implattrs)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monopropertyinfo_fields[] = {
+       {"parent", G_STRUCT_OFFSET (MonoPropertyInfo, parent)},
+       {"name", G_STRUCT_OFFSET (MonoPropertyInfo, name)},
+       {"get_method", G_STRUCT_OFFSET (MonoPropertyInfo, get)},
+       {"set_method", G_STRUCT_OFFSET (MonoPropertyInfo, set)},
+       {"attrs", G_STRUCT_OFFSET (MonoPropertyInfo, attrs)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monofieldinfo_fields[] = {
+       {"parent", G_STRUCT_OFFSET (MonoFieldInfo, parent)},
+       {"type", G_STRUCT_OFFSET (MonoFieldInfo, type)},
+       {"name", G_STRUCT_OFFSET (MonoFieldInfo, name)},
+       {"attrs", G_STRUCT_OFFSET (MonoFieldInfo, attrs)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monomethod_fields[] = {
+       {"mhandle", G_STRUCT_OFFSET (MonoReflectionMethod, method)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+monocmethod_fields[] = {
+       {"mhandle", G_STRUCT_OFFSET (MonoReflectionMethod, method)},
+       {NULL, 0}
+};
+
+static const FieldDesc 
+pinfo_fields[] = {
+       {"ClassImpl", G_STRUCT_OFFSET (MonoReflectionParameter, ClassImpl)},
+       {"DefaultValueImpl", G_STRUCT_OFFSET (MonoReflectionParameter, DefaultValueImpl)},
+       {"MemberImpl", G_STRUCT_OFFSET (MonoReflectionParameter, MemberImpl)},
+       {"NameImpl", G_STRUCT_OFFSET (MonoReflectionParameter, NameImpl)},
+       {"PositionImpl", G_STRUCT_OFFSET (MonoReflectionParameter, PositionImpl)},
+       {"AttrsImpl", G_STRUCT_OFFSET (MonoReflectionParameter, AttrsImpl)},
+       {NULL, 0}
+};
+
+static const ClassDesc
+reflection_classes_to_check [] = {
+       {"MonoEvent", monoevent_fields},
+       {"MonoProperty", monoproperty_fields},
+       {"MonoField", monofield_fields},
+       {"MonoMethodInfo", monomethodinfo_fields},
+       {"MonoPropertyInfo", monopropertyinfo_fields},
+       {"MonoFieldInfo", monofieldinfo_fields},
+       {"MonoMethod", monomethod_fields},
+       {"MonoCMethod", monocmethod_fields},
+       {"ParameterInfo", pinfo_fields},
+       {NULL, NULL}
+};
+
+static FieldDesc 
+enuminfo_fields[] = {
+       {"utype", G_STRUCT_OFFSET (MonoEnumInfo, utype)},
+       {"values", G_STRUCT_OFFSET (MonoEnumInfo, values)},
+       {"names", G_STRUCT_OFFSET (MonoEnumInfo, names)},
+       {NULL, 0}
+};
+
+static FieldDesc 
+delegate_fields[] = {
+       {"target_type", G_STRUCT_OFFSET (MonoDelegate, target_type)},
+       {"m_target", G_STRUCT_OFFSET (MonoDelegate, target)},
+       {"method_name", G_STRUCT_OFFSET (MonoDelegate, method_name)},
+       {"method_ptr", G_STRUCT_OFFSET (MonoDelegate, method_ptr)},
+       {"delegate_trampoline", G_STRUCT_OFFSET (MonoDelegate, delegate_trampoline)},
+       {"method_info", G_STRUCT_OFFSET (MonoDelegate, method_info)},
+       {NULL, 0}
+};
+
+static FieldDesc 
+multicast_delegate_fields[] = {
+       {"prev", G_STRUCT_OFFSET (MonoMulticastDelegate, prev)},
+       {NULL, 0}
+};
+
+static FieldDesc 
+async_result_fields[] = {
+       {"async_state", G_STRUCT_OFFSET (MonoAsyncResult, async_state)},
+       {"handle", G_STRUCT_OFFSET (MonoAsyncResult, handle)},
+       {"async_delegate", G_STRUCT_OFFSET (MonoAsyncResult, async_delegate)},
+       {"data", G_STRUCT_OFFSET (MonoAsyncResult, data)},
+       {"sync_completed", G_STRUCT_OFFSET (MonoAsyncResult, sync_completed)},
+       {"completed", G_STRUCT_OFFSET (MonoAsyncResult, completed)},
+       {"endinvoke_called", G_STRUCT_OFFSET (MonoAsyncResult, endinvoke_called)},
+       {NULL, 0}
+};
+
+static const ClassDesc
+system_classes_to_check [] = {
+       {"MonoEnumInfo", enuminfo_fields},
+       {"Delegate", delegate_fields},
+       {"MulticastDelegate", multicast_delegate_fields},
+       {NULL, NULL}
+};
+
+static FieldDesc 
+mono_method_message_fields[] = {
+       {"method", G_STRUCT_OFFSET (MonoMethodMessage, method)},
+       {"args", G_STRUCT_OFFSET (MonoMethodMessage, args)},
+       {"names", G_STRUCT_OFFSET (MonoMethodMessage, names)},
+       {"arg_types", G_STRUCT_OFFSET (MonoMethodMessage, arg_types)},
+       {"ctx", G_STRUCT_OFFSET (MonoMethodMessage, ctx)},
+       {"rval", G_STRUCT_OFFSET (MonoMethodMessage, rval)},
+       {"exc", G_STRUCT_OFFSET (MonoMethodMessage, exc)},
+       {NULL, 0}
+};
+
+static const ClassDesc
+messaging_classes_to_check [] = {
+       {"AsyncResult", async_result_fields},
+       {"MonoMethodMessage", mono_method_message_fields},
+       {NULL, NULL}
+};
+
+static FieldDesc 
+transparent_proxy_fields[] = {
+       {"_rp", G_STRUCT_OFFSET (MonoTransparentProxy, rp)},
+       {NULL, 0}
+};
+
+static FieldDesc 
+real_proxy_fields[] = {
+       {"class_to_proxy", G_STRUCT_OFFSET (MonoRealProxy, class_to_proxy)},
+       {NULL, 0}
+};
+
+static const ClassDesc
+proxy_classes_to_check [] = {
+       {"TransparentProxy", transparent_proxy_fields},
+       {"RealProxy", real_proxy_fields},
+       {NULL, NULL}
+};
+
+static FieldDesc 
+wait_handle_fields[] = {
+       {"os_handle", G_STRUCT_OFFSET (MonoWaitHandle, handle)},
+       {"disposed", G_STRUCT_OFFSET (MonoWaitHandle, disposed)},
+       {NULL, 0}
+};
+
+static const ClassDesc
+threading_classes_to_check [] = {
+       {"WaitHandle", wait_handle_fields},
+       {NULL, NULL}
+};
+
+typedef struct {
+       const char *name;
+       const ClassDesc *types;
+} NameSpaceDesc;
+
+static const NameSpaceDesc
+namespaces_to_check[] = {
+       {"System.Runtime.Remoting.Proxies", proxy_classes_to_check},
+       {"System.Runtime.Remoting.Messaging", messaging_classes_to_check},
+       {"System.Reflection.Emit", emit_classes_to_check},
+       {"System.Reflection", reflection_classes_to_check},
+       {"System.Threading", threading_classes_to_check},
+       {"System", system_classes_to_check},
+       {NULL, NULL}
+};
+
+static char*
+check_corlib (MonoImage *corlib)
+{
+       MonoClass *klass;
+       MonoClassField *field;
+       const FieldDesc *fdesc;
+       const ClassDesc *cdesc;
+       const NameSpaceDesc *ndesc;
+       gint struct_offset;
+
+       for (ndesc = namespaces_to_check; ndesc->name; ++ndesc) {
+               for (cdesc = ndesc->types; cdesc->name; ++cdesc) {
+                       klass = mono_class_from_name (corlib, ndesc->name, cdesc->name);
+                       if (!klass)
+                               return g_strdup_printf ("Cannot find class %s", cdesc->name);
+                       mono_class_init (klass);
+                       /*
+                        * FIXME: we should also check the size of valuetypes, or
+                        * we're going to have trouble when we access them in arrays.
+                        */
+                       if (klass->valuetype)
+                               struct_offset = 8;
+                       else
+                               struct_offset = 0;
+                       for (fdesc = cdesc->fields; fdesc->name; ++fdesc) {
+                               field = mono_class_get_field_from_name (klass, fdesc->name);
+                               if (!field || (field->offset != (fdesc->offset + struct_offset)))
+                                       return g_strdup_printf ("field `%s' mismatch in class %s (%ld != %ld)", fdesc->name, cdesc->name, (long) fdesc->offset, (long) (field?field->offset:-1));
+                       }
+               }
+       }
+       return NULL;
+}
+
+char*
+mono_verify_corlib () {
+       return check_corlib (mono_defaults.corlib);
+}
+