2007-11-07 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Wed, 7 Nov 2007 11:31:29 +0000 (11:31 -0000)
committerMark Probst <mark.probst@gmail.com>
Wed, 7 Nov 2007 11:31:29 +0000 (11:31 -0000)
* icall.c: Safety checks in InitializeArray.  Fixes bug #324535.

2007-11-07  Mark Probst  <mark.probst@gmail.com>

* mini.c: Abort inlining call to InitializeArray if something
looks wrong.  Let the icall handle it, which now has proper safety
checks.

2007-11-07  Mark Probst  <mark.probst@gmail.com>

* bug-324535.cs, bug-324535-il.il: Added.

* Makefile.am: Added test for bug #324525.

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

mono/metadata/ChangeLog
mono/metadata/icall.c
mono/mini/ChangeLog
mono/mini/mini.c
mono/tests/ChangeLog
mono/tests/Makefile.am
mono/tests/bug-324535-il.il [new file with mode: 0644]
mono/tests/bug-324535.cs [new file with mode: 0644]

index 4ddfc49fa0b7314afa3210ed22a94a46c4e9cabb..d60cef084533fb3f10a1b479be235bd070cb5397 100644 (file)
@@ -1,3 +1,7 @@
+2007-11-07  Mark Probst  <mark.probst@gmail.com>
+
+       * icall.c: Safety checks in InitializeArray.  Fixes bug #324535.
+
 2007-11-06  Sebastien Pouliot  <sebastien@ximian.com> 
 
        * object.c: Fix mono_string_to_utf8 to handle NULL values inside the
index d7f88ac45f7107c10f2868e1aa2d7346a7697928..5fa3cd2f4334595cb7f819cc25bf2a4965e33b9a 100644 (file)
@@ -718,9 +718,32 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoAr
 {
        MonoClass *klass = array->obj.vtable->klass;
        guint32 size = mono_array_element_size (klass);
+       MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
+       int align;
+
+       if (MONO_TYPE_IS_REFERENCE (type) ||
+                       (type->type == MONO_TYPE_VALUETYPE &&
+                               (!mono_type_get_class (type) ||
+                               mono_type_get_class (type)->has_references))) {
+               MonoException *exc = mono_get_exception_argument("array",
+                       "Cannot initialize array containing references");
+               mono_raise_exception (exc);
+       }
+
+       if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
+               MonoException *exc = mono_get_exception_argument("field_handle",
+                       "Field doesn't have an RVA");
+               mono_raise_exception (exc);
+       }
 
        size *= array->max_length;
 
+       if (size > mono_type_size (field_handle->type, &align)) {
+               MonoException *exc = mono_get_exception_argument("field_handle",
+                       "Field not large enough to fill array");
+               mono_raise_exception (exc);
+       }
+
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
 #define SWAP(n) {\
        guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
@@ -734,7 +757,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoAr
 
        /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
 
