2009-09-15 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Tue, 15 Sep 2009 12:50:12 +0000 (12:50 -0000)
committerMark Probst <mark.probst@gmail.com>
Tue, 15 Sep 2009 12:50:12 +0000 (12:50 -0000)
        * class.c (mono_class_init): Always set an exception in a class if
        vtable setup fails.  Fixes #538577.

        * generic-sharing.c: Raise an exception if mono_class_vtable()
        returns NULL.

2009-09-15  Mark Probst  <mark.probst@gmail.com>

        * generic-type-load-exception.2.il: Test case for vtable setup
        failure in shared generic code.

        * Makefile.am: Test added.

svn path=/trunk/mono/; revision=141954

mono/metadata/ChangeLog
mono/metadata/class.c
mono/metadata/generic-sharing.c
mono/tests/ChangeLog
mono/tests/Makefile.am
mono/tests/generic-type-load-exception.2.il [new file with mode: 0644]

index 66e72d7649a6064d24ace67f144a55b7e0ba9fe7..c28b7611f460dbd1e152dc4b2c378b49185d7db9 100644 (file)
@@ -1,3 +1,11 @@
+2009-09-15  Mark Probst  <mark.probst@gmail.com>
+
+       * class.c (mono_class_init): Always set an exception in a class if
+       vtable setup fails.  Fixes #538577.
+
+       * generic-sharing.c: Raise an exception if mono_class_vtable()
+       returns NULL.
+
 2009-09-13  Zoltan Varga  <vargaz@gmail.com>
 
        * marshal.c (mono_marshal_get_runtime_invoke): Don't share instance 
index 2e14c7232ede4712abefaebfe62b2616804c4f8b..5861b469e676ea07aafe9d09a57a326abb28d2f2 100644 (file)
@@ -3952,8 +3952,10 @@ mono_class_init (MonoClass *class)
                class->has_cctor = gklass->has_cctor;
 
                mono_class_setup_vtable (gklass);
