When inflating a (M)VAR make sure we're not using a broken type.
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 1 Nov 2012 20:23:50 +0000 (16:23 -0400)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 1 Nov 2012 21:49:25 +0000 (17:49 -0400)
*class.c (inflate_generic_type): When inflating (M)VAR we must
check if the replaced type is not void or typedbyref as both can
later lead to all sorts of nasty crashes or memory corruption.

mono/metadata/class.c
mono/tests/Makefile.am
mono/tests/invalid_generic_instantiation.il [new file with mode: 0644]

index 7f51f22629ddad51add1cfe5480a2fc0edd1d798..933cd46c942c8caf2be635d3d208c79a2b0ac0a7 100644 (file)
@@ -513,6 +513,21 @@ mono_class_is_open_constructed_type (MonoType *t)
        }
 }
 
+/*
+This is a simple function to catch the most common bad instances of generic types.
+Specially those that might lead to further failures in the runtime.
+*/
+static gboolean
+is_valid_generic_argument (MonoType *type)
+{
+       switch (type->type) {
+       case MONO_TYPE_VOID:
+       case MONO_TYPE_TYPEDBYREF:
+               return FALSE;
+       }
+       return TRUE;
+}
+
 static MonoType*
 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
 {
@@ -532,6 +547,12 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                        return NULL;
                }
 
+               if (!is_valid_generic_argument (inst->type_argv [num])) {
+                       MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
+                       mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
+                               num, info ? info->name : "", inst->type_argv [num]->type);
+                       return NULL;                    
+               }
                /*
                 * Note that the VAR/MVAR cases are different from the rest.  The other cases duplicate @type,
                 * while the VAR/MVAR duplicates a type from the context.  So, we need to ensure that the
@@ -554,6 +575,12 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont
                                num, info ? info->name : "", inst->type_argc);
                        return NULL;
                }
+               if (!is_valid_generic_argument (inst->type_argv [num])) {
+                       MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
+                       mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
+                               num, info ? info->name : "", inst->type_argv [num]->type);
+                       return NULL;                    
+               }
                nt = mono_metadata_type_dup (image, inst->type_argv [num]);
                nt->byref = type->byref;
                nt->attrs = type->attrs;
index 5892416ab226de191b5ca8b8019f4e05c5ab4ecf..bfb9be065089345c736603b245796cad2b865227 100644 (file)
@@ -548,7 +548,8 @@ TEST_IL_SRC=                        \
        bug-633291.il   \
        delegate-with-null-target.il    \
        bug-318677.il   \
-       gsharing-valuetype-layout.il
+       gsharing-valuetype-layout.il    \
+       invalid_generic_instantiation.il
 
 
 # pre-requisite test sources: files that are not test themselves
diff --git a/mono/tests/invalid_generic_instantiation.il b/mono/tests/invalid_generic_instantiation.il
new file mode 100644 (file)
index 0000000..2d28245
--- /dev/null
@@ -0,0 +1,109 @@
+.assembly extern mscorlib
+{
+  .ver 4:0:0:0
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'repro'
+{
+  .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 repro.exe // GUID = {5C01F6E6-77DE-4AB1-AD74-6AA56EAA8CD8}
+
+
+  .class private auto ansi beforefieldinit Foo`1<T>
+       extends [mscorlib]System.Object
+  {
+    .field  private  !0 t
+
+    // method line 1
+    .method public hidebysig specialname rtspecialname 
+           instance default void '.ctor' ()  cil managed 
+    {
+        // Method begins at RVA 0x20ec
+       // Code size 22 (0x16)
+       .maxstack 4
+       .locals init (
+               !T      V_0)
+       IL_0000:  ldarg.0 
+       IL_0001:  call instance void object::'.ctor'()
+       IL_0006:  ldarg.0 
+       IL_0007:  ldloca.s 0
+       IL_0009:  initobj !0
+       IL_000f:  ldloc.0 
+       IL_0010:  stfld !0 class Foo`1<!0>::t
+       IL_0015:  ret 
+    } // end of method Foo`1::.ctor
+
+  } // end of class Foo`1
+
+  .class private auto ansi beforefieldinit Program
+       extends [mscorlib]System.Object
+  {
+
+    // method line 2
+    .method public hidebysig specialname rtspecialname 
+           instance default void '.ctor' ()  cil managed 
+    {
+        // Method begins at RVA 0x2110
+       // Code size 7 (0x7)
+       .maxstack 8
+       IL_0000:  ldarg.0 
+       IL_0001:  call instance void object::'.ctor'()
+       IL_0006:  ret 
+    } // end of method Program::.ctor
+
+    // method line 3
+    .method private static hidebysig 
+           default void CreateInvalidInstantiation ()  cil managed noinlining 
+    {
+        // Method begins at RVA 0x2118
+       // Code size 7 (0x7)
+       .maxstack 8
+       IL_0000:  newobj instance void class Foo`1<void>::'.ctor'()
+       IL_0005:  pop 
+       IL_0006:  ret 
+    } // end of method Program::CreateInvalidInstantiation
+
+    // method line 4
+    .method private static hidebysig 
+           default int32 Main ()  cil managed 
+    {
+        // Method begins at RVA 0x2120
+       .entrypoint
+       // Code size 52 (0x34)
+       .maxstack 3
+       .locals init (
+               int32   V_0)
+       .try { // 0
+         IL_0000:  call void class Program::CreateInvalidInstantiation()
+         IL_0005:  ldstr "NO EXCEPTION"
+         IL_000a:  call void class [mscorlib]System.Console::WriteLine(string)
+         IL_000f:  ldc.i4.1 
+         IL_0010:  stloc.0 
+         IL_0011:  leave IL_0032
+
+         IL_0016:  leave IL_0032
+
+       } // end .try 0
+       catch class [mscorlib]System.TypeLoadException { // 0
+         IL_001b:  pop 
+         IL_001c:  ldstr "OK"
+         IL_0021:  call void class [mscorlib]System.Console::WriteLine(string)
+         IL_0026:  ldc.i4.0 
+         IL_0027:  stloc.0 
+         IL_0028:  leave IL_0032
+
+         IL_002d:  leave IL_0032
+
+       } // end handler 0
+       IL_0032:  ldloc.0 
+       IL_0033:  ret 
+    } // end of method Program::Main
+
+  } // end of class Program
+