-       switch (mono_type_get_underlying_type (&klass->element_class->byval_arg)->type) {
+       switch (type->type) {
        case MONO_TYPE_CHAR:
        case MONO_TYPE_I2:
        case MONO_TYPE_U2:
index ab38058aeee7141e0c1e4eb86af9c7feb8ea731e..883c42f96f57c55f4fa3a2e407810b051384f846 100644 (file)
@@ -1,3 +1,9 @@
+2007-11-07  Mark Probst  <mark.probst@gmail.com>
+
+       * mini.c: Abort inlining call to InitializeArray if something
+       looks wrong.  Let the icall handle it, which now has proper safety
+       checks.
+
 2007-11-05  Rodrigo Kumpera  <rkumpera@novell.com>
 
        * mini.c (mono_spill_call): add support for soft-float.
index defdd344f7da45fec40c88dfbde1613a4ea1dc4a..8897ca7f594e17480f1c704d993fc3a20c84336e 100644 (file)
@@ -3963,11 +3963,19 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono
         */
        if (ip [0] == CEE_DUP && ip [1] == CEE_LDTOKEN && ip [5] == 0x4 && ip [6] == CEE_CALL) {
                MonoClass *klass = newarr->inst_newa_class;
+               guint32 field_token = read32 (ip + 2);
+               guint32 field_index = field_token & 0xffffff;
                guint32 token = read32 (ip + 7);
-               guint32 rva, field_index;
+               guint32 rva;
                const char *data_ptr;
                int size = 0;
                MonoMethod *cmethod;
+               MonoClass *dummy_class;
+               MonoClassField *field = mono_field_from_token (method->klass->image, field_token, &dummy_class, NULL);
+               int dummy_align;
+
+               if (!field)
+                       return NULL;
 
                if (newarr->inst_newa_len->opcode != OP_ICONST)
                        return NULL;
@@ -4003,6 +4011,8 @@ initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, Mono
                        return NULL;
                }
                size *= newarr->inst_newa_len->inst_c0;
+               if (size > mono_type_size (field->type, &dummy_align))
+                   return NULL;
                *out_size = size;
                /*g_print ("optimized in %s: size: %d, numelems: %d\n", method->name, size, newarr->inst_newa_len->inst_c0);*/
                field_index = read32 (ip + 2) & 0xffffff;
index 3846abf21df3f271f29f8292bd0262c89e7efdb4..72c785e2947b7f8b17b05b742dc3c12565d21ec4 100644 (file)
@@ -1,3 +1,9 @@
+2007-11-07  Mark Probst  <mark.probst@gmail.com>
+
+       * bug-324535.cs, bug-324535-il.il: Added.
+
+       * Makefile.am: Added test for bug #324525.
+
 2007-11-05 Rodrigo Kumpera  <rkumpera@novell.com>
 
        * soft-float-tests.cs: Tests for soft-float.
index 9083159dab6e754c09929bc473533403d726b424..babfc28d5d2d47e81cdb8ad12917f086405414e0 100644 (file)
@@ -351,14 +351,14 @@ EXTRA_DIST=test-driver $(TEST_CS_SRC) $(TEST_CS2_SRC) $(TEST_IL_SRC) $(TEST_IL2_
 
 # mkbundle works on ppc, but the pkg-config POC doesn't when run with make test
 if POWERPC
-test:  assemblyresolve/test/asm.dll testjit test-type-load test-inline-call-stack test-bug-80307 test-bug-81673 test-bug-81691 test-bug-81466
+test:  assemblyresolve/test/asm.dll testjit test-type-load test-inline-call-stack test-bug-80307 test-bug-81673 test-bug-81691 test-bug-81466 test-bug-324535
 else
 # Can't use mkbundle on win32 since there is no static build there
 # Can't run test-unhandled-exception on Windows because of all the debug popups...
 if PLATFORM_WIN32
-test:   assemblyresolve/test/asm.dll testjit test-type-load test-inline-call-stack test-bug-80307 test-bug-81673 test-bug-81691 test-bug-81466
+test:   assemblyresolve/test/asm.dll testjit test-type-load test-inline-call-stack test-bug-80307 test-bug-81673 test-bug-81691 test-bug-81466 test-bug-324535
 else
-test:  assemblyresolve/test/asm.dll testjit testbundle test-type-load test-inline-call-stack test-iomap-regression test-bug-80307 test-bug-81673 test-bug-81691 test-bug-81466
+test:  assemblyresolve/test/asm.dll testjit testbundle test-type-load test-inline-call-stack test-iomap-regression test-bug-80307 test-bug-81673 test-bug-81691 test-bug-81466 test-bug-324535
 endif
 endif
 
@@ -605,6 +605,14 @@ bug-81466.exe: bug-81466.il bug-81466-lib.dll
 test-bug-81466: bug-81466.exe bug-81466-lib.dll
        $(RUNTIME) bug-81466.exe
 
+EXTRA_DIST += bug-324535-il.il bug-324535.cs
+bug-324535-il.dll : bug-324535-il.il
+       $(ILASM) /dll /output:bug-324535-il.dll $(srcdir)/bug-324535-il.il
+bug-324535.exe : bug-324535.cs bug-324535-il.dll
+       $(MCS) -r:bug-324535-il.dll -out:bug-324535.exe $(srcdir)/bug-324535.cs
+test-bug-324535 : bug-324535.exe bug-324535-il.dll
+       $(RUNTIME) bug-324535.exe
+
 EXTRA_DIST += make_imt_test.sh
 imt_big_iface_test.cs: $(srcdir)/make_imt_test.sh
        $(srcdir)/make_imt_test.sh > imt_big_iface_test.cs
diff --git a/mono/tests/bug-324535-il.il b/mono/tests/bug-324535-il.il
new file mode 100644 (file)
index 0000000..f44b260
--- /dev/null
@@ -0,0 +1,110 @@
+.assembly extern mscorlib
+{
+  .ver 1:0:5000:0
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'bug-324535-il'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+.module 'bug-324535-il.dll' // GUID = {60452EB2-5BE7-4A6D-A5BB-CCC19EA7F8EF}
+
+
+  .class public auto ansi beforefieldinit Generator
+       extends [mscorlib]System.Object
+  {
+    .field  private static  int32[] fld
+
+    // method line 1
+    .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 Generator::.ctor
+
+    // method line 2
+    .method public static  hidebysig 
+           default object fieldOverflow ()  cil managed 
+    {
+        // Method begins at RVA 0x20f4
+       // Code size 20 (0x14)
+       .maxstack 4
+       .locals init (
+               int32[] V_0)
+       IL_0000:  ldc.i4.5
+       IL_0001:  newarr [mscorlib]System.Int32
+       IL_0006:  dup 
+       IL_0007:  ldtoken field valuetype '<PrivateImplementationDetails>'/$ArrayType$16 '<PrivateImplementationDetails>'::'$$field-0'
+       IL_000c:  call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
+       IL_0011:  stloc.0 
+       IL_0012:  ldloc.0 
+       IL_0013:  ret 
+    } // end of method Generator::fieldOverflow
+
+    // method line 3
+    .method public static  hidebysig 
+           default object referenceArray ()  cil managed 
+    {
+        // Method begins at RVA 0x2114
+       // Code size 2 (0x2)
+       .maxstack 8
+       IL_0016:  ldc.i4.2
+       IL_0017:  newarr [mscorlib]System.Object
+                       dup
+                       ldtoken field valuetype '<PrivateImplementationDetails>'/$ArrayType$16 '<PrivateImplementationDetails>'::'$$field-0'
+                       call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
+       IL_0001:  ret 
+    } // end of method Generator::referenceArray
+
+    // method line 4
+    .method public static  hidebysig 
+           default object nonRVAField ()  cil managed 
+    {
+        // Method begins at RVA 0x2118
+       // Code size 2 (0x2)
+       .maxstack 8
+       IL_0000:  ldc.i4.1
+       IL_0001:  newarr [mscorlib]System.Int32
+       IL_0006:  dup 
+       IL_0007:  ldtoken field int32[] Generator::fld
+       IL_000c:  call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
+       IL_0013:  ret 
+    } // end of method Generator::nonRVAField
+
+  } // end of class Generator
+
+  .class private auto ansi '<PrivateImplementationDetails>'
+       extends [mscorlib]System.Object
+  {
+    .field  assembly static  valuetype '<PrivateImplementationDetails>'/$ArrayType$16 '$$field-0' at D_0000211c
+
+    // method line 5
+    .method public specialname  rtspecialname 
+           instance default void .ctor ()  cil managed 
+    {
+        // Method begins at RVA 0x212c
+       // Code size 7 (0x7)
+       .maxstack 8
+       IL_0000:  ldarg.0 
+       IL_0001:  call instance void object::.ctor()
+       IL_0006:  ret 
+    } // end of method <PrivateImplementationDetails>::.ctor
+
+  .class nested private explicit ansi sealed $ArrayType$16
+       extends [mscorlib]System.ValueType
+  {
+    .pack 1
+    .size 16
+
+  } // end of class $ArrayType$16
+
+  } // end of class <PrivateImplementationDetails>
+
+.data D_0000211c = bytearray (
+        01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00) // size: 16
diff --git a/mono/tests/bug-324535.cs b/mono/tests/bug-324535.cs
new file mode 100644 (file)
index 0000000..ccf605a
--- /dev/null
@@ -0,0 +1,36 @@
+using System;
+
+class Test
+{
+    static int Main ()
+    {
+       bool exc = false;
+       try {
+           Generator.fieldOverflow();
+       } catch (ArgumentException e) {
+           exc = true;
+           //Console.WriteLine(e.ToString());
+       }
+       if (!exc) return 1;
+
+       exc = false;
+       try {
+           Generator.referenceArray();
+       } catch (ArgumentException e) {
+           exc = true;
+           //Console.WriteLine(e.ToString());
+       }
+       if (!exc) return 1;
+
+       exc = false;
+       try {
+           Generator.nonRVAField();
+       } catch (ArgumentException e) {
+           exc = true;
+           //Console.WriteLine(e.ToString());
+       }
+       if (!exc) return 1;
+
+       return 0;
+    }
+}