Mon May 26 15:21:21 CEST 2003 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Mon, 26 May 2003 14:25:45 +0000 (14:25 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Mon, 26 May 2003 14:25:45 +0000 (14:25 -0000)
* mini-ops.h, mini.c, inssel.brg, exceptions.cs: validate arguments passed
to a method (including results of ldelema, bug#43207).

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

mono/mini/ChangeLog
mono/mini/exceptions.cs
mono/mini/inssel.brg
mono/mini/mini-ops.h
mono/mini/mini.c

index b41a722f43238ba99b4761cea28f64dca8e5e7e0..ee5afbe53d1ecea2e9ba83b92fd8de84510de227 100644 (file)
@@ -1,3 +1,9 @@
+
+Mon May 26 15:21:21 CEST 2003 Paolo Molaro <lupus@ximian.com>
+
+       * mini-ops.h, mini.c, inssel.brg, exceptions.cs: validate arguments passed
+       to a method (including results of ldelema, bug#43207).
+
 2003-05-26  Dietmar Maurer  <dietmar@ximian.com>
 
        * inssel-x86.brg (OP_OUTARG_VT): dont push zero sized structures
index 1db43de32c8599149d00649bb3a2b1643b9ef2f6..2b8638ea0c88e0d1e5ffad96ba84caefe0bf0f34 100644 (file)
@@ -1489,5 +1489,31 @@ class Tests {
                        return 0;
                return 200;
        }
+
+       static void helper_out_obj (out object o) {
+               o = (object)"buddy";
+       }
+
+       static void helper_out_string (out string o) {
+               o = "buddy";
+       }
+
+       static int test_2_array_mismatch () {
+               string[] a = { "hello", "world" };
+               object[] b = a;
+               bool passed = false;
+
+               try {
+                       helper_out_obj (out b [1]);
+               } catch (ArrayTypeMismatchException) {
+                       passed = true;
+               }
+               if (!passed)
+                       return 0;
+               helper_out_string (out a [1]);
+               if (a [1] != "buddy")
+                       return 1;
+               return 2;
+       }
 }
 
index 8a8aab59228f617ad690947ef1d33e6a69a1156d..3ed1611c3941a587fa9d25a0d50e4f85ae2ce37c 100644 (file)
@@ -1532,6 +1532,22 @@ reg: CEE_LDLEN (reg) {
                                   state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
 }
 
+reg: OP_CHECK_ARRAY_TYPE (reg) {
+       int vtable_reg = mono_regstate_next_int (s->rs);
+       int class_reg = mono_regstate_next_int (s->rs);
+       int elclass_reg = mono_regstate_next_int (s->rs);
+
+       MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, vtable_reg, 
+                                      state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
+       MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, class_reg, 
+                                      vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+       MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, elclass_reg, 
+                                      class_reg, G_STRUCT_OFFSET (MonoClass, element_class));
+       MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, elclass_reg, tree->klass);
+       MONO_EMIT_NEW_COND_EXC (s, NE_UN, "ArrayTypeMismatchException");
+       MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
+}
+
 reg: CEE_LDELEMA (reg, OP_ICONST) "15" {
        int length_reg = mono_regstate_next_int (s->rs);
        guint32 size = mono_class_array_element_size (tree->klass);
index 65746377e52de700c6c7c2859ca894e023c7f498..0acb2980b9bc9a48f67c7e79c2ac625c3c9687f2 100644 (file)
@@ -51,6 +51,7 @@ MINI_OP(OP_REGVAR,    "regvar")
 MINI_OP(OP_REG,                "reg")
 MINI_OP(OP_REGOFFSET,  "regoffset")
 MINI_OP(OP_LABEL,      "label")
+MINI_OP(OP_CHECK_ARRAY_TYPE,   "check_array_type")
 
 MINI_OP(OP_STORE_MEMBASE_IMM,"store_membase_imm")
 MINI_OP(OP_STORE_MEMBASE_REG,"store_membase_reg")
index 7eb766851b13f54b1760d275bc062fe800ca8cab..ac90c53eb3eb592aacceb9ae72f3ef17243124c1 100644 (file)
@@ -1630,6 +1630,104 @@ handle_loaded_temps (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst **stack,
        }
 }
 