-               if (gklass->exception_type)
+               if (gklass->exception_type) {
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto fail;
+               }
 
                class->vtable_size = gklass->vtable_size;
        } else {
@@ -4041,12 +4043,20 @@ mono_class_init (MonoClass *class)
                if (class->parent) {
                        /* This will compute class->parent->vtable_size for some classes */
                        mono_class_init (class->parent);
-                       if (class->parent->exception_type || mono_loader_get_last_error ())
+                       if (class->parent->exception_type) {
+                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                               goto fail;
+                       }
+                       if (mono_loader_get_last_error ())
                                goto fail;
                        if (!class->parent->vtable_size) {
                                /* FIXME: Get rid of this somehow */
                                mono_class_setup_vtable (class->parent);
-                               if (class->parent->exception_type || mono_loader_get_last_error ())
+                               if (class->parent->exception_type) {
+                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                                       goto fail;
+                               }
+                               if (mono_loader_get_last_error ())
                                        goto fail;
                        }
                        setup_interface_offsets (class, class->parent->vtable_size);
index 47b5a370f9c737f80a68ebb145920c6fa1d2934d..690c87ed70f6e644f20a4f6370b4647500c4078f 100644 (file)
@@ -722,12 +722,20 @@ static gpointer
 class_type_info (MonoDomain *domain, MonoClass *class, int info_type)
 {
        switch (info_type) {
-       case MONO_RGCTX_INFO_STATIC_DATA:
-               return mono_class_vtable (domain, class)->data;
+       case MONO_RGCTX_INFO_STATIC_DATA: {
+               MonoVTable *vtable = mono_class_vtable (domain, class);
+               if (!vtable)
+                       mono_raise_exception (mono_class_get_exception_for_failure (class));
+               return vtable->data;
+       }
        case MONO_RGCTX_INFO_KLASS:
                return class;
-       case MONO_RGCTX_INFO_VTABLE:
-               return mono_class_vtable (domain, class);
+       case MONO_RGCTX_INFO_VTABLE: {
+               MonoVTable *vtable = mono_class_vtable (domain, class);
+               if (!vtable)
+                       mono_raise_exception (mono_class_get_exception_for_failure (class));
+               return vtable;
+       }
        default:
                g_assert_not_reached ();
        }
@@ -791,12 +799,16 @@ instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTe
                return data;
        case MONO_RGCTX_INFO_METHOD_RGCTX: {
                MonoMethodInflated *method = data;
+               MonoVTable *vtable;
 
                g_assert (method->method.method.is_inflated);
                g_assert (method->context.method_inst);
 
-               return mono_method_lookup_rgctx (mono_class_vtable (domain, method->method.method.klass),
-                       method->context.method_inst);
+               vtable = mono_class_vtable (domain, method->method.method.klass);
+               if (!vtable)
+                       mono_raise_exception (mono_class_get_exception_for_failure (method->method.method.klass));
+
+               return mono_method_lookup_rgctx (vtable, method->context.method_inst);
        }
        case MONO_RGCTX_INFO_METHOD_CONTEXT: {
                MonoMethodInflated *method = data;
index 17f97c524a5a76a2e8c17ae087d73801f63bd3d6..171cc9548259db380eed2ca6d42281f74b542259 100644 (file)
@@ -1,3 +1,10 @@
+2009-09-15  Mark Probst  <mark.probst@gmail.com>
+
+       * generic-type-load-exception.2.il: Test case for vtable setup
+       failure in shared generic code.
+
+       * Makefile.am: Test added.
+
 2009-09-13  Zoltan Varga  <vargaz@gmail.com>
 
        * runtime-invoke.cs: Add a test.
index 9759fb4dad59972a2c72768ef0f0917e542b47d4..af51de3780da45b0b20fd55579625013b28f8585 100644 (file)
@@ -455,6 +455,7 @@ TEST_IL_SRC=                        \
        generic-valuetype-newobj2.2.il  \
        generic-valuetype-newobj.2.il   \
        generic-constrained.2.il        \
+       generic-type-load-exception.2.il        \
        bug-81466.il    \
        bug457574.il    \
        bug445361.il    \
@@ -780,7 +781,8 @@ test-generic-sharing : generics-sharing.2.exe shared-generic-methods.2.exe  \
                generic-sealed-virtual.2.exe generic-system-arrays.2.exe        \
                generic-stack-traces.2.exe generic-stack-traces2.2.exe          \
                bug-472600.2.exe bug-473482.2.exe bug-473999.2.exe              \
-               bug-479763.2.exe generic-xdomain.2.exe
+               bug-479763.2.exe generic-xdomain.2.exe                          \
+               generic-type-load-exception.2.exe
        @for fn in $+ ; do      \
                echo "Testing $$fn ...";        \
                MONO_GENERIC_SHARING=all $(RUNTIME) -O=gshared                $$fn > $$fn.stdout || exit 1;     \
diff --git a/mono/tests/generic-type-load-exception.2.il b/mono/tests/generic-type-load-exception.2.il
new file mode 100644 (file)
index 0000000..2bfd8e5
--- /dev/null
@@ -0,0 +1,154 @@
+.assembly extern mscorlib
+{
+  .ver 2:0:0:0
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'typeloadexcgeneric'
+{
+  .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() =  (
+               01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
+               63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01       ) // ceptionThrows.
+
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+.module typeloadexcgeneric.exe // GUID = {877F6CE7-B3D8-4CC7-AEB0-DA6A9DB96059}
+
+
+  .class interface private auto ansi abstract IFoo
+  {
+
+    // method line 1
+    .method public virtual  hidebysig  newslot  abstract 
+           instance default int32 A ()  cil managed 
+    {
+        // Method begins at RVA 0x0
+    } // end of method IFoo::A
+
+    // method line 2
+    .method public virtual  hidebysig  newslot  abstract 
+           instance default int32 B ()  cil managed 
+    {
+        // Method begins at RVA 0x0
+    } // end of method IFoo::B
+
+  } // end of class IFoo
+
+  .class private auto ansi beforefieldinit Foo`1<T>
+       extends [mscorlib]System.Object
+       implements IFoo  {
+
+    // method line 3
+    .method public hidebysig  specialname  rtspecialname 
+           instance default void '.ctor' ()  cil managed 
+    {
+        // Method begins at RVA 0x20ec
+       // Code size 7 (0x7)
+       .maxstack 8
+       IL_0000:  ldarg.0 
+       IL_0001:  call instance void object::'.ctor'()
+       IL_0006:  ret 
+    } // end of method Foo`1::.ctor
+
+    // method line 4
+    .method public final  virtual  hidebysig  newslot 
+           instance default int32 A ()  cil managed 
+    {
+        // Method begins at RVA 0x20f4
+       // Code size 2 (0x2)
+       .maxstack 8
+       IL_0000:  ldc.i4.1 
+       IL_0001:  ret 
+    } // end of method Foo`1::A
+  } // end of class Foo`1
+
+  .class private auto ansi beforefieldinit Bar`1<T>
+       extends [mscorlib]System.Object
+  {
+
+    // method line 6
+    .method public hidebysig  specialname  rtspecialname 
+           instance default void '.ctor' ()  cil managed 
+    {
+        // Method begins at RVA 0x20fc
+       // Code size 7 (0x7)
+       .maxstack 8
+       IL_0000:  ldarg.0 
+       IL_0001:  call instance void object::'.ctor'()
+       IL_0006:  ret 
+    } // end of method Bar`1::.ctor
+
+    // method line 7
+    .method public hidebysig 
+           instance default void work ()  cil managed 
+    {
+        // Method begins at RVA 0x2104
+       // Code size 33 (0x21)
+       .maxstack 5
+       .locals init (
+               class Foo`1<!T> V_0)
+       IL_0000:  newobj instance void class Foo`1<!T>::'.ctor'()
+       IL_0005:  stloc.0 
+       IL_0006:  ldstr "A "
+       IL_000b:  ldloc.0 
+       IL_000c:  callvirt instance int32 class Foo`1<!T>::A()
+       IL_0011:  box [mscorlib]System.Int32
+       IL_0016:  call string string::Concat(object, object)
+       IL_001b:  call void class [mscorlib]System.Console::WriteLine(string)
+       IL_0020:  ret 
+    } // end of method Bar`1::work
+
+  } // end of class Bar`1
+
+  .class public auto ansi beforefieldinit main
+       extends [mscorlib]System.Object
+  {
+
+    // method line 8
+    .method public hidebysig  specialname  rtspecialname 
+           instance default void '.ctor' ()  cil managed 
+    {
+        // Method begins at RVA 0x2134
+       // Code size 7 (0x7)
+       .maxstack 8
+       IL_0000:  ldarg.0 
+       IL_0001:  call instance void object::'.ctor'()
+       IL_0006:  ret 
+    } // end of method main::.ctor
+
+    // method line 9
+    .method public static  hidebysig 
+           default int32 Main ()  cil managed 
+    {
+        // Method begins at RVA 0x213c
+       .entrypoint
+       // Code size 34 (0x22)
+       .maxstack 4
+       .locals init (
+               class Bar`1<string>     V_0,
+               int32   V_1)
+       IL_0000:  newobj instance void class Bar`1<string>::'.ctor'()
+       IL_0005:  stloc.0 
+       .try { // 0
+         IL_0006:  ldloc.0 
+         IL_0007:  callvirt instance void class Bar`1<string>::work()
+         IL_000c:  leave IL_001e
+
+       } // end .try 0
+       catch class [mscorlib]System.TypeLoadException { // 0
+         IL_0011:  pop 
+         IL_0012:  ldc.i4.0 
+         IL_0013:  stloc.1 
+         IL_0014:  leave IL_0020
+
+         IL_0019:  leave IL_001e
+
+       } // end handler 0
+       IL_001e:  ldc.i4.1 
+       IL_001f:  ret 
+       IL_0020:  ldloc.1 
+       IL_0021:  ret 
+    } // end of method main::Main
+
+  } // end of class main
+