+/*
+ * Prepare arguments for passing to a function call.
+ * Return a non-zero value if the arguments can't be passed to the given
+ * signature.
+ * The type checks are not yet complete and some conversions may need
+ * casts on 32 or 64 bit architectures.
+ */
+static int
+check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args)
+{
+       int i, simple_type;
+
+       if (sig->hasthis) {
+               if (args [0]->type != STACK_OBJ && args [0]->type != STACK_MP && args [0]->type != STACK_PTR)
+                       return 1;
+               args++;
+       }
+       for (i = 0; i < sig->param_count; ++i) {
+               if (sig->params [i]->byref) {
+                       /* 
+                        * check the result of ldelema is only passed as an argument if the byref
+                        * type matches exactly the array element type.
+                        * FIXME: if the argument as been saved on the stack as part of the
+                        * interface variable code (the value was on the stack at a basic block boundary)
+                        * we need to add the check in that case, too.
+                        */
+                       if (args [i]->opcode == CEE_LDELEMA) {
+                               MonoInst *check;
+                               MonoClass *exact_class = mono_class_from_mono_type (sig->params [i]);
+                               if (!exact_class->valuetype) {
+                                       MONO_INST_NEW (cfg, check, OP_CHECK_ARRAY_TYPE);
+                                       check->cil_code = args [i]->cil_code;
+                                       check->klass = exact_class;
+                                       check->inst_left = args [i]->inst_left;
+                                       check->type = STACK_OBJ;
+                                       args [i]->inst_left = check;
+                               }
+                       }
+                       if (args [i]->type != STACK_MP && args [i]->type != STACK_PTR)
+                               return 1;
+                       continue;
+               }
+               simple_type = sig->params [i]->type;
+handle_enum:
+               switch (simple_type) {
+               case MONO_TYPE_VOID:
+                       return 1;
+                       continue;
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+                       if (args [i]->type != STACK_I4 && args [i]->type != STACK_PTR)
+                               return 1;
+                       continue;
+               case MONO_TYPE_I:
+               case MONO_TYPE_U:
+               case MONO_TYPE_PTR:
+                       if (args [i]->type != STACK_I4 && args [i]->type != STACK_PTR && args [i]->type != STACK_MP)
+                               return 1;
+                       continue;
+               case MONO_TYPE_CLASS:
+               case MONO_TYPE_STRING:
+               case MONO_TYPE_OBJECT:
+               case MONO_TYPE_SZARRAY:
+               case MONO_TYPE_ARRAY:    
+                       if (args [i]->type != STACK_OBJ)
+                               return 1;
+                       continue;
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+                       if (args [i]->type != STACK_I8)
+                               return 1;
+                       continue;
+               case MONO_TYPE_R4:
+               case MONO_TYPE_R8:
+                       if (args [i]->type != STACK_R8)
+                               return 1;
+                       continue;
+               case MONO_TYPE_VALUETYPE:
+                       if (sig->params [i]->data.klass->enumtype) {
+                               simple_type = sig->params [i]->data.klass->enum_basetype->type;
+                               goto handle_enum;
+                       }
+                       if (args [i]->type != STACK_VTYPE)
+                               return 1;
+                       continue;
+               default:
+                       g_error ("unknown type 0x%02x in check_call_signature", simple_type);
+               }
+       }
+       return 0;
+}
+
 inline static int
 mono_spill_call (MonoCompile *cfg, MonoBasicBlock *bblock, MonoCallInst *call, MonoMethodSignature *sig, gboolean ret_object, 
                 const guint8 *ip, gboolean to_end)
@@ -2822,6 +2920,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        sp -= n;
 
+                       if (*ip != CEE_CALLI && check_call_signature (cfg, fsig, sp))
+                               goto unverified;
+
                        if ((ins_flag & MONO_INST_TAILCALL) && cmethod && (*ip == CEE_CALL)) {
                                int i;
                                for (i = 0; i < n; ++i) {