Casts must be to realizable types.
[mono.git] / mono / metadata / verify.c
1 /*
2  * verify.c: 
3  *
4  * Author:
5  *      Mono Project (http://www.mono-project.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  */
10 #include <config.h>
11
12 #include <mono/metadata/object-internals.h>
13 #include <mono/metadata/verify.h>
14 #include <mono/metadata/verify-internals.h>
15 #include <mono/metadata/opcodes.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/reflection.h>
18 #include <mono/metadata/debug-helpers.h>
19 #include <mono/metadata/mono-endian.h>
20 #include <mono/metadata/metadata.h>
21 #include <mono/metadata/metadata-internals.h>
22 #include <mono/metadata/class-internals.h>
23 #include <mono/metadata/security-manager.h>
24 #include <mono/metadata/security-core-clr.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/mono-basic-block.h>
27 #include <mono/utils/mono-counters.h>
28 #include <mono/utils/monobitset.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <ctype.h>
32
33 static MiniVerifierMode verifier_mode = MONO_VERIFIER_MODE_OFF;
34 static gboolean verify_all = FALSE;
35
36 /*
37  * Set the desired level of checks for the verfier.
38  * 
39  */
40 void
41 mono_verifier_set_mode (MiniVerifierMode mode)
42 {
43         verifier_mode = mode;
44 }
45
46 void
47 mono_verifier_enable_verify_all ()
48 {
49         verify_all = TRUE;
50 }
51
52 #ifndef DISABLE_VERIFIER
53 /*
54  * Pull the list of opcodes
55  */
56 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
57         a = i,
58
59 enum {
60 #include "mono/cil/opcode.def"
61         LAST = 0xff
62 };
63 #undef OPDEF
64
65 #ifdef MONO_VERIFIER_DEBUG
66 #define VERIFIER_DEBUG(code) do { code } while (0)
67 #else
68 #define VERIFIER_DEBUG(code)
69 #endif
70
71 //////////////////////////////////////////////////////////////////
72 #define IS_STRICT_MODE(ctx) (((ctx)->level & MONO_VERIFY_NON_STRICT) == 0)
73 #define IS_FAIL_FAST_MODE(ctx) (((ctx)->level & MONO_VERIFY_FAIL_FAST) == MONO_VERIFY_FAIL_FAST)
74 #define IS_SKIP_VISIBILITY(ctx) (((ctx)->level & MONO_VERIFY_SKIP_VISIBILITY) == MONO_VERIFY_SKIP_VISIBILITY)
75 #define IS_REPORT_ALL_ERRORS(ctx) (((ctx)->level & MONO_VERIFY_REPORT_ALL_ERRORS) == MONO_VERIFY_REPORT_ALL_ERRORS)
76 #define CLEAR_PREFIX(ctx, prefix) do { (ctx)->prefix_set &= ~(prefix); } while (0)
77 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception)    \
78         do {    \
79                 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1);      \
80                 vinfo->info.status = __status;  \
81                 vinfo->info.message = ( __msg );        \
82                 vinfo->exception_type = (__exception);  \
83                 (__ctx)->list = g_slist_prepend ((__ctx)->list, vinfo); \
84         } while (0)
85
86 //TODO support MONO_VERIFY_REPORT_ALL_ERRORS
87 #define ADD_VERIFY_ERROR(__ctx, __msg)  \
88         do {    \
89                 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
90                 (__ctx)->valid = 0; \
91         } while (0)
92
93 #define CODE_NOT_VERIFIABLE(__ctx, __msg) \
94         do {    \
95                 if ((__ctx)->verifiable || IS_REPORT_ALL_ERRORS (__ctx)) { \
96                         ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_NOT_VERIFIABLE, MONO_EXCEPTION_UNVERIFIABLE_IL); \
97                         (__ctx)->verifiable = 0; \
98                         if (IS_FAIL_FAST_MODE (__ctx)) \
99                                 (__ctx)->valid = 0; \
100                 } \
101         } while (0)
102
103 #define ADD_VERIFY_ERROR2(__ctx, __msg, __exception)    \
104         do {    \
105                 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, __exception); \
106                 (__ctx)->valid = 0; \
107         } while (0)
108
109 #define CODE_NOT_VERIFIABLE2(__ctx, __msg, __exception) \
110         do {    \
111                 if ((__ctx)->verifiable || IS_REPORT_ALL_ERRORS (__ctx)) { \
112                         ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_NOT_VERIFIABLE, __exception); \
113                         (__ctx)->verifiable = 0; \
114                         if (IS_FAIL_FAST_MODE (__ctx)) \
115                                 (__ctx)->valid = 0; \
116                 } \
117         } while (0)
118
119 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
120 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
121
122 #if SIZEOF_VOID_P == 4
123 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
124 #else
125 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
126 #endif
127
128 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
129 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
130
131 /*Flags to be used with ILCodeDesc::flags */
132 enum {
133         /*Instruction has not been processed.*/
134         IL_CODE_FLAG_NOT_PROCESSED  = 0,
135         /*Instruction was decoded by mono_method_verify loop.*/
136         IL_CODE_FLAG_SEEN = 1,
137         /*Instruction was target of a branch or is at a protected block boundary.*/
138         IL_CODE_FLAG_WAS_TARGET = 2,
139         /*Used by stack_init to avoid double initialize each entry.*/
140         IL_CODE_FLAG_STACK_INITED = 4,
141         /*Used by merge_stacks to decide if it should just copy the eval stack.*/
142         IL_CODE_STACK_MERGED = 8,
143         /*This instruction is part of the delegate construction sequence, it cannot be target of a branch.*/
144         IL_CODE_DELEGATE_SEQUENCE = 0x10,
145         /*This is a delegate created from a ldftn to a non final virtual method*/
146         IL_CODE_LDFTN_DELEGATE_NONFINAL_VIRTUAL = 0x20,
147         /*This is a call to a non final virtual method*/
148         IL_CODE_CALL_NONFINAL_VIRTUAL = 0x40,
149 };
150
151 typedef enum {
152         RESULT_VALID,
153         RESULT_UNVERIFIABLE,
154         RESULT_INVALID
155 } verify_result_t;
156
157 typedef struct {
158         MonoType *type;
159         int stype;
160         MonoMethod *method;
161 } ILStackDesc;
162
163
164 typedef struct {
165         ILStackDesc *stack;
166         guint16 size, max_size;
167         guint16 flags;
168 } ILCodeDesc;
169
170 typedef struct {
171         int max_args;
172         int max_stack;
173         int verifiable;
174         int valid;
175         int level;
176
177         int code_size;
178         ILCodeDesc *code;
179         ILCodeDesc eval;
180
181         MonoType **params;
182         GSList *list;
183         /*Allocated fnptr MonoType that should be freed by us.*/
184         GSList *funptrs;
185         /*Type dup'ed exception types from catch blocks.*/
186         GSList *exception_types;
187
188         int num_locals;
189         MonoType **locals;
190
191         /*TODO get rid of target here, need_merge in mono_method_verify and hoist the merging code in the branching code*/
192         int target;
193
194         guint32 ip_offset;
195         MonoMethodSignature *signature;
196         MonoMethodHeader *header;
197
198         MonoGenericContext *generic_context;
199         MonoImage *image;
200         MonoMethod *method;
201
202         /*This flag helps solving a corner case of delegate verification in that you cannot have a "starg 0" 
203          *on a method that creates a delegate for a non-final virtual method using ldftn*/
204         gboolean has_this_store;
205
206         /*This flag is used to control if the contructor of the parent class has been called.
207          *If the this pointer is pushed on the eval stack and it's a reference type constructor and
208          * super_ctor_called is false, the uninitialized flag is set on the pushed value.
209          * 
210          * Poping an uninitialized this ptr from the eval stack is an unverifiable operation unless
211          * the safe variant is used. Only a few opcodes can use it : dup, pop, ldfld, stfld and call to a constructor.
212          */
213         gboolean super_ctor_called;
214
215         guint32 prefix_set;
216         gboolean has_flags;
217         MonoType *constrained_type;
218 } VerifyContext;
219
220 static void
221 merge_stacks (VerifyContext *ctx, ILCodeDesc *from, ILCodeDesc *to, gboolean start, gboolean external);
222
223 static int
224 get_stack_type (MonoType *type);
225
226 static gboolean
227 mono_delegate_signature_equal (MonoMethodSignature *delegate_sig, MonoMethodSignature *method_sig, gboolean is_static_ldftn);
228
229 static gboolean
230 mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass);
231
232 static gboolean
233 mono_method_is_valid_generic_instantiation (VerifyContext *ctx, MonoMethod *method);
234 //////////////////////////////////////////////////////////////////
235
236
237
238 enum {
239         TYPE_INV = 0, /* leave at 0. */
240         TYPE_I4  = 1,
241         TYPE_I8  = 2,
242         TYPE_NATIVE_INT = 3,
243         TYPE_R8  = 4,
244         /* Used by operator tables to resolve pointer types (managed & unmanaged) and by unmanaged pointer types*/
245         TYPE_PTR  = 5,
246         /* value types and classes */
247         TYPE_COMPLEX = 6,
248         /* Number of types, used to define the size of the tables*/
249         TYPE_MAX = 6,
250
251         /* Used by tables to signal that a result is not verifiable*/
252         NON_VERIFIABLE_RESULT = 0x80,
253
254         /*Mask used to extract just the type, excluding flags */
255         TYPE_MASK = 0x0F,
256
257         /* The stack type is a managed pointer, unmask the value to res */
258         POINTER_MASK = 0x100,
259         
260         /*Stack type with the pointer mask*/
261         RAW_TYPE_MASK = 0x10F,
262
263         /* Controlled Mutability Manager Pointer */
264         CMMP_MASK = 0x200,
265
266         /* The stack type is a null literal*/
267         NULL_LITERAL_MASK = 0x400,
268         
269         /**Used by ldarg.0 and family to let delegate verification happens.*/
270         THIS_POINTER_MASK = 0x800,
271
272         /**Signals that this is a boxed value type*/
273         BOXED_MASK = 0x1000,
274
275         /*This is an unitialized this ref*/
276         UNINIT_THIS_MASK = 0x2000,
277 };
278
279 static const char* const
280 type_names [TYPE_MAX + 1] = {
281         "Invalid",
282         "Int32",
283         "Int64",
284         "Native Int",
285         "Float64",
286         "Native Pointer",
287         "Complex"       
288 };
289
290 enum {
291         PREFIX_UNALIGNED = 1,
292         PREFIX_VOLATILE  = 2,
293         PREFIX_TAIL      = 4,
294         PREFIX_CONSTRAINED = 8,
295         PREFIX_READONLY = 16
296 };
297 //////////////////////////////////////////////////////////////////
298
299 #ifdef ENABLE_VERIFIER_STATS
300
301 #define MEM_ALLOC(amt) do { allocated_memory += (amt); working_set += (amt); } while (0)
302 #define MEM_FREE(amt) do { working_set -= (amt); } while (0)
303
304 static int allocated_memory;
305 static int working_set;
306 static int max_allocated_memory;
307 static int max_working_set;
308 static int total_allocated_memory;
309
310 static void
311 finish_collect_stats (void)
312 {
313         max_allocated_memory = MAX (max_allocated_memory, allocated_memory);
314         max_working_set = MAX (max_working_set, working_set);
315         total_allocated_memory += allocated_memory;
316         allocated_memory = working_set = 0;
317 }
318
319 static void
320 init_verifier_stats (void)
321 {
322         static gboolean inited;
323         if (!inited) {
324                 inited = TRUE;
325                 mono_counters_register ("Maximum memory allocated during verification", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &max_allocated_memory);
326                 mono_counters_register ("Maximum memory used during verification", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &max_working_set);
327                 mono_counters_register ("Total memory allocated for verification", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &total_allocated_memory);
328         }
329 }
330
331 #else
332
333 #define MEM_ALLOC(amt) do {} while (0)
334 #define MEM_FREE(amt) do { } while (0)
335
336 #define finish_collect_stats()
337 #define init_verifier_stats()
338
339 #endif
340
341
342 //////////////////////////////////////////////////////////////////
343
344
345 /*Token validation macros and functions */
346 #define IS_MEMBER_REF(token) (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF)
347 #define IS_METHOD_DEF(token) (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
348 #define IS_METHOD_SPEC(token) (mono_metadata_token_table (token) == MONO_TABLE_METHODSPEC)
349 #define IS_FIELD_DEF(token) (mono_metadata_token_table (token) == MONO_TABLE_FIELD)
350
351 #define IS_TYPE_REF(token) (mono_metadata_token_table (token) == MONO_TABLE_TYPEREF)
352 #define IS_TYPE_DEF(token) (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
353 #define IS_TYPE_SPEC(token) (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC)
354 #define IS_METHOD_DEF_OR_REF_OR_SPEC(token) (IS_METHOD_DEF (token) || IS_MEMBER_REF (token) || IS_METHOD_SPEC (token))
355 #define IS_TYPE_DEF_OR_REF_OR_SPEC(token) (IS_TYPE_DEF (token) || IS_TYPE_REF (token) || IS_TYPE_SPEC (token))
356 #define IS_FIELD_DEF_OR_REF(token) (IS_FIELD_DEF (token) || IS_MEMBER_REF (token))
357
358 /*
359  * Verify if @token refers to a valid row on int's table.
360  */
361 static gboolean
362 token_bounds_check (MonoImage *image, guint32 token)
363 {
364         if (image->dynamic)
365                 return mono_reflection_is_valid_dynamic_token ((MonoDynamicImage*)image, token);
366         return image->tables [mono_metadata_token_table (token)].rows >= mono_metadata_token_index (token);
367 }
368
369 static MonoType *
370 mono_type_create_fnptr_from_mono_method (VerifyContext *ctx, MonoMethod *method)
371 {
372         MonoType *res = g_new0 (MonoType, 1);
373         MEM_ALLOC (sizeof (MonoType));
374
375         //FIXME use mono_method_get_signature_full
376         res->data.method = mono_method_signature (method);
377         res->type = MONO_TYPE_FNPTR;
378         ctx->funptrs = g_slist_prepend (ctx->funptrs, res);
379         return res;
380 }
381
382 /*
383  * mono_type_is_enum_type:
384  * 
385  * Returns TRUE if @type is an enum type. 
386  */
387 static gboolean
388 mono_type_is_enum_type (MonoType *type)
389 {
390         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
391                 return TRUE;
392         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
393                 return TRUE;
394         return FALSE;
395 }
396
397 /*
398  * mono_type_is_value_type:
399  * 
400  * Returns TRUE if @type is named after @namespace.@name.
401  * 
402  */
403 static gboolean
404 mono_type_is_value_type (MonoType *type, const char *namespace, const char *name)
405 {
406         return type->type == MONO_TYPE_VALUETYPE &&
407                 !strcmp (namespace, type->data.klass->name_space) &&
408                 !strcmp (name, type->data.klass->name);
409 }
410
411 /*
412  * Returns TURE if @type is VAR or MVAR
413  */
414 static gboolean
415 mono_type_is_generic_argument (MonoType *type)
416 {
417         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
418 }
419
420 /*
421  * mono_type_get_underlying_type_any:
422  * 
423  * This functions is just like mono_type_get_underlying_type but it doesn't care if the type is byref.
424  * 
425  * Returns the underlying type of @type regardless if it is byref or not.
426  */
427 static MonoType*
428 mono_type_get_underlying_type_any (MonoType *type)
429 {
430         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
431                 return mono_class_enum_basetype (type->data.klass);
432         if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
433                 return mono_class_enum_basetype (type->data.generic_class->container_class);
434         return type;
435 }
436
437 static G_GNUC_UNUSED const char*
438 mono_type_get_stack_name (MonoType *type)
439 {
440         return type_names [get_stack_type (type) & TYPE_MASK];
441 }
442
443 #define CTOR_REQUIRED_FLAGS (METHOD_ATTRIBUTE_SPECIAL_NAME | METHOD_ATTRIBUTE_RT_SPECIAL_NAME)
444 #define CTOR_INVALID_FLAGS (METHOD_ATTRIBUTE_STATIC)
445
446 static gboolean
447 mono_method_is_constructor (MonoMethod *method) 
448 {
449         return ((method->flags & CTOR_REQUIRED_FLAGS) == CTOR_REQUIRED_FLAGS &&
450                         !(method->flags & CTOR_INVALID_FLAGS) &&
451                         !strcmp (".ctor", method->name));
452 }
453
454 static gboolean
455 mono_class_has_default_constructor (MonoClass *klass)
456 {
457         MonoMethod *method;
458         int i;
459
460         mono_class_setup_methods (klass);
461         if (klass->exception_type)
462                 return FALSE;
463
464         for (i = 0; i < klass->method.count; ++i) {
465                 method = klass->methods [i];
466                 if (mono_method_is_constructor (method) &&
467                         mono_method_signature (method) &&
468                         mono_method_signature (method)->param_count == 0 &&
469                         (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)
470                         return TRUE;
471         }
472         return FALSE;
473 }
474
475 /*
476  * Verify if @type is valid for the given @ctx verification context.
477  * this function checks for VAR and MVAR types that are invalid under the current verifier,
478  */
479 static gboolean
480 mono_type_is_valid_type_in_context (MonoType *type, MonoGenericContext *context)
481 {
482         int i;
483         MonoGenericInst *inst;
484
485         switch (type->type) {
486         case MONO_TYPE_VAR:
487         case MONO_TYPE_MVAR:
488                 if (!context)
489                         return FALSE;
490                 inst = type->type == MONO_TYPE_VAR ? context->class_inst : context->method_inst;
491                 if (!inst || mono_type_get_generic_param_num (type) >= inst->type_argc)
492                         return FALSE;
493                 break;
494         case MONO_TYPE_SZARRAY:
495                 return mono_type_is_valid_type_in_context (&type->data.klass->byval_arg, context);
496         case MONO_TYPE_ARRAY:
497                 return mono_type_is_valid_type_in_context (&type->data.array->eklass->byval_arg, context);
498         case MONO_TYPE_PTR:
499                 return mono_type_is_valid_type_in_context (type->data.type, context);
500         case MONO_TYPE_GENERICINST:
501                 inst = type->data.generic_class->context.class_inst;
502                 if (!inst->is_open)
503                         break;
504                 for (i = 0; i < inst->type_argc; ++i)
505                         if (!mono_type_is_valid_type_in_context (inst->type_argv [i], context))
506                                 return FALSE;
507                 break;
508         case MONO_TYPE_CLASS:
509         case MONO_TYPE_VALUETYPE: {
510                 MonoClass *klass = type->data.klass;
511                 /*
512                  * It's possible to encode generic'sh types in such a way that they disguise themselves as class or valuetype.
513                  * Fixing the type decoding is really tricky since under some cases this behavior is needed, for example, to
514                  * have a 'class' type pointing to a 'genericinst' class.
515                  *
516                  * For the runtime these non canonical (weird) encodings work fine, they worst they can cause is some
517                  * reflection oddities which are harmless  - to security at least.
518                  */
519                 if (klass->byval_arg.type != type->type)
520                         return mono_type_is_valid_type_in_context (&klass->byval_arg, context);
521                 break;
522         }
523         }
524         return TRUE;
525 }
526
527 /*This function returns NULL if the type is not instantiatable*/
528 static MonoType*
529 verifier_inflate_type (VerifyContext *ctx, MonoType *type, MonoGenericContext *context)
530 {
531         MonoError error;
532         MonoType *result;
533
534         result = mono_class_inflate_generic_type_checked (type, context, &error);
535         if (!mono_error_ok (&error)) {
536                 mono_error_cleanup (&error);
537                 return NULL;
538         }
539         return result;
540 }
541
542
543 static gboolean
544 is_valid_generic_instantiation (MonoGenericContainer *gc, MonoGenericContext *context, MonoGenericInst *ginst)
545 {
546         MonoError error;
547         int i;
548
549         if (ginst->type_argc != gc->type_argc)
550                 return FALSE;
551
552         for (i = 0; i < gc->type_argc; ++i) {
553                 MonoGenericParamInfo *param_info = mono_generic_container_get_param_info (gc, i);
554                 MonoClass *paramClass;
555                 MonoClass **constraints;
556                 MonoType *param_type = ginst->type_argv [i];
557
558                 /*it's not our job to validate type variables*/
559                 if (mono_type_is_generic_argument (param_type))
560                         continue;
561
562                 paramClass = mono_class_from_mono_type (param_type);
563
564                 if (paramClass->exception_type != MONO_EXCEPTION_NONE)
565                         return FALSE;
566
567                 /* A GTD can't be a generic argument.
568                  *
569                  * Due to how types are encoded we must check for the case of a genericinst MonoType and GTD MonoClass.
570                  * This happens in cases such as: class Foo<T>  { void X() { new Bar<T> (); } }
571                  *
572                  * Open instantiations can have GTDs as this happens when one type is instantiated with others params
573                  * and the former has an expansion into the later. For example:
574                  * class B<K> {}
575                  * class A<T>: B<K> {}
576                  * The type A <K> has a parent B<K>, that is inflated into the GTD B<>.
577                  * Since A<K> is open, thus not instantiatable, this is valid.
578                  */
579                 if (paramClass->generic_container && param_type->type != MONO_TYPE_GENERICINST && !ginst->is_open)
580                         return FALSE;
581
582                 /*it's not safe to call mono_class_init from here*/
583                 if (paramClass->generic_class && !paramClass->inited) {
584                         if (!mono_class_is_valid_generic_instantiation (NULL, paramClass))
585                                 return FALSE;
586                 }
587
588                 if (!param_info->constraints && !(param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK))
589                         continue;
590
591                 if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && (!paramClass->valuetype || mono_class_is_nullable (paramClass)))
592                         return FALSE;
593
594                 if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && paramClass->valuetype)
595                         return FALSE;
596
597                 if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !paramClass->valuetype && !mono_class_has_default_constructor (paramClass))
598                         return FALSE;
599
600                 if (!param_info->constraints)
601                         continue;
602
603                 for (constraints = param_info->constraints; *constraints; ++constraints) {
604                         MonoClass *ctr = *constraints;
605                         MonoType *inflated;
606
607                         inflated = mono_class_inflate_generic_type_checked (&ctr->byval_arg, context, &error);
608                         if (!mono_error_ok (&error)) {
609                                 mono_error_cleanup (&error);
610                                 return FALSE;
611                         }
612                         ctr = mono_class_from_mono_type (inflated);
613                         mono_metadata_free_type (inflated);
614
615                         if (!mono_class_is_assignable_from_slow (ctr, paramClass))
616                                 return FALSE;
617                 }
618         }
619         return TRUE;
620 }
621
622 /*
623  * Return true if @candidate is constraint compatible with @target.
624  * 
625  * This means that @candidate constraints are a super set of @target constaints
626  */
627 static gboolean
628 mono_generic_param_is_constraint_compatible (VerifyContext *ctx, MonoGenericParam *target, MonoGenericParam *candidate, MonoClass *candidate_param_class, MonoGenericContext *context)
629 {
630         MonoGenericParamInfo *tinfo = mono_generic_param_info (target);
631         MonoGenericParamInfo *cinfo = mono_generic_param_info (candidate);
632
633         int tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
634         int cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
635         if ((tmask & cmask) != tmask)
636                 return FALSE;
637
638         if (tinfo->constraints) {
639                 MonoClass **target_class, **candidate_class;
640                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
641                         MonoClass *tc;
642                         MonoType *inflated = verifier_inflate_type (ctx, &(*target_class)->byval_arg, context);
643                         if (!inflated)
644                                 return FALSE;
645                         tc = mono_class_from_mono_type (inflated);
646                         mono_metadata_free_type (inflated);
647
648                         /*
649                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
650                          * check it's constraints since it satisfy the constraint by itself.
651                          */
652                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate_param_class->byval_arg))
653                                 continue;
654
655                         if (!cinfo->constraints)
656                                 return FALSE;
657
658                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
659                                 MonoClass *cc;
660                                 inflated = verifier_inflate_type (ctx, &(*candidate_class)->byval_arg, ctx->generic_context);
661                                 if (!inflated)
662                                         return FALSE;
663                                 cc = mono_class_from_mono_type (inflated);
664                                 mono_metadata_free_type (inflated);
665
666                                 if (mono_class_is_assignable_from (tc, cc))
667                                         break;
668                         }
669                         if (!*candidate_class)
670                                 return FALSE;
671                 }
672         }
673         return TRUE;
674 }
675
676 static MonoGenericParam*
677 verifier_get_generic_param_from_type (VerifyContext *ctx, MonoType *type)
678 {
679         MonoGenericContainer *gc;
680         MonoMethod *method = ctx->method;
681         int num;
682
683         num = mono_type_get_generic_param_num (type);
684
685         if (type->type == MONO_TYPE_VAR) {
686                 MonoClass *gtd = method->klass;
687                 if (gtd->generic_class)
688                         gtd = gtd->generic_class->container_class;
689                 gc = gtd->generic_container;
690         } else { //MVAR
691                 MonoMethod *gmd = method;
692                 if (method->is_inflated)
693                         gmd = ((MonoMethodInflated*)method)->declaring;
694                 gc = mono_method_get_generic_container (gmd);
695         }
696         if (!gc)
697                 return FALSE;
698         return mono_generic_container_get_param (gc, num);
699 }
700
701
702
703 /*
704  * Verify if @type is valid for the given @ctx verification context.
705  * this function checks for VAR and MVAR types that are invalid under the current verifier,
706  * This means that it either 
707  */
708 static gboolean
709 is_valid_type_in_context (VerifyContext *ctx, MonoType *type)
710 {
711         return mono_type_is_valid_type_in_context (type, ctx->generic_context);
712 }
713
714 static gboolean
715 is_valid_generic_instantiation_in_context (VerifyContext *ctx, MonoGenericInst *ginst)
716 {
717         int i;
718         for (i = 0; i < ginst->type_argc; ++i) {
719                 MonoType *type = ginst->type_argv [i];
720                 if (!is_valid_type_in_context (ctx, type))
721                         return FALSE;
722         }
723         return TRUE;
724 }
725
726 static gboolean
727 generic_arguments_respect_constraints (VerifyContext *ctx, MonoGenericContainer *gc, MonoGenericContext *context, MonoGenericInst *ginst)
728 {
729         int i;
730         for (i = 0; i < ginst->type_argc; ++i) {
731                 MonoType *type = ginst->type_argv [i];
732                 MonoGenericParam *target = mono_generic_container_get_param (gc, i);
733                 MonoGenericParam *candidate;
734                 MonoClass *candidate_class;
735
736                 if (!mono_type_is_generic_argument (type))
737                         continue;
738
739                 if (!is_valid_type_in_context (ctx, type))
740                         return FALSE;
741
742                 candidate = verifier_get_generic_param_from_type (ctx, type);
743                 candidate_class = mono_class_from_mono_type (type);
744
745                 if (!mono_generic_param_is_constraint_compatible (ctx, target, candidate, candidate_class, context))
746                         return FALSE;
747         }
748         return TRUE;
749 }
750
751 static gboolean
752 mono_method_repect_method_constraints (VerifyContext *ctx, MonoMethod *method)
753 {
754         MonoMethodInflated *gmethod = (MonoMethodInflated *)method;
755         MonoGenericInst *ginst = gmethod->context.method_inst;
756         MonoGenericContainer *gc = mono_method_get_generic_container (gmethod->declaring);
757         return !gc || generic_arguments_respect_constraints (ctx, gc, &gmethod->context, ginst);
758 }
759
760 static gboolean
761 mono_class_repect_method_constraints (VerifyContext *ctx, MonoClass *klass)
762 {
763         MonoGenericClass *gklass = klass->generic_class;
764         MonoGenericInst *ginst = gklass->context.class_inst;
765         MonoGenericContainer *gc = gklass->container_class->generic_container;
766         return !gc || generic_arguments_respect_constraints (ctx, gc, &gklass->context, ginst);
767 }
768
769 static gboolean
770 mono_method_is_valid_generic_instantiation (VerifyContext *ctx, MonoMethod *method)
771 {
772         MonoMethodInflated *gmethod = (MonoMethodInflated *)method;
773         MonoGenericInst *ginst = gmethod->context.method_inst;
774         MonoGenericContainer *gc = mono_method_get_generic_container (gmethod->declaring);
775         if (!gc) /*non-generic inflated method - it's part of a generic type  */
776                 return TRUE;
777         if (ctx && !is_valid_generic_instantiation_in_context (ctx, ginst))
778                 return FALSE;
779         return is_valid_generic_instantiation (gc, &gmethod->context, ginst);
780
781 }
782
783 static gboolean
784 mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass)
785 {
786         MonoGenericClass *gklass = klass->generic_class;
787         MonoGenericInst *ginst = gklass->context.class_inst;
788         MonoGenericContainer *gc = gklass->container_class->generic_container;
789         if (ctx && !is_valid_generic_instantiation_in_context (ctx, ginst))
790                 return FALSE;
791         return is_valid_generic_instantiation (gc, &gklass->context, ginst);
792 }
793
794 static gboolean
795 mono_type_is_valid_in_context (VerifyContext *ctx, MonoType *type)
796 {
797         MonoClass *klass;
798
799         if (type == NULL) {
800                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid null type at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
801                 return FALSE;
802         }
803
804         if (!is_valid_type_in_context (ctx, type)) {
805                 char *str = mono_type_full_name (type);
806                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic type (%s%s) (argument out of range or %s is not generic) at 0x%04x",
807                         type->type == MONO_TYPE_VAR ? "!" : "!!",
808                         str,
809                         type->type == MONO_TYPE_VAR ? "class" : "method",
810                         ctx->ip_offset),
811                         MONO_EXCEPTION_BAD_IMAGE);              
812                 g_free (str);
813                 return FALSE;
814         }
815
816         klass = mono_class_from_mono_type (type);
817         mono_class_init (klass);
818         if (mono_loader_get_last_error () || klass->exception_type != MONO_EXCEPTION_NONE) {
819                 if (klass->generic_class && !mono_class_is_valid_generic_instantiation (NULL, klass))
820                         ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic instantiation of type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
821                 else
822                         ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
823                 mono_loader_clear_error ();
824                 return FALSE;
825         }
826
827         if (klass->generic_class && klass->generic_class->container_class->exception_type != MONO_EXCEPTION_NONE) {
828                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
829                 return FALSE;
830         }
831
832         if (!klass->generic_class)
833                 return TRUE;
834
835         if (!mono_class_is_valid_generic_instantiation (ctx, klass)) {
836                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic type instantiation of type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
837                 return FALSE;
838         }
839
840         if (!mono_class_repect_method_constraints (ctx, klass)) {
841                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic type instantiation of type %s.%s (generic args don't respect target's constraints) at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
842                 return FALSE;
843         }
844
845         return TRUE;
846 }
847
848 static verify_result_t
849 mono_method_is_valid_in_context (VerifyContext *ctx, MonoMethod *method)
850 {
851         if (!mono_type_is_valid_in_context (ctx, &method->klass->byval_arg))
852                 return RESULT_INVALID;
853
854         if (!method->is_inflated)
855                 return RESULT_VALID;
856
857         if (!mono_method_is_valid_generic_instantiation (ctx, method)) {
858                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic method instantiation of method %s.%s::%s at 0x%04x", method->klass->name_space, method->klass->name, method->name, ctx->ip_offset), MONO_EXCEPTION_UNVERIFIABLE_IL);
859                 return RESULT_INVALID;
860         }
861
862         if (!mono_method_repect_method_constraints (ctx, method)) {
863                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid generic method instantiation of method %s.%s::%s (generic args don't respect target's constraints) at 0x%04x", method->klass->name_space, method->klass->name, method->name, ctx->ip_offset));
864                 return RESULT_UNVERIFIABLE;
865         }
866         return RESULT_VALID;
867 }
868
869         
870 static MonoClassField*
871 verifier_load_field (VerifyContext *ctx, int token, MonoClass **out_klass, const char *opcode) {
872         MonoClassField *field;
873         MonoClass *klass = NULL;
874
875         if (!IS_FIELD_DEF_OR_REF (token) || !token_bounds_check (ctx->image, token)) {
876                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid field token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
877                 return NULL;
878         }
879
880         field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
881         if (!field || !field->parent || !klass || mono_loader_get_last_error ()) {
882                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load field from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
883                 mono_loader_clear_error ();
884                 return NULL;
885         }
886
887         if (!mono_type_is_valid_in_context (ctx, &klass->byval_arg))
888                 return NULL;
889
890         *out_klass = klass;
891         return field;
892 }
893
894 static MonoMethod*
895 verifier_load_method (VerifyContext *ctx, int token, const char *opcode) {
896         MonoMethod* method;
897         
898         if (!IS_METHOD_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
899                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid method token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
900                 return NULL;
901         }
902
903         method = mono_get_method_full (ctx->image, token, NULL, ctx->generic_context);
904
905         if (!method || mono_loader_get_last_error ()) {
906                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load method from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
907                 mono_loader_clear_error ();
908                 return NULL;
909         }
910         
911         if (mono_method_is_valid_in_context (ctx, method) == RESULT_INVALID)
912                 return NULL;
913
914         return method;
915 }
916
917 static MonoType*
918 verifier_load_type (VerifyContext *ctx, int token, const char *opcode) {
919         MonoType* type;
920         
921         if (!IS_TYPE_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
922                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid type token 0x%08x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
923                 return NULL;
924         }
925
926         type = mono_type_get_full (ctx->image, token, ctx->generic_context);
927
928         if (!type || mono_loader_get_last_error ()) {
929                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load type from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
930                 mono_loader_clear_error ();
931                 return NULL;
932         }
933
934         if (!mono_type_is_valid_in_context (ctx, type))
935                 return NULL;
936
937         return type;
938 }
939
940
941 /* stack_slot_get_type:
942  * 
943  * Returns the stack type of @value. This value includes POINTER_MASK.
944  * 
945  * Use this function to checks that account for a managed pointer.
946  */
947 static gint32
948 stack_slot_get_type (ILStackDesc *value)
949 {
950         return value->stype & RAW_TYPE_MASK;
951 }
952
953 /* stack_slot_get_underlying_type:
954  * 
955  * Returns the stack type of @value. This value does not include POINTER_MASK.
956  * 
957  * Use this function is cases where the fact that the value could be a managed pointer is
958  * irrelevant. For example, field load doesn't care about this fact of type on stack.
959  */
960 static gint32
961 stack_slot_get_underlying_type (ILStackDesc *value)
962 {
963         return value->stype & TYPE_MASK;
964 }
965
966 /* stack_slot_is_managed_pointer:
967  * 
968  * Returns TRUE is @value is a managed pointer.
969  */
970 static gboolean
971 stack_slot_is_managed_pointer (ILStackDesc *value)
972 {
973         return (value->stype & POINTER_MASK) == POINTER_MASK;
974 }
975
976 /* stack_slot_is_managed_mutability_pointer:
977  * 
978  * Returns TRUE is @value is a managed mutability pointer.
979  */
980 static G_GNUC_UNUSED gboolean
981 stack_slot_is_managed_mutability_pointer (ILStackDesc *value)
982 {
983         return (value->stype & CMMP_MASK) == CMMP_MASK;
984 }
985
986 /* stack_slot_is_null_literal:
987  * 
988  * Returns TRUE is @value is the null literal.
989  */
990 static gboolean
991 stack_slot_is_null_literal (ILStackDesc *value)
992 {
993         return (value->stype & NULL_LITERAL_MASK) == NULL_LITERAL_MASK;
994 }
995
996
997 /* stack_slot_is_this_pointer:
998  * 
999  * Returns TRUE is @value is the this literal
1000  */
1001 static gboolean
1002 stack_slot_is_this_pointer (ILStackDesc *value)
1003 {
1004         return (value->stype & THIS_POINTER_MASK) == THIS_POINTER_MASK;
1005 }
1006
1007 /* stack_slot_is_boxed_value:
1008  * 
1009  * Returns TRUE is @value is a boxed value
1010  */
1011 static gboolean
1012 stack_slot_is_boxed_value (ILStackDesc *value)
1013 {
1014         return (value->stype & BOXED_MASK) == BOXED_MASK;
1015 }
1016
1017 static const char *
1018 stack_slot_get_name (ILStackDesc *value)
1019 {
1020         return type_names [value->stype & TYPE_MASK];
1021 }
1022
1023 #define APPEND_WITH_PREDICATE(PRED,NAME) do {\
1024         if (PRED (value)) { \
1025                 if (!first) \
1026                         g_string_append (str, ", "); \
1027                 g_string_append (str, NAME); \
1028                 first = FALSE; \
1029         } } while (0)
1030
1031 static char*
1032 stack_slot_stack_type_full_name (ILStackDesc *value)
1033 {
1034         GString *str = g_string_new ("");
1035         char *result;
1036         gboolean has_pred = FALSE, first = TRUE;
1037
1038         if ((value->stype & TYPE_MASK) != value->stype) {
1039                 g_string_append(str, "[");
1040                 APPEND_WITH_PREDICATE (stack_slot_is_this_pointer, "this");
1041                 APPEND_WITH_PREDICATE (stack_slot_is_boxed_value, "boxed");
1042                 APPEND_WITH_PREDICATE (stack_slot_is_null_literal, "null");
1043                 APPEND_WITH_PREDICATE (stack_slot_is_managed_mutability_pointer, "cmmp");
1044                 APPEND_WITH_PREDICATE (stack_slot_is_managed_pointer, "mp");
1045                 has_pred = TRUE;
1046         }
1047
1048         if (mono_type_is_generic_argument (value->type) && !stack_slot_is_boxed_value (value)) {
1049                 if (!has_pred)
1050                         g_string_append(str, "[");
1051                 if (!first)
1052                         g_string_append (str, ", ");
1053                 g_string_append (str, "unboxed");
1054                 has_pred = TRUE;
1055         }
1056
1057         if (has_pred)
1058                 g_string_append(str, "] ");
1059
1060         g_string_append (str, stack_slot_get_name (value));
1061         result = str->str;
1062         g_string_free (str, FALSE);
1063         return result;
1064 }
1065
1066 static char*
1067 stack_slot_full_name (ILStackDesc *value)
1068 {
1069         char *type_name = mono_type_full_name (value->type);
1070         char *stack_name = stack_slot_stack_type_full_name (value);
1071         char *res = g_strdup_printf ("%s (%s)", type_name, stack_name);
1072         g_free (type_name);
1073         g_free (stack_name);
1074         return res;
1075 }
1076
1077 //////////////////////////////////////////////////////////////////
1078 void
1079 mono_free_verify_list (GSList *list)
1080 {
1081         MonoVerifyInfoExtended *info;
1082         GSList *tmp;
1083
1084         for (tmp = list; tmp; tmp = tmp->next) {
1085                 info = tmp->data;
1086                 g_free (info->info.message);
1087                 g_free (info);
1088         }
1089         g_slist_free (list);
1090 }
1091
1092 #define ADD_ERROR(list,msg)     \
1093         do {    \
1094                 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1);      \
1095                 vinfo->info.status = MONO_VERIFY_ERROR; \
1096                 vinfo->info.message = (msg);    \
1097                 (list) = g_slist_prepend ((list), vinfo);       \
1098         } while (0)
1099
1100 #define ADD_WARN(list,code,msg) \
1101         do {    \
1102                 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1);      \
1103                 vinfo->info.status = (code);    \
1104                 vinfo->info.message = (msg);    \
1105                 (list) = g_slist_prepend ((list), vinfo);       \
1106         } while (0)
1107
1108 #define ADD_INVALID(list,msg)   \
1109         do {    \
1110                 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1);      \
1111                 vinfo->status = MONO_VERIFY_ERROR;      \
1112                 vinfo->message = (msg); \
1113                 (list) = g_slist_prepend ((list), vinfo);       \
1114                 /*G_BREAKPOINT ();*/    \
1115                 goto invalid_cil;       \
1116         } while (0)
1117
1118 #define CHECK_STACK_UNDERFLOW(num)      \
1119         do {    \
1120                 if (cur_stack < (num))  \
1121                         ADD_INVALID (list, g_strdup_printf ("Stack underflow at 0x%04x (%d items instead of %d)", ip_offset, cur_stack, (num)));        \
1122         } while (0)
1123
1124 #define CHECK_STACK_OVERFLOW()  \
1125         do {    \
1126                 if (cur_stack >= max_stack)     \
1127                         ADD_INVALID (list, g_strdup_printf ("Maxstack exceeded at 0x%04x", ip_offset)); \
1128         } while (0)
1129
1130
1131 static int
1132 in_any_block (MonoMethodHeader *header, guint offset)
1133 {
1134         int i;
1135         MonoExceptionClause *clause;
1136
1137         for (i = 0; i < header->num_clauses; ++i) {
1138                 clause = &header->clauses [i];
1139                 if (MONO_OFFSET_IN_CLAUSE (clause, offset))
1140                         return 1;
1141                 if (MONO_OFFSET_IN_HANDLER (clause, offset))
1142                         return 1;
1143                 if (MONO_OFFSET_IN_FILTER (clause, offset))
1144                         return 1;
1145         }
1146         return 0;
1147 }
1148
1149 /*
1150  * in_any_exception_block:
1151  * 
1152  * Returns TRUE is @offset is part of any exception clause (filter, handler, catch, finally or fault).
1153  */
1154 static gboolean
1155 in_any_exception_block (MonoMethodHeader *header, guint offset)
1156 {
1157         int i;
1158         MonoExceptionClause *clause;
1159
1160         for (i = 0; i < header->num_clauses; ++i) {
1161                 clause = &header->clauses [i];
1162                 if (MONO_OFFSET_IN_HANDLER (clause, offset))
1163                         return TRUE;
1164                 if (MONO_OFFSET_IN_FILTER (clause, offset))
1165                         return TRUE;
1166         }
1167         return FALSE;
1168 }
1169
1170 /*
1171  * is_valid_branch_instruction:
1172  *
1173  * Verify if it's valid to perform a branch from @offset to @target.
1174  * This should be used with br and brtrue/false.
1175  * It returns 0 if valid, 1 for unverifiable and 2 for invalid.
1176  * The major diferent from other similiar functions is that branching into a
1177  * finally/fault block is invalid instead of just unverifiable.  
1178  */
1179 static int
1180 is_valid_branch_instruction (MonoMethodHeader *header, guint offset, guint target)
1181 {
1182         int i;
1183         MonoExceptionClause *clause;
1184
1185         for (i = 0; i < header->num_clauses; ++i) {
1186                 clause = &header->clauses [i];
1187                 /*branching into a finally block is invalid*/
1188                 if ((clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT) &&
1189                         !MONO_OFFSET_IN_HANDLER (clause, offset) &&
1190                         MONO_OFFSET_IN_HANDLER (clause, target))
1191                         return 2;
1192
1193                 if (clause->try_offset != target && (MONO_OFFSET_IN_CLAUSE (clause, offset) ^ MONO_OFFSET_IN_CLAUSE (clause, target)))
1194                         return 1;
1195                 if (MONO_OFFSET_IN_HANDLER (clause, offset) ^ MONO_OFFSET_IN_HANDLER (clause, target))
1196                         return 1;
1197                 if (MONO_OFFSET_IN_FILTER (clause, offset) ^ MONO_OFFSET_IN_FILTER (clause, target))
1198                         return 1;
1199         }
1200         return 0;
1201 }
1202
1203 /*
1204  * is_valid_cmp_branch_instruction:
1205  * 
1206  * Verify if it's valid to perform a branch from @offset to @target.
1207  * This should be used with binary comparison branching instruction, like beq, bge and similars.
1208  * It returns 0 if valid, 1 for unverifiable and 2 for invalid.
1209  * 
1210  * The major diferences from other similar functions are that most errors lead to invalid
1211  * code and only branching out of finally, filter or fault clauses is unverifiable. 
1212  */
1213 static int
1214 is_valid_cmp_branch_instruction (MonoMethodHeader *header, guint offset, guint target)
1215 {
1216         int i;
1217         MonoExceptionClause *clause;
1218
1219         for (i = 0; i < header->num_clauses; ++i) {
1220                 clause = &header->clauses [i];
1221                 /*branching out of a handler or finally*/
1222                 if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE &&
1223                         MONO_OFFSET_IN_HANDLER (clause, offset) &&
1224                         !MONO_OFFSET_IN_HANDLER (clause, target))
1225                         return 1;
1226
1227                 if (clause->try_offset != target && (MONO_OFFSET_IN_CLAUSE (clause, offset) ^ MONO_OFFSET_IN_CLAUSE (clause, target)))
1228                         return 2;
1229                 if (MONO_OFFSET_IN_HANDLER (clause, offset) ^ MONO_OFFSET_IN_HANDLER (clause, target))
1230                         return 2;
1231                 if (MONO_OFFSET_IN_FILTER (clause, offset) ^ MONO_OFFSET_IN_FILTER (clause, target))
1232                         return 2;
1233         }
1234         return 0;
1235 }
1236
1237 /*
1238  * A leave can't escape a finally block 
1239  */
1240 static int
1241 is_correct_leave (MonoMethodHeader *header, guint offset, guint target)
1242 {
1243         int i;
1244         MonoExceptionClause *clause;
1245
1246         for (i = 0; i < header->num_clauses; ++i) {
1247                 clause = &header->clauses [i];
1248                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY && MONO_OFFSET_IN_HANDLER (clause, offset) && !MONO_OFFSET_IN_HANDLER (clause, target))
1249                         return 0;
1250                 if (MONO_OFFSET_IN_FILTER (clause, offset))
1251                         return 0;
1252         }
1253         return 1;
1254 }
1255
1256 /*
1257  * A rethrow can't happen outside of a catch handler.
1258  */
1259 static int
1260 is_correct_rethrow (MonoMethodHeader *header, guint offset)
1261 {
1262         int i;
1263         MonoExceptionClause *clause;
1264
1265         for (i = 0; i < header->num_clauses; ++i) {
1266                 clause = &header->clauses [i];
1267                 if (MONO_OFFSET_IN_HANDLER (clause, offset))
1268                         return 1;
1269                 if (MONO_OFFSET_IN_FILTER (clause, offset))
1270                         return 1;
1271         }
1272         return 0;
1273 }
1274
1275 /*
1276  * An endfinally can't happen outside of a finally/fault handler.
1277  */
1278 static int
1279 is_correct_endfinally (MonoMethodHeader *header, guint offset)
1280 {
1281         int i;
1282         MonoExceptionClause *clause;
1283
1284         for (i = 0; i < header->num_clauses; ++i) {
1285                 clause = &header->clauses [i];
1286                 if (MONO_OFFSET_IN_HANDLER (clause, offset) && (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY))
1287                         return 1;
1288         }
1289         return 0;
1290 }
1291
1292
1293 /*
1294  * An endfilter can only happens inside a filter clause.
1295  * In non-strict mode filter is allowed inside the handler clause too
1296  */
1297 static MonoExceptionClause *
1298 is_correct_endfilter (VerifyContext *ctx, guint offset)
1299 {
1300         int i;
1301         MonoExceptionClause *clause;
1302
1303         for (i = 0; i < ctx->header->num_clauses; ++i) {
1304                 clause = &ctx->header->clauses [i];
1305                 if (clause->flags != MONO_EXCEPTION_CLAUSE_FILTER)
1306                         continue;
1307                 if (MONO_OFFSET_IN_FILTER (clause, offset))
1308                         return clause;
1309                 if (!IS_STRICT_MODE (ctx) && MONO_OFFSET_IN_HANDLER (clause, offset))
1310                         return clause;
1311         }
1312         return NULL;
1313 }
1314
1315
1316 /*
1317  * Non-strict endfilter can happens inside a try block or any handler block
1318  */
1319 static int
1320 is_unverifiable_endfilter (VerifyContext *ctx, guint offset)
1321 {
1322         int i;
1323         MonoExceptionClause *clause;
1324
1325         for (i = 0; i < ctx->header->num_clauses; ++i) {
1326                 clause = &ctx->header->clauses [i];
1327                 if (MONO_OFFSET_IN_CLAUSE (clause, offset))
1328                         return 1;
1329         }
1330         return 0;
1331 }
1332
1333 static gboolean
1334 is_valid_bool_arg (ILStackDesc *arg)
1335 {
1336         if (stack_slot_is_managed_pointer (arg) || stack_slot_is_boxed_value (arg) || stack_slot_is_null_literal (arg))
1337                 return TRUE;
1338
1339
1340         switch (stack_slot_get_underlying_type (arg)) {
1341         case TYPE_I4:
1342         case TYPE_I8:
1343         case TYPE_NATIVE_INT:
1344         case TYPE_PTR:
1345                 return TRUE;
1346         case TYPE_COMPLEX:
1347                 g_assert (arg->type);
1348                 switch (arg->type->type) {
1349                 case MONO_TYPE_CLASS:
1350                 case MONO_TYPE_STRING:
1351                 case MONO_TYPE_OBJECT:
1352                 case MONO_TYPE_SZARRAY:
1353                 case MONO_TYPE_ARRAY:
1354                 case MONO_TYPE_FNPTR:
1355                 case MONO_TYPE_PTR:
1356                         return TRUE;
1357                 case MONO_TYPE_GENERICINST:
1358                         /*We need to check if the container class
1359                          * of the generic type is a valuetype, iow:
1360                          * is it a "class Foo<T>" or a "struct Foo<T>"?
1361                          */
1362                         return !arg->type->data.generic_class->container_class->valuetype;
1363                 }
1364         default:
1365                 return FALSE;
1366         }
1367 }
1368
1369
1370 /*Type manipulation helper*/
1371
1372 /*Returns the byref version of the supplied MonoType*/
1373 static MonoType*
1374 mono_type_get_type_byref (MonoType *type)
1375 {
1376         if (type->byref)
1377                 return type;
1378         return &mono_class_from_mono_type (type)->this_arg;
1379 }
1380
1381
1382 /*Returns the byval version of the supplied MonoType*/
1383 static MonoType*
1384 mono_type_get_type_byval (MonoType *type)
1385 {
1386         if (!type->byref)
1387                 return type;
1388         return &mono_class_from_mono_type (type)->byval_arg;
1389 }
1390
1391 static MonoType*
1392 mono_type_from_stack_slot (ILStackDesc *slot)
1393 {
1394         if (stack_slot_is_managed_pointer (slot))
1395                 return mono_type_get_type_byref (slot->type);
1396         return slot->type;
1397 }
1398
1399 /*Stack manipulation code*/
1400
1401 static void
1402 ensure_stack_size (ILCodeDesc *stack, int required)
1403 {
1404         int new_size = 8;
1405         ILStackDesc *tmp;
1406
1407         if (required < stack->max_size)
1408                 return;
1409
1410         /* We don't have to worry about the exponential growth since stack_copy prune unused space */
1411         new_size = MAX (8, MAX (required, stack->max_size * 2));
1412
1413         g_assert (new_size >= stack->size);
1414         g_assert (new_size >= required);
1415
1416         tmp = g_new0 (ILStackDesc, new_size);
1417         MEM_ALLOC (sizeof (ILStackDesc) * new_size);
1418
1419         if (stack->stack) {
1420                 if (stack->size)
1421                         memcpy (tmp, stack->stack, stack->size * sizeof (ILStackDesc));
1422                 g_free (stack->stack);
1423                 MEM_FREE (sizeof (ILStackDesc) * stack->max_size);
1424         }
1425
1426         stack->stack = tmp;
1427         stack->max_size = new_size;
1428 }
1429
1430 static void
1431 stack_init (VerifyContext *ctx, ILCodeDesc *state) 
1432 {
1433         if (state->flags & IL_CODE_FLAG_STACK_INITED)
1434                 return;
1435         state->size = state->max_size = 0;
1436         state->flags |= IL_CODE_FLAG_STACK_INITED;
1437 }
1438
1439 static void
1440 stack_copy (ILCodeDesc *to, ILCodeDesc *from)
1441 {
1442         ensure_stack_size (to, from->size);
1443         to->size = from->size;
1444
1445         /*stack copy happens at merge points, which have small stacks*/
1446         if (from->size)
1447                 memcpy (to->stack, from->stack, sizeof (ILStackDesc) * from->size);
1448 }
1449
1450 static void
1451 copy_stack_value (ILStackDesc *to, ILStackDesc *from)
1452 {
1453         to->stype = from->stype;
1454         to->type = from->type;
1455         to->method = from->method;
1456 }
1457
1458 static int
1459 check_underflow (VerifyContext *ctx, int size)
1460 {
1461         if (ctx->eval.size < size) {
1462                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack underflow, required %d, but have %d at 0x%04x", size, ctx->eval.size, ctx->ip_offset));
1463                 return 0;
1464         }
1465         return 1;
1466 }
1467
1468 static int
1469 check_overflow (VerifyContext *ctx)
1470 {
1471         if (ctx->eval.size >= ctx->max_stack) {
1472                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have stack-depth %d at 0x%04x", ctx->eval.size + 1, ctx->ip_offset));
1473                 return 0;
1474         }
1475         return 1;
1476 }
1477
1478 /*This reject out PTR, FNPTR and TYPEDBYREF*/
1479 static gboolean
1480 check_unmanaged_pointer (VerifyContext *ctx, ILStackDesc *value)
1481 {
1482         if (stack_slot_get_type (value) == TYPE_PTR) {
1483                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Unmanaged pointer is not a verifiable type at 0x%04x", ctx->ip_offset));
1484                 return 0;
1485         }
1486         return 1;
1487 }
1488
1489 /*TODO verify if MONO_TYPE_TYPEDBYREF is not allowed here as well.*/
1490 static gboolean
1491 check_unverifiable_type (VerifyContext *ctx, MonoType *type)
1492 {
1493         if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
1494                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Unmanaged pointer is not a verifiable type at 0x%04x", ctx->ip_offset));
1495                 return 0;
1496         }
1497         return 1;
1498 }
1499
1500 static ILStackDesc *
1501 stack_push (VerifyContext *ctx)
1502 {
1503         g_assert (ctx->eval.size < ctx->max_stack);
1504         g_assert (ctx->eval.size <= ctx->eval.max_size);
1505
1506         ensure_stack_size (&ctx->eval, ctx->eval.size + 1);
1507
1508         return & ctx->eval.stack [ctx->eval.size++];
1509 }
1510
1511 static ILStackDesc *
1512 stack_push_val (VerifyContext *ctx, int stype, MonoType *type)
1513 {
1514         ILStackDesc *top = stack_push (ctx);
1515         top->stype = stype;
1516         top->type = type;
1517         return top;
1518 }
1519
1520 static ILStackDesc *
1521 stack_pop (VerifyContext *ctx)
1522 {
1523         ILStackDesc *ret;
1524         g_assert (ctx->eval.size > 0);  
1525         ret = ctx->eval.stack + --ctx->eval.size;
1526         if ((ret->stype & UNINIT_THIS_MASK) == UNINIT_THIS_MASK)
1527                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Found use of uninitialized 'this ptr' ref at 0x%04x", ctx->ip_offset));
1528         return ret;
1529 }
1530
1531 /* This function allows to safely pop an unititialized this ptr from
1532  * the eval stack without marking the method as unverifiable. 
1533  */
1534 static ILStackDesc *
1535 stack_pop_safe (VerifyContext *ctx)
1536 {
1537         g_assert (ctx->eval.size > 0);
1538         return ctx->eval.stack + --ctx->eval.size;
1539 }
1540
1541 /*Positive number distance from stack top. [0] is stack top, [1] is the one below*/
1542 static ILStackDesc*
1543 stack_peek (VerifyContext *ctx, int distance)
1544 {
1545         g_assert (ctx->eval.size - distance > 0);
1546         return ctx->eval.stack + (ctx->eval.size - 1 - distance);
1547 }
1548
1549 static ILStackDesc *
1550 stack_push_stack_val (VerifyContext *ctx, ILStackDesc *value)
1551 {
1552         ILStackDesc *top = stack_push (ctx);
1553         copy_stack_value (top, value);
1554         return top;
1555 }
1556
1557 /* Returns the MonoType associated with the token, or NULL if it is invalid.
1558  * 
1559  * A boxable type can be either a reference or value type, but cannot be a byref type or an unmanaged pointer   
1560  * */
1561 static MonoType*
1562 get_boxable_mono_type (VerifyContext* ctx, int token, const char *opcode)
1563 {
1564         MonoType *type;
1565         MonoClass *class;
1566
1567         if (!(type = verifier_load_type (ctx, token, opcode)))
1568                 return NULL;
1569
1570         if (type->byref && type->type != MONO_TYPE_TYPEDBYREF) {
1571                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of byref type for %s at 0x%04x", opcode, ctx->ip_offset));
1572                 return NULL;
1573         }
1574
1575         if (type->type == MONO_TYPE_VOID) {
1576                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of void type for %s at 0x%04x", opcode, ctx->ip_offset));
1577                 return NULL;
1578         }
1579
1580         if (type->type == MONO_TYPE_TYPEDBYREF)
1581                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid use of typedbyref for %s at 0x%04x", opcode, ctx->ip_offset));
1582
1583         if (!(class = mono_class_from_mono_type (type)))
1584                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not retrieve type token for %s at 0x%04x", opcode, ctx->ip_offset));
1585
1586         if (class->generic_container && type->type != MONO_TYPE_GENERICINST)
1587                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the generic type definition in a boxable type position for %s at 0x%04x", opcode, ctx->ip_offset));      
1588
1589         check_unverifiable_type (ctx, type);
1590         return type;
1591 }
1592
1593
1594 /*operation result tables */
1595
1596 static const unsigned char bin_op_table [TYPE_MAX][TYPE_MAX] = {
1597         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1598         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1599         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1600         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_R8, TYPE_INV, TYPE_INV},
1601         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1602         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1603 };
1604
1605 static const unsigned char add_table [TYPE_MAX][TYPE_MAX] = {
1606         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
1607         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1608         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
1609         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_R8, TYPE_INV, TYPE_INV},
1610         {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_INV, TYPE_INV},
1611         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1612 };
1613
1614 static const unsigned char sub_table [TYPE_MAX][TYPE_MAX] = {
1615         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1616         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1617         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1618         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_R8, TYPE_INV, TYPE_INV},
1619         {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_NATIVE_INT | NON_VERIFIABLE_RESULT, TYPE_INV},
1620         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1621 };
1622
1623 static const unsigned char int_bin_op_table [TYPE_MAX][TYPE_MAX] = {
1624         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1625         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1626         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1627         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1628         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1629         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1630 };
1631
1632 static const unsigned char shift_op_table [TYPE_MAX][TYPE_MAX] = {
1633         {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
1634         {TYPE_I8, TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV},
1635         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1636         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1637         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1638         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1639 };
1640
1641 static const unsigned char cmp_br_op [TYPE_MAX][TYPE_MAX] = {
1642         {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
1643         {TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1644         {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
1645         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV},
1646         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4, TYPE_INV},
1647         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1648 };
1649
1650 static const unsigned char cmp_br_eq_op [TYPE_MAX][TYPE_MAX] = {
1651         {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
1652         {TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1653         {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_I4 | NON_VERIFIABLE_RESULT, TYPE_INV},
1654         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV},
1655         {TYPE_INV, TYPE_INV, TYPE_I4 | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_I4, TYPE_INV},
1656         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4},
1657 };
1658
1659 static const unsigned char add_ovf_un_table [TYPE_MAX][TYPE_MAX] = {
1660         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
1661         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1662         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
1663         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1664         {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_INV, TYPE_INV},
1665         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1666 };
1667
1668 static const unsigned char sub_ovf_un_table [TYPE_MAX][TYPE_MAX] = {
1669         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1670         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1671         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1672         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1673         {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_NATIVE_INT | NON_VERIFIABLE_RESULT, TYPE_INV},
1674         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1675 };
1676
1677 static const unsigned char bin_ovf_table [TYPE_MAX][TYPE_MAX] = {
1678         {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1679         {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1680         {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
1681         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1682         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1683         {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
1684 };
1685
1686 #ifdef MONO_VERIFIER_DEBUG
1687
1688 /*debug helpers */
1689 static void
1690 dump_stack_value (ILStackDesc *value)
1691 {
1692         printf ("[(%x)(%x)", value->type->type, value->stype);
1693
1694         if (stack_slot_is_this_pointer (value))
1695                 printf ("[this] ");
1696
1697         if (stack_slot_is_boxed_value (value))
1698                 printf ("[boxed] ");
1699
1700         if (stack_slot_is_null_literal (value))
1701                 printf ("[null] ");
1702
1703         if (stack_slot_is_managed_mutability_pointer (value))
1704                 printf ("Controled Mutability MP: ");
1705
1706         if (stack_slot_is_managed_pointer (value))
1707                 printf ("Managed Pointer to: ");
1708
1709         switch (stack_slot_get_underlying_type (value)) {
1710                 case TYPE_INV:
1711                         printf ("invalid type]"); 
1712                         return;
1713                 case TYPE_I4:
1714                         printf ("int32]"); 
1715                         return;
1716                 case TYPE_I8:
1717                         printf ("int64]"); 
1718                         return;
1719                 case TYPE_NATIVE_INT:
1720                         printf ("native int]"); 
1721                         return;
1722                 case TYPE_R8:
1723                         printf ("float64]"); 
1724                         return;
1725                 case TYPE_PTR:
1726                         printf ("unmanaged pointer]"); 
1727                         return;
1728                 case TYPE_COMPLEX:
1729                         switch (value->type->type) {
1730                         case MONO_TYPE_CLASS:
1731                         case MONO_TYPE_VALUETYPE:
1732                                 printf ("complex] (%s)", value->type->data.klass->name);
1733                                 return;
1734                         case MONO_TYPE_STRING:
1735                                 printf ("complex] (string)");
1736                                 return;
1737                         case MONO_TYPE_OBJECT:
1738                                 printf ("complex] (object)");
1739                                 return;
1740                         case MONO_TYPE_SZARRAY:
1741                                 printf ("complex] (%s [])", value->type->data.klass->name);
1742                                 return;
1743                         case MONO_TYPE_ARRAY:
1744                                 printf ("complex] (%s [%d %d %d])",
1745                                         value->type->data.array->eklass->name,
1746                                         value->type->data.array->rank,
1747                                         value->type->data.array->numsizes,
1748                                         value->type->data.array->numlobounds);
1749                                 return;
1750                         case MONO_TYPE_GENERICINST:
1751                                 printf ("complex] (inst of %s )", value->type->data.generic_class->container_class->name);
1752                                 return;
1753                         case MONO_TYPE_VAR:
1754                                 printf ("complex] (type generic param !%d - %s) ", value->type->data.generic_param->num, mono_generic_param_info (value->type->data.generic_param)->name);
1755                                 return;
1756                         case MONO_TYPE_MVAR:
1757                                 printf ("complex] (method generic param !!%d - %s) ", value->type->data.generic_param->num, mono_generic_param_info (value->type->data.generic_param)->name);
1758                                 return;
1759                         default: {
1760                                 //should be a boxed value 
1761                                 char * name = mono_type_full_name (value->type);
1762                                 printf ("complex] %s", name);
1763                                 g_free (name);
1764                                 return;
1765                                 }
1766                         }
1767                 default:
1768                         printf ("unknown stack %x type]\n", value->stype);
1769                         g_assert_not_reached ();
1770         }
1771 }
1772
1773 static void
1774 dump_stack_state (ILCodeDesc *state) 
1775 {
1776         int i;
1777
1778         printf ("(%d) ", state->size);
1779         for (i = 0; i < state->size; ++i)
1780                 dump_stack_value (state->stack + i);
1781         printf ("\n");
1782 }
1783 #endif
1784
1785 /*Returns TRUE if candidate array type can be assigned to target.
1786  *Both parameters MUST be of type MONO_TYPE_ARRAY (target->type == MONO_TYPE_ARRAY)
1787  */
1788 static gboolean
1789 is_array_type_compatible (MonoType *target, MonoType *candidate)
1790 {
1791         MonoArrayType *left = target->data.array;
1792         MonoArrayType *right = candidate->data.array;
1793
1794         g_assert (target->type == MONO_TYPE_ARRAY);
1795         g_assert (candidate->type == MONO_TYPE_ARRAY);
1796
1797         if (left->rank != right->rank)
1798                 return FALSE;
1799
1800         return mono_class_is_assignable_from (left->eklass, right->eklass);
1801 }
1802
1803 static int
1804 get_stack_type (MonoType *type)
1805 {
1806         int mask = 0;
1807         int type_kind = type->type;
1808         if (type->byref)
1809                 mask = POINTER_MASK;
1810         /*TODO handle CMMP_MASK */
1811
1812 handle_enum:
1813         switch (type_kind) {
1814         case MONO_TYPE_I1:
1815         case MONO_TYPE_U1:
1816         case MONO_TYPE_BOOLEAN:
1817         case MONO_TYPE_I2:
1818         case MONO_TYPE_U2:
1819         case MONO_TYPE_CHAR:
1820         case MONO_TYPE_I4:
1821         case MONO_TYPE_U4:
1822                 return TYPE_I4 | mask;
1823
1824         case MONO_TYPE_I:
1825         case MONO_TYPE_U:
1826                 return TYPE_NATIVE_INT | mask;
1827
1828         /* FIXME: the spec says that you cannot have a pointer to method pointer, do we need to check this here? */ 
1829         case MONO_TYPE_FNPTR:
1830         case MONO_TYPE_PTR:
1831         case MONO_TYPE_TYPEDBYREF:
1832                 return TYPE_PTR | mask;
1833
1834         case MONO_TYPE_VAR:
1835         case MONO_TYPE_MVAR:
1836
1837         case MONO_TYPE_CLASS:
1838         case MONO_TYPE_STRING:
1839         case MONO_TYPE_OBJECT:
1840         case MONO_TYPE_SZARRAY:
1841         case MONO_TYPE_ARRAY:
1842                 return TYPE_COMPLEX | mask;
1843
1844         case MONO_TYPE_I8:
1845         case MONO_TYPE_U8:
1846                 return TYPE_I8 | mask;
1847
1848         case MONO_TYPE_R4:
1849         case MONO_TYPE_R8:
1850                 return TYPE_R8 | mask;
1851
1852         case MONO_TYPE_GENERICINST:
1853         case MONO_TYPE_VALUETYPE:
1854                 if (mono_type_is_enum_type (type)) {
1855                         type = mono_type_get_underlying_type_any (type);
1856                         if (!type)
1857                                 return FALSE;
1858                         type_kind = type->type;
1859                         goto handle_enum;
1860                 } else {
1861                         return TYPE_COMPLEX | mask;
1862                 }
1863
1864         default:
1865                 return TYPE_INV;
1866         }
1867 }
1868
1869 /* convert MonoType to ILStackDesc format (stype) */
1870 static gboolean
1871 set_stack_value (VerifyContext *ctx, ILStackDesc *stack, MonoType *type, int take_addr)
1872 {
1873         int mask = 0;
1874         int type_kind = type->type;
1875
1876         if (type->byref || take_addr)
1877                 mask = POINTER_MASK;
1878         /* TODO handle CMMP_MASK */
1879
1880 handle_enum:
1881         stack->type = type;
1882
1883         switch (type_kind) {
1884         case MONO_TYPE_I1:
1885         case MONO_TYPE_U1:
1886         case MONO_TYPE_BOOLEAN:
1887         case MONO_TYPE_I2:
1888         case MONO_TYPE_U2:
1889         case MONO_TYPE_CHAR:
1890         case MONO_TYPE_I4:
1891         case MONO_TYPE_U4:
1892                 stack->stype = TYPE_I4 | mask;
1893                 break;
1894         case MONO_TYPE_I:
1895         case MONO_TYPE_U:
1896                 stack->stype = TYPE_NATIVE_INT | mask;
1897                 break;
1898
1899         /*FIXME: Do we need to check if it's a pointer to the method pointer? The spec says it' illegal to have that.*/
1900         case MONO_TYPE_FNPTR:
1901         case MONO_TYPE_PTR:
1902         case MONO_TYPE_TYPEDBYREF:
1903                 stack->stype = TYPE_PTR | mask;
1904                 break;
1905
1906         case MONO_TYPE_CLASS:
1907         case MONO_TYPE_STRING:
1908         case MONO_TYPE_OBJECT:
1909         case MONO_TYPE_SZARRAY:
1910         case MONO_TYPE_ARRAY:
1911
1912         case MONO_TYPE_VAR:
1913         case MONO_TYPE_MVAR: 
1914                 stack->stype = TYPE_COMPLEX | mask;
1915                 break;
1916                 
1917         case MONO_TYPE_I8:
1918         case MONO_TYPE_U8:
1919                 stack->stype = TYPE_I8 | mask;
1920                 break;
1921         case MONO_TYPE_R4:
1922         case MONO_TYPE_R8:
1923                 stack->stype = TYPE_R8 | mask;
1924                 break;
1925         case MONO_TYPE_GENERICINST:
1926         case MONO_TYPE_VALUETYPE:
1927                 if (mono_type_is_enum_type (type)) {
1928                         MonoType *utype = mono_type_get_underlying_type_any (type);
1929                         if (!utype) {
1930                                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not resolve underlying type of %x at %d", type->type, ctx->ip_offset));
1931                                 return FALSE;
1932                         }
1933                         type = utype;
1934                         type_kind = type->type;
1935                         goto handle_enum;
1936                 } else {
1937                         stack->stype = TYPE_COMPLEX | mask;
1938                         break;
1939                 }
1940         default:
1941                 VERIFIER_DEBUG ( printf ("unknown type 0x%02x in eval stack type\n", type->type); );
1942                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Illegal value set on stack 0x%02x at %d", type->type, ctx->ip_offset));
1943                 return FALSE;
1944         }
1945         return TRUE;
1946 }
1947
1948 /* 
1949  * init_stack_with_value_at_exception_boundary:
1950  * 
1951  * Initialize the stack and push a given type.
1952  * The instruction is marked as been on the exception boundary.
1953  */
1954 static void
1955 init_stack_with_value_at_exception_boundary (VerifyContext *ctx, ILCodeDesc *code, MonoClass *klass)
1956 {
1957         MonoError error;
1958         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, ctx->generic_context, &error);
1959
1960         if (!mono_error_ok (&error)) {
1961                 char *name = mono_type_get_full_name (klass);
1962                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid class %s used for exception", name));
1963                 g_free (name);
1964                 mono_error_cleanup (&error);
1965                 return;
1966         }
1967
1968         if (!ctx->max_stack) {
1969                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack overflow at 0x%04x", ctx->ip_offset));
1970                 return;
1971         }
1972
1973         stack_init (ctx, code);
1974         ensure_stack_size (code, 1);
1975         set_stack_value (ctx, code->stack, type, FALSE);
1976         ctx->exception_types = g_slist_prepend (ctx->exception_types, type);
1977         code->size = 1;
1978         code->flags |= IL_CODE_FLAG_WAS_TARGET;
1979         if (mono_type_is_generic_argument (type))
1980                 code->stack->stype |= BOXED_MASK;
1981 }
1982
1983 /*Verify if type 'candidate' can be stored in type 'target'.
1984  * 
1985  * If strict, check for the underlying type and not the verification stack types
1986  */
1987 static gboolean
1988 verify_type_compatibility_full (VerifyContext *ctx, MonoType *target, MonoType *candidate, gboolean strict)
1989 {
1990 #define IS_ONE_OF3(T, A, B, C) (T == A || T == B || T == C)
1991 #define IS_ONE_OF2(T, A, B) (T == A || T == B)
1992
1993         MonoType *original_candidate = candidate;
1994         VERIFIER_DEBUG ( printf ("checking type compatibility %s x %s strict %d\n", mono_type_full_name (target), mono_type_full_name (candidate), strict); );
1995
1996         /*only one is byref */
1997         if (candidate->byref ^ target->byref) {
1998                 /* converting from native int to byref*/
1999                 if (get_stack_type (candidate) == TYPE_NATIVE_INT && target->byref) {
2000                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("using byref native int at 0x%04x", ctx->ip_offset));
2001                         return TRUE;
2002                 }
2003                 return FALSE;
2004         }
2005         strict |= target->byref;
2006         /*From now on we don't care about byref anymore, so it's ok to discard it here*/
2007         candidate = mono_type_get_underlying_type_any (candidate);
2008
2009 handle_enum:
2010         switch (target->type) {
2011         case MONO_TYPE_VOID:
2012                 return candidate->type == MONO_TYPE_VOID;
2013         case MONO_TYPE_I1:
2014         case MONO_TYPE_U1:
2015         case MONO_TYPE_BOOLEAN:
2016                 if (strict)
2017                         return IS_ONE_OF3 (candidate->type, MONO_TYPE_I1, MONO_TYPE_U1, MONO_TYPE_BOOLEAN);
2018         case MONO_TYPE_I2:
2019         case MONO_TYPE_U2:
2020         case MONO_TYPE_CHAR:
2021                 if (strict)
2022                         return IS_ONE_OF3 (candidate->type, MONO_TYPE_I2, MONO_TYPE_U2, MONO_TYPE_CHAR);
2023         case MONO_TYPE_I4:
2024         case MONO_TYPE_U4: {
2025                 gboolean is_native_int = IS_ONE_OF2 (candidate->type, MONO_TYPE_I, MONO_TYPE_U);
2026                 gboolean is_int4 = IS_ONE_OF2 (candidate->type, MONO_TYPE_I4, MONO_TYPE_U4);
2027                 if (strict)
2028                         return is_native_int || is_int4;
2029                 return is_native_int || get_stack_type (candidate) == TYPE_I4;
2030         }
2031
2032         case MONO_TYPE_I8:
2033         case MONO_TYPE_U8:
2034                 return IS_ONE_OF2 (candidate->type, MONO_TYPE_I8, MONO_TYPE_U8);
2035
2036         case MONO_TYPE_R4:
2037         case MONO_TYPE_R8:
2038                 if (strict)
2039                         return candidate->type == target->type;
2040                 return IS_ONE_OF2 (candidate->type, MONO_TYPE_R4, MONO_TYPE_R8);
2041
2042         case MONO_TYPE_I:
2043         case MONO_TYPE_U: {
2044                 gboolean is_native_int = IS_ONE_OF2 (candidate->type, MONO_TYPE_I, MONO_TYPE_U);
2045                 gboolean is_int4 = IS_ONE_OF2 (candidate->type, MONO_TYPE_I4, MONO_TYPE_U4);
2046                 if (strict)
2047                         return is_native_int || is_int4;
2048                 return is_native_int || get_stack_type (candidate) == TYPE_I4;
2049         }
2050
2051         case MONO_TYPE_PTR:
2052                 if (candidate->type != MONO_TYPE_PTR)
2053                         return FALSE;
2054                 /* check the underlying type */
2055                 return verify_type_compatibility_full (ctx, target->data.type, candidate->data.type, TRUE);
2056
2057         case MONO_TYPE_FNPTR: {
2058                 MonoMethodSignature *left, *right;
2059                 if (candidate->type != MONO_TYPE_FNPTR)
2060                         return FALSE;
2061
2062                 left = mono_type_get_signature (target);
2063                 right = mono_type_get_signature (candidate);
2064                 return mono_metadata_signature_equal (left, right) && left->call_convention == right->call_convention;
2065         }
2066
2067         case MONO_TYPE_GENERICINST: {
2068                 MonoClass *target_klass;
2069                 MonoClass *candidate_klass;
2070                 if (mono_type_is_enum_type (target)) {
2071                         target = mono_type_get_underlying_type_any (target);
2072                         if (!target)
2073                                 return FALSE;
2074                         goto handle_enum;
2075                 }
2076                 /*
2077                  * VAR / MVAR compatibility must be checked by verify_stack_type_compatibility
2078                  * to take boxing status into account.
2079                  */
2080                 if (mono_type_is_generic_argument (original_candidate))
2081                         return FALSE;
2082
2083                 target_klass = mono_class_from_mono_type (target);
2084                 candidate_klass = mono_class_from_mono_type (candidate);
2085                 if (mono_class_is_nullable (target_klass)) {
2086                         if (!mono_class_is_nullable (candidate_klass))
2087                                 return FALSE;
2088                         return target_klass == candidate_klass;
2089                 }
2090                 
2091                 return mono_class_is_assignable_from (target_klass, candidate_klass);
2092         }
2093
2094         case MONO_TYPE_STRING:
2095                 return candidate->type == MONO_TYPE_STRING;
2096
2097         case MONO_TYPE_CLASS:
2098                 /*
2099                  * VAR / MVAR compatibility must be checked by verify_stack_type_compatibility
2100                  * to take boxing status into account.
2101                  */
2102                 if (mono_type_is_generic_argument (original_candidate))
2103                         return FALSE;
2104
2105                 if (candidate->type == MONO_TYPE_VALUETYPE)
2106                         return FALSE;
2107
2108                 /* If candidate is an enum it should return true for System.Enum and supertypes.
2109                  * That's why here we use the original type and not the underlying type.
2110                  */ 
2111                 return mono_class_is_assignable_from (target->data.klass, mono_class_from_mono_type (original_candidate));
2112
2113         case MONO_TYPE_OBJECT:
2114                 return MONO_TYPE_IS_REFERENCE (candidate);
2115
2116         case MONO_TYPE_SZARRAY: {
2117                 MonoClass *left;
2118                 MonoClass *right;
2119                 if (candidate->type != MONO_TYPE_SZARRAY)
2120                         return FALSE;
2121
2122                 left = mono_class_from_mono_type (target);
2123                 right = mono_class_from_mono_type (candidate);
2124
2125                 return mono_class_is_assignable_from (left, right);
2126         }
2127
2128         case MONO_TYPE_ARRAY:
2129                 if (candidate->type != MONO_TYPE_ARRAY)
2130                         return FALSE;
2131                 return is_array_type_compatible (target, candidate);
2132
2133         case MONO_TYPE_TYPEDBYREF:
2134                 return candidate->type == MONO_TYPE_TYPEDBYREF;
2135
2136         case MONO_TYPE_VALUETYPE: {
2137                 MonoClass *target_klass;
2138                 MonoClass *candidate_klass;
2139
2140                 if (candidate->type == MONO_TYPE_CLASS)
2141                         return FALSE;
2142
2143                 target_klass = mono_class_from_mono_type (target);
2144                 candidate_klass = mono_class_from_mono_type (candidate);
2145                 if (target_klass == candidate_klass)
2146                         return TRUE;
2147                 if (mono_type_is_enum_type (target)) {
2148                         target = mono_type_get_underlying_type_any (target);
2149                         if (!target)
2150                                 return FALSE;
2151                         goto handle_enum;
2152                 }
2153                 return FALSE;
2154         }
2155
2156         case MONO_TYPE_VAR:
2157                 if (candidate->type != MONO_TYPE_VAR)
2158                         return FALSE;
2159                 return mono_type_get_generic_param_num (candidate) == mono_type_get_generic_param_num (target);
2160
2161         case MONO_TYPE_MVAR:
2162                 if (candidate->type != MONO_TYPE_MVAR)
2163                         return FALSE;
2164                 return mono_type_get_generic_param_num (candidate) == mono_type_get_generic_param_num (target);
2165
2166         default:
2167                 VERIFIER_DEBUG ( printf ("unknown store type %d\n", target->type); );
2168                 g_assert_not_reached ();
2169                 return FALSE;
2170         }
2171         return 1;
2172 #undef IS_ONE_OF3
2173 #undef IS_ONE_OF2
2174 }
2175
2176 static gboolean
2177 verify_type_compatibility (VerifyContext *ctx, MonoType *target, MonoType *candidate)
2178 {
2179         return verify_type_compatibility_full (ctx, target, candidate, FALSE);
2180 }
2181
2182 /*
2183  * Returns the generic param bound to the context been verified.
2184  * 
2185  */
2186 static MonoGenericParam*
2187 get_generic_param (VerifyContext *ctx, MonoType *param) 
2188 {
2189         guint16 param_num = mono_type_get_generic_param_num (param);
2190         if (param->type == MONO_TYPE_VAR) {
2191                 if (!ctx->generic_context->class_inst || ctx->generic_context->class_inst->type_argc <= param_num) {
2192                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid generic type argument %d", param_num));
2193                         return NULL;
2194                 }
2195                 return ctx->generic_context->class_inst->type_argv [param_num]->data.generic_param;
2196         }
2197         
2198         /*param must be a MVAR */
2199         if (!ctx->generic_context->method_inst || ctx->generic_context->method_inst->type_argc <= param_num) {
2200                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid generic method argument %d", param_num));
2201                 return NULL;
2202         }
2203         return ctx->generic_context->method_inst->type_argv [param_num]->data.generic_param;
2204         
2205 }
2206
2207 static gboolean
2208 recursive_boxed_constraint_type_check (VerifyContext *ctx, MonoType *type, MonoClass *constraint_class, int recursion_level)
2209 {
2210         MonoType *constraint_type = &constraint_class->byval_arg;
2211         if (recursion_level <= 0)
2212                 return FALSE;
2213
2214         if (verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (constraint_type), FALSE))
2215                 return TRUE;
2216
2217         if (mono_type_is_generic_argument (constraint_type)) {
2218                 MonoGenericParam *param = get_generic_param (ctx, constraint_type);
2219                 MonoClass **class;
2220                 if (!param)
2221                         return FALSE;
2222                 for (class = mono_generic_param_info (param)->constraints; class && *class; ++class) {
2223                         if (recursive_boxed_constraint_type_check (ctx, type, *class, recursion_level - 1))
2224                                 return TRUE;
2225                 }
2226         }
2227         return FALSE;
2228 }
2229
2230 /*
2231  * is_compatible_boxed_valuetype:
2232  * 
2233  * Returns TRUE if @candidate / @stack is a valid boxed valuetype. 
2234  * 
2235  * @type The source type. It it tested to be of the proper type.    
2236  * @candidate type of the boxed valuetype.
2237  * @stack stack slot of the boxed valuetype, separate from @candidade since one could be changed before calling this function
2238  * @strict if TRUE candidate must be boxed compatible to the target type
2239  * 
2240  */
2241 static gboolean
2242 is_compatible_boxed_valuetype (VerifyContext *ctx, MonoType *type, MonoType *candidate, ILStackDesc *stack, gboolean strict)
2243 {
2244         if (!stack_slot_is_boxed_value (stack))
2245                 return FALSE;
2246         if (type->byref || candidate->byref)
2247                 return FALSE;
2248
2249         if (mono_type_is_generic_argument (candidate)) {
2250                 MonoGenericParam *param = get_generic_param (ctx, candidate);
2251                 MonoClass **class;
2252                 if (!param)
2253                         return FALSE;
2254
2255                 for (class = mono_generic_param_info (param)->constraints; class && *class; ++class) {
2256                         /*256 should be enough since there can't be more than 255 generic arguments.*/
2257                         if (recursive_boxed_constraint_type_check (ctx, type, *class, 256))
2258                                 return TRUE;
2259                 }
2260         }
2261
2262         if (mono_type_is_generic_argument (type))
2263                 return FALSE;
2264
2265         if (!strict)
2266                 return TRUE;
2267
2268         return MONO_TYPE_IS_REFERENCE (type) && mono_class_is_assignable_from (mono_class_from_mono_type (type), mono_class_from_mono_type (candidate));
2269 }
2270
2271 static int
2272 verify_stack_type_compatibility_full (VerifyContext *ctx, MonoType *type, ILStackDesc *stack, gboolean drop_byref, gboolean valuetype_must_be_boxed)
2273 {
2274         MonoType *candidate = mono_type_from_stack_slot (stack);
2275         if (MONO_TYPE_IS_REFERENCE (type) && !type->byref && stack_slot_is_null_literal (stack))
2276                 return TRUE;
2277
2278         if (is_compatible_boxed_valuetype (ctx, type, candidate, stack, TRUE))
2279                 return TRUE;
2280
2281         if (valuetype_must_be_boxed && !stack_slot_is_boxed_value (stack) && !MONO_TYPE_IS_REFERENCE (candidate))
2282                 return FALSE;
2283
2284         if (!valuetype_must_be_boxed && stack_slot_is_boxed_value (stack))
2285                 return FALSE;
2286
2287         if (drop_byref)
2288                 return verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (candidate), FALSE);
2289
2290         return verify_type_compatibility_full (ctx, type, candidate, FALSE);
2291 }
2292
2293 static int
2294 verify_stack_type_compatibility (VerifyContext *ctx, MonoType *type, ILStackDesc *stack)
2295 {
2296         return verify_stack_type_compatibility_full (ctx, type, stack, FALSE, FALSE);
2297 }
2298
2299 static gboolean
2300 mono_delegate_type_equal (MonoType *target, MonoType *candidate)
2301 {
2302         if (candidate->byref ^ target->byref)
2303                 return FALSE;
2304
2305         switch (target->type) {
2306         case MONO_TYPE_VOID:
2307         case MONO_TYPE_I1:
2308         case MONO_TYPE_U1:
2309         case MONO_TYPE_BOOLEAN:
2310         case MONO_TYPE_I2:
2311         case MONO_TYPE_U2:
2312         case MONO_TYPE_CHAR:
2313         case MONO_TYPE_I4:
2314         case MONO_TYPE_U4:
2315         case MONO_TYPE_I8:
2316         case MONO_TYPE_U8:
2317         case MONO_TYPE_R4:
2318         case MONO_TYPE_R8:
2319         case MONO_TYPE_I:
2320         case MONO_TYPE_U:
2321         case MONO_TYPE_STRING:
2322         case MONO_TYPE_TYPEDBYREF:
2323                 return candidate->type == target->type;
2324
2325         case MONO_TYPE_PTR:
2326                 return mono_delegate_type_equal (target->data.type, candidate->data.type);
2327
2328         case MONO_TYPE_FNPTR:
2329                 if (candidate->type != MONO_TYPE_FNPTR)
2330                         return FALSE;
2331                 return mono_delegate_signature_equal (mono_type_get_signature (target), mono_type_get_signature (candidate), FALSE);
2332
2333         case MONO_TYPE_GENERICINST: {
2334                 MonoClass *target_klass;
2335                 MonoClass *candidate_klass;
2336                 target_klass = mono_class_from_mono_type (target);
2337                 candidate_klass = mono_class_from_mono_type (candidate);
2338                 /*FIXME handle nullables and enum*/
2339                 return mono_class_is_assignable_from (target_klass, candidate_klass);
2340         }
2341         case MONO_TYPE_OBJECT:
2342                 return MONO_TYPE_IS_REFERENCE (candidate);
2343
2344         case MONO_TYPE_CLASS:
2345                 return mono_class_is_assignable_from(target->data.klass, mono_class_from_mono_type (candidate));
2346
2347         case MONO_TYPE_SZARRAY:
2348                 if (candidate->type != MONO_TYPE_SZARRAY)
2349                         return FALSE;
2350                 return mono_class_is_assignable_from (mono_class_from_mono_type (target)->element_class, mono_class_from_mono_type (candidate)->element_class);
2351
2352         case MONO_TYPE_ARRAY:
2353                 if (candidate->type != MONO_TYPE_ARRAY)
2354                         return FALSE;
2355                 return is_array_type_compatible (target, candidate);
2356
2357         case MONO_TYPE_VALUETYPE:
2358                 /*FIXME handle nullables and enum*/
2359                 return mono_class_from_mono_type (candidate) == mono_class_from_mono_type (target);
2360
2361         case MONO_TYPE_VAR:
2362                 return candidate->type == MONO_TYPE_VAR && mono_type_get_generic_param_num (target) == mono_type_get_generic_param_num (candidate);
2363                 return FALSE;
2364
2365         case MONO_TYPE_MVAR:
2366                 return candidate->type == MONO_TYPE_MVAR && mono_type_get_generic_param_num (target) == mono_type_get_generic_param_num (candidate);
2367                 return FALSE;
2368
2369         default:
2370                 VERIFIER_DEBUG ( printf ("Unknown type %d. Implement me!\n", target->type); );
2371                 g_assert_not_reached ();
2372                 return FALSE;
2373         }
2374 }
2375
2376 static gboolean
2377 mono_delegate_param_equal (MonoType *delegate, MonoType *method)
2378 {
2379         if (mono_metadata_type_equal_full (delegate, method, TRUE))
2380                 return TRUE;
2381
2382         return mono_delegate_type_equal (method, delegate);
2383 }
2384
2385 static gboolean
2386 mono_delegate_ret_equal (MonoType *delegate, MonoType *method)
2387 {
2388         if (mono_metadata_type_equal_full (delegate, method, TRUE))
2389                 return TRUE;
2390
2391         return mono_delegate_type_equal (delegate, method);
2392 }
2393
2394 /*
2395  * mono_delegate_signature_equal:
2396  * 
2397  * Compare two signatures in the way expected by delegates.
2398  * 
2399  * This function only exists due to the fact that it should ignore the 'has_this' part of the signature.
2400  *
2401  * FIXME can this function be eliminated and proper metadata functionality be used?
2402  */
2403 static gboolean
2404 mono_delegate_signature_equal (MonoMethodSignature *delegate_sig, MonoMethodSignature *method_sig, gboolean is_static_ldftn)
2405 {
2406         int i;
2407         int method_offset = is_static_ldftn ? 1 : 0;
2408
2409         if (delegate_sig->param_count + method_offset != method_sig->param_count) 
2410                 return FALSE;
2411
2412         if (delegate_sig->call_convention != method_sig->call_convention)
2413                 return FALSE;
2414
2415         for (i = 0; i < delegate_sig->param_count; i++) { 
2416                 MonoType *p1 = delegate_sig->params [i];
2417                 MonoType *p2 = method_sig->params [i + method_offset];
2418
2419                 if (!mono_delegate_param_equal (p1, p2))
2420                         return FALSE;
2421         }
2422
2423         if (!mono_delegate_ret_equal (delegate_sig->ret, method_sig->ret))
2424                 return FALSE;
2425
2426         return TRUE;
2427 }
2428
2429 gboolean
2430 mono_verifier_is_signature_compatible (MonoMethodSignature *target, MonoMethodSignature *candidate)
2431 {
2432         return mono_delegate_signature_equal (target, candidate, FALSE);
2433 }
2434
2435 /* 
2436  * verify_ldftn_delegate:
2437  * 
2438  * Verify properties of ldftn based delegates.
2439  */
2440 static void
2441 verify_ldftn_delegate (VerifyContext *ctx, MonoClass *delegate, ILStackDesc *value, ILStackDesc *funptr)
2442 {
2443         MonoMethod *method = funptr->method;
2444
2445         /*ldftn non-final virtuals only allowed if method is not static,
2446          * the object is a this arg (comes from a ldarg.0), and there is no starg.0.
2447          * This rules doesn't apply if the object on stack is a boxed valuetype.
2448          */
2449         if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED) && !stack_slot_is_boxed_value (value)) {
2450                 /*A stdarg 0 must not happen, we fail here only in fail fast mode to avoid double error reports*/
2451                 if (IS_FAIL_FAST_MODE (ctx) && ctx->has_this_store)
2452                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid ldftn with virtual function in method with stdarg 0 at  0x%04x", ctx->ip_offset));
2453
2454                 /*current method must not be static*/
2455                 if (ctx->method->flags & METHOD_ATTRIBUTE_STATIC)
2456                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid ldftn with virtual function at 0x%04x", ctx->ip_offset));
2457
2458                 /*value is the this pointer, loaded using ldarg.0 */
2459                 if (!stack_slot_is_this_pointer (value))
2460                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid object argument, it is not the this pointer, to ldftn with virtual method at  0x%04x", ctx->ip_offset));
2461
2462                 ctx->code [ctx->ip_offset].flags |= IL_CODE_LDFTN_DELEGATE_NONFINAL_VIRTUAL;
2463         }
2464 }
2465
2466 /*
2467  * verify_delegate_compatibility:
2468  * 
2469  * Verify delegate creation sequence.
2470  * 
2471  */
2472 static void
2473 verify_delegate_compatibility (VerifyContext *ctx, MonoClass *delegate, ILStackDesc *value, ILStackDesc *funptr)
2474 {
2475 #define IS_VALID_OPCODE(offset, opcode) (ip [ip_offset - offset] == opcode && (ctx->code [ip_offset - offset].flags & IL_CODE_FLAG_SEEN))
2476 #define IS_LOAD_FUN_PTR(kind) (IS_VALID_OPCODE (6, CEE_PREFIX1) && ip [ip_offset - 5] == kind)
2477
2478         MonoMethod *invoke, *method;
2479         const guint8 *ip = ctx->header->code;
2480         guint32 ip_offset = ctx->ip_offset;
2481         gboolean is_static_ldftn = FALSE, is_first_arg_bound = FALSE;
2482         
2483         if (stack_slot_get_type (funptr) != TYPE_PTR || !funptr->method) {
2484                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid function pointer parameter for delegate constructor at 0x%04x", ctx->ip_offset));
2485                 return;
2486         }
2487         
2488         invoke = mono_get_delegate_invoke (delegate);
2489         method = funptr->method;
2490
2491         if (!method || !mono_method_signature (method)) {
2492                 char *name = mono_type_get_full_name (delegate);
2493                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid method on stack to create delegate %s construction at 0x%04x", name, ctx->ip_offset));
2494                 g_free (name);
2495                 return;
2496         }
2497
2498         if (!invoke || !mono_method_signature (invoke)) {
2499                 char *name = mono_type_get_full_name (delegate);
2500                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Delegate type %s with bad Invoke method at 0x%04x", name, ctx->ip_offset));
2501                 g_free (name);
2502                 return;
2503         }
2504
2505         is_static_ldftn = (ip_offset > 5 && IS_LOAD_FUN_PTR (CEE_LDFTN)) && method->flags & METHOD_ATTRIBUTE_STATIC;
2506
2507         if (is_static_ldftn)
2508                 is_first_arg_bound = mono_method_signature (invoke)->param_count + 1 ==  mono_method_signature (method)->param_count;
2509
2510         if (!mono_delegate_signature_equal (mono_method_signature (invoke), mono_method_signature (method), is_first_arg_bound)) {
2511                 char *fun_sig = mono_signature_get_desc (mono_method_signature (method), FALSE);
2512                 char *invoke_sig = mono_signature_get_desc (mono_method_signature (invoke), FALSE);
2513                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Function pointer signature '%s' doesn't match delegate's signature '%s' at 0x%04x", fun_sig, invoke_sig, ctx->ip_offset));
2514                 g_free (fun_sig);
2515                 g_free (invoke_sig);
2516         }
2517
2518         /* 
2519          * Delegate code sequences:
2520          * [-6] ldftn token
2521          * newobj ...
2522          * 
2523          * 
2524          * [-7] dup
2525          * [-6] ldvirtftn token
2526          * newobj ...
2527          * 
2528          * ldftn sequence:*/
2529         if (ip_offset > 5 && IS_LOAD_FUN_PTR (CEE_LDFTN)) {
2530                 verify_ldftn_delegate (ctx, delegate, value, funptr);
2531         } else if (ip_offset > 6 && IS_VALID_OPCODE (7, CEE_DUP) && IS_LOAD_FUN_PTR (CEE_LDVIRTFTN)) {
2532                 ctx->code [ip_offset - 6].flags |= IL_CODE_DELEGATE_SEQUENCE;   
2533         }else {
2534                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid code sequence for delegate creation at 0x%04x", ctx->ip_offset));
2535         }
2536         ctx->code [ip_offset].flags |= IL_CODE_DELEGATE_SEQUENCE;
2537
2538         //general tests
2539         if (is_first_arg_bound) {
2540                 if (mono_method_signature (method)->param_count == 0 || !verify_stack_type_compatibility_full (ctx, mono_method_signature (method)->params [0], value, FALSE, TRUE))
2541                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("This object not compatible with function pointer for delegate creation at 0x%04x", ctx->ip_offset));
2542         } else {
2543                 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
2544                         if (!stack_slot_is_null_literal (value) && !is_first_arg_bound)
2545                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Non-null this args used with static function for delegate creation at 0x%04x", ctx->ip_offset));
2546                 } else {
2547                         if (!verify_stack_type_compatibility_full (ctx, &method->klass->byval_arg, value, FALSE, TRUE) && !stack_slot_is_null_literal (value))
2548                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("This object not compatible with function pointer for delegate creation at 0x%04x", ctx->ip_offset));
2549                 }
2550         }
2551
2552         if (stack_slot_get_type (value) != TYPE_COMPLEX)
2553                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid first parameter for delegate creation at 0x%04x", ctx->ip_offset));
2554
2555 #undef IS_VALID_OPCODE
2556 #undef IS_LOAD_FUN_PTR
2557 }
2558
2559 /* implement the opcode checks*/
2560 static void
2561 push_arg (VerifyContext *ctx, unsigned int arg, int take_addr) 
2562 {
2563         ILStackDesc *top;
2564
2565         if (arg >= ctx->max_args) {
2566                 if (take_addr) 
2567                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have argument %d", arg + 1));
2568                 else {
2569                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method doesn't have argument %d", arg + 1));
2570                         if (check_overflow (ctx)) //FIXME: what sane value could we ever push?
2571                                 stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
2572                 }
2573         } else if (check_overflow (ctx)) {
2574                 /*We must let the value be pushed, otherwise we would get an underflow error*/
2575                 check_unverifiable_type (ctx, ctx->params [arg]);
2576                 if (ctx->params [arg]->byref && take_addr)
2577                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ByRef of ByRef at 0x%04x", ctx->ip_offset));
2578                 top = stack_push (ctx);
2579                 if (!set_stack_value (ctx, top, ctx->params [arg], take_addr))
2580                         return;
2581
2582                 if (arg == 0 && !(ctx->method->flags & METHOD_ATTRIBUTE_STATIC)) {
2583                         if (take_addr)
2584                                 ctx->has_this_store = TRUE;
2585                         else
2586                                 top->stype |= THIS_POINTER_MASK;
2587                         if (mono_method_is_constructor (ctx->method) && !ctx->super_ctor_called && !ctx->method->klass->valuetype)
2588                                 top->stype |= UNINIT_THIS_MASK;
2589                 }
2590         } 
2591 }
2592
2593 static void
2594 push_local (VerifyContext *ctx, guint32 arg, int take_addr) 
2595 {
2596         if (arg >= ctx->num_locals) {
2597                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have local %d", arg + 1));
2598         } else if (check_overflow (ctx)) {
2599                 /*We must let the value be pushed, otherwise we would get an underflow error*/
2600                 check_unverifiable_type (ctx, ctx->locals [arg]);
2601                 if (ctx->locals [arg]->byref && take_addr)
2602                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ByRef of ByRef at 0x%04x", ctx->ip_offset));
2603
2604                 set_stack_value (ctx, stack_push (ctx), ctx->locals [arg], take_addr);
2605         } 
2606 }
2607
2608 static void
2609 store_arg (VerifyContext *ctx, guint32 arg)
2610 {
2611         ILStackDesc *value;
2612
2613         if (arg >= ctx->max_args) {
2614                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method doesn't have argument %d at 0x%04x", arg + 1, ctx->ip_offset));
2615                 if (check_underflow (ctx, 1))
2616                         stack_pop (ctx);
2617                 return;
2618         }
2619
2620         if (check_underflow (ctx, 1)) {
2621                 value = stack_pop (ctx);
2622                 if (!verify_stack_type_compatibility (ctx, ctx->params [arg], value)) {
2623                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in argument store at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
2624                 }
2625         }
2626         if (arg == 0 && !(ctx->method->flags & METHOD_ATTRIBUTE_STATIC))
2627                 ctx->has_this_store = 1;
2628 }
2629
2630 static void
2631 store_local (VerifyContext *ctx, guint32 arg)
2632 {
2633         ILStackDesc *value;
2634         if (arg >= ctx->num_locals) {
2635                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have local var %d at 0x%04x", arg + 1, ctx->ip_offset));
2636                 return;
2637         }
2638
2639         /*TODO verify definite assigment */             
2640         if (check_underflow (ctx, 1)) {
2641                 value = stack_pop(ctx);
2642                 if (!verify_stack_type_compatibility (ctx, ctx->locals [arg], value)) {
2643                         char *expected = mono_type_full_name (ctx->locals [arg]);
2644                         char *found = stack_slot_full_name (value);
2645                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type '%s' on stack cannot be stored to local %d with type '%s' at 0x%04x",
2646                                         found,
2647                                         arg,
2648                                         expected,
2649                                         ctx->ip_offset));
2650                         g_free (expected);
2651                         g_free (found); 
2652                 }
2653         }
2654 }
2655
2656 /*FIXME add and sub needs special care here*/
2657 static void
2658 do_binop (VerifyContext *ctx, unsigned int opcode, const unsigned char table [TYPE_MAX][TYPE_MAX])
2659 {
2660         ILStackDesc *a, *b, *top;
2661         int idxa, idxb, complexMerge = 0;
2662         unsigned char res;
2663
2664         if (!check_underflow (ctx, 2))
2665                 return;
2666         b = stack_pop (ctx);
2667         a = stack_pop (ctx);
2668
2669         idxa = stack_slot_get_underlying_type (a);
2670         if (stack_slot_is_managed_pointer (a)) {
2671                 idxa = TYPE_PTR;
2672                 complexMerge = 1;
2673         }
2674
2675         idxb = stack_slot_get_underlying_type (b);
2676         if (stack_slot_is_managed_pointer (b)) {
2677                 idxb = TYPE_PTR;
2678                 complexMerge = 2;
2679         }
2680
2681         --idxa;
2682         --idxb;
2683         res = table [idxa][idxb];
2684
2685         VERIFIER_DEBUG ( printf ("binop res %d\n", res); );
2686         VERIFIER_DEBUG ( printf ("idxa %d idxb %d\n", idxa, idxb); );
2687
2688         top = stack_push (ctx);
2689         if (res == TYPE_INV) {
2690                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Binary instruction applyed to ill formed stack (%s x %s)", stack_slot_get_name (a), stack_slot_get_name (b)));
2691                 copy_stack_value (top, a);
2692                 return;
2693         }
2694
2695         if (res & NON_VERIFIABLE_RESULT) {
2696                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Binary instruction is not verifiable (%s x %s)", stack_slot_get_name (a), stack_slot_get_name (b)));
2697
2698                 res = res & ~NON_VERIFIABLE_RESULT;
2699         }
2700
2701         if (complexMerge && res == TYPE_PTR) {
2702                 if (complexMerge == 1) 
2703                         copy_stack_value (top, a);
2704                 else if (complexMerge == 2)
2705                         copy_stack_value (top, b);
2706                 /*
2707                  * There is no need to merge the type of two pointers.
2708                  * The only valid operation is subtraction, that returns a native
2709                  *  int as result and can be used with any 2 pointer kinds.
2710                  * This is valid acording to Patition III 1.1.4
2711                  */
2712         } else
2713                 top->stype = res;
2714         
2715 }
2716
2717
2718 static void
2719 do_boolean_branch_op (VerifyContext *ctx, int delta)
2720 {
2721         int target = ctx->ip_offset + delta;
2722         ILStackDesc *top;
2723
2724         VERIFIER_DEBUG ( printf ("boolean branch offset %d delta %d target %d\n", ctx->ip_offset, delta, target); );
2725  
2726         if (target < 0 || target >= ctx->code_size) {
2727                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Boolean branch target out of code at 0x%04x", ctx->ip_offset));
2728                 return;
2729         }
2730
2731         switch (is_valid_branch_instruction (ctx->header, ctx->ip_offset, target)) {
2732         case 1:
2733                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
2734                 break;
2735         case 2:
2736                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
2737                 return;
2738         }
2739
2740         ctx->target = target;
2741
2742         if (!check_underflow (ctx, 1))
2743                 return;
2744
2745         top = stack_pop (ctx);
2746         if (!is_valid_bool_arg (top))
2747                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Argument type %s not valid for brtrue/brfalse at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
2748
2749         check_unmanaged_pointer (ctx, top);
2750 }
2751
2752 static gboolean
2753 stack_slot_is_complex_type_not_reference_type (ILStackDesc *slot)
2754 {
2755         return stack_slot_get_type (slot) == TYPE_COMPLEX && !MONO_TYPE_IS_REFERENCE (slot->type) && !stack_slot_is_boxed_value (slot);
2756 }
2757
2758 static void
2759 do_branch_op (VerifyContext *ctx, signed int delta, const unsigned char table [TYPE_MAX][TYPE_MAX])
2760 {
2761         ILStackDesc *a, *b;
2762         int idxa, idxb;
2763         unsigned char res;
2764         int target = ctx->ip_offset + delta;
2765
2766         VERIFIER_DEBUG ( printf ("branch offset %d delta %d target %d\n", ctx->ip_offset, delta, target); );
2767  
2768         if (target < 0 || target >= ctx->code_size) {
2769                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target out of code at 0x%04x", ctx->ip_offset));
2770                 return;
2771         }
2772
2773         switch (is_valid_cmp_branch_instruction (ctx->header, ctx->ip_offset, target)) {
2774         case 1: /*FIXME use constants and not magic numbers.*/
2775                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
2776                 break;
2777         case 2:
2778                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
2779                 return;
2780         }
2781
2782         ctx->target = target;
2783
2784         if (!check_underflow (ctx, 2))
2785                 return;
2786
2787         b = stack_pop (ctx);
2788         a = stack_pop (ctx);
2789
2790         idxa = stack_slot_get_underlying_type (a);
2791         if (stack_slot_is_managed_pointer (a))
2792                 idxa = TYPE_PTR;
2793
2794         idxb = stack_slot_get_underlying_type (b);
2795         if (stack_slot_is_managed_pointer (b))
2796                 idxb = TYPE_PTR;
2797
2798         if (stack_slot_is_complex_type_not_reference_type (a) || stack_slot_is_complex_type_not_reference_type (b)) {
2799                 res = TYPE_INV;
2800         } else {
2801                 --idxa;
2802                 --idxb;
2803                 res = table [idxa][idxb];
2804         }
2805
2806         VERIFIER_DEBUG ( printf ("branch res %d\n", res); );
2807         VERIFIER_DEBUG ( printf ("idxa %d idxb %d\n", idxa, idxb); );
2808
2809         if (res == TYPE_INV) {
2810                 CODE_NOT_VERIFIABLE (ctx,
2811                         g_strdup_printf ("Compare and Branch instruction applyed to ill formed stack (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
2812         } else if (res & NON_VERIFIABLE_RESULT) {
2813                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare and Branch instruction is not verifiable (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset)); 
2814                 res = res & ~NON_VERIFIABLE_RESULT;
2815         }
2816 }
2817
2818 static void
2819 do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX], guint32 opcode)
2820 {
2821         ILStackDesc *a, *b;
2822         int idxa, idxb;
2823         unsigned char res;
2824
2825         if (!check_underflow (ctx, 2))
2826                 return;
2827         b = stack_pop (ctx);
2828         a = stack_pop (ctx);
2829
2830         if (opcode == CEE_CGT_UN) {
2831                 if (stack_slot_get_type (a) == TYPE_COMPLEX && stack_slot_get_type (b) == TYPE_COMPLEX) {
2832                         stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
2833                         return;
2834                 }
2835         }
2836
2837         idxa = stack_slot_get_underlying_type (a);
2838         if (stack_slot_is_managed_pointer (a))
2839                 idxa = TYPE_PTR;
2840
2841         idxb = stack_slot_get_underlying_type (b);
2842         if (stack_slot_is_managed_pointer (b)) 
2843                 idxb = TYPE_PTR;
2844
2845         if (stack_slot_is_complex_type_not_reference_type (a) || stack_slot_is_complex_type_not_reference_type (b)) {
2846                 res = TYPE_INV;
2847         } else {
2848                 --idxa;
2849                 --idxb;
2850                 res = table [idxa][idxb];
2851         }
2852
2853         if(res == TYPE_INV) {
2854                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
2855         } else if (res & NON_VERIFIABLE_RESULT) {
2856                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare instruction is not verifiable (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset)); 
2857                 res = res & ~NON_VERIFIABLE_RESULT;
2858         }
2859         stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
2860 }
2861
2862 static void
2863 do_ret (VerifyContext *ctx)
2864 {
2865         MonoType *ret = ctx->signature->ret;
2866         VERIFIER_DEBUG ( printf ("checking ret\n"); );
2867         if (ret->type != MONO_TYPE_VOID) {
2868                 ILStackDesc *top;
2869                 if (!check_underflow (ctx, 1))
2870                         return;
2871
2872                 top = stack_pop(ctx);
2873
2874                 if (!verify_stack_type_compatibility (ctx, ctx->signature->ret, top)) {
2875                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible return value on stack with method signature ret at 0x%04x", ctx->ip_offset));
2876                         return;
2877                 }
2878
2879                 if (ret->byref || ret->type == MONO_TYPE_TYPEDBYREF || mono_type_is_value_type (ret, "System", "ArgIterator") || mono_type_is_value_type (ret, "System", "RuntimeArgumentHandle"))
2880                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method returns byref, TypedReference, ArgIterator or RuntimeArgumentHandle at 0x%04x", ctx->ip_offset));
2881         }
2882
2883         if (ctx->eval.size > 0) {
2884                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack not empty (%d) after ret at 0x%04x", ctx->eval.size, ctx->ip_offset));
2885         } 
2886         if (in_any_block (ctx->header, ctx->ip_offset))
2887                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ret cannot escape exception blocks at 0x%04x", ctx->ip_offset));
2888 }
2889
2890 /*
2891  * FIXME we need to fix the case of a non-virtual instance method defined in the parent but call using a token pointing to a subclass.
2892  *      This is illegal but mono_get_method_full decoded it.
2893  * TODO handle calling .ctor outside one or calling the .ctor for other class but super  
2894  */
2895 static void
2896 do_invoke_method (VerifyContext *ctx, int method_token, gboolean virtual)
2897 {
2898         int param_count, i;
2899         MonoMethodSignature *sig;
2900         ILStackDesc *value;
2901         MonoMethod *method;
2902         gboolean virt_check_this = FALSE;
2903         gboolean constrained = ctx->prefix_set & PREFIX_CONSTRAINED;
2904
2905         if (!(method = verifier_load_method (ctx, method_token, virtual ? "callvirt" : "call")))
2906                 return;
2907
2908         if (virtual) {
2909                 CLEAR_PREFIX (ctx, PREFIX_CONSTRAINED);
2910
2911                 if (method->klass->valuetype) // && !constrained ???
2912                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use callvirtual with valuetype method at 0x%04x", ctx->ip_offset));
2913
2914                 if ((method->flags & METHOD_ATTRIBUTE_STATIC))
2915                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use callvirtual with static method at 0x%04x", ctx->ip_offset));
2916
2917         } else {
2918                 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT) 
2919                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use call with an abstract method at 0x%04x", ctx->ip_offset));
2920                 
2921                 if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED)) {
2922                         virt_check_this = TRUE;
2923                         ctx->code [ctx->ip_offset].flags |= IL_CODE_CALL_NONFINAL_VIRTUAL;
2924                 }
2925         }
2926
2927         if (!(sig = mono_method_get_signature_full (method, ctx->image, method_token, ctx->generic_context)))
2928                 sig = mono_method_get_signature (method, ctx->image, method_token);
2929
2930         if (!sig) {
2931                 char *name = mono_type_get_full_name (method->klass);
2932                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not resolve signature of %s:%s at 0x%04x", name, method->name, ctx->ip_offset));
2933                 g_free (name);
2934                 return;
2935         }
2936
2937         param_count = sig->param_count + sig->hasthis;
2938         if (!check_underflow (ctx, param_count))
2939                 return;
2940
2941         for (i = sig->param_count - 1; i >= 0; --i) {
2942                 VERIFIER_DEBUG ( printf ("verifying argument %d\n", i); );
2943                 value = stack_pop (ctx);
2944                 if (!verify_stack_type_compatibility (ctx, sig->params[i], value)) {
2945                         char *stack_name = stack_slot_full_name (value);
2946                         char *sig_name = mono_type_full_name (sig->params [i]);
2947                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible parameter with function signature: Calling method with signature (%s) but for argument %d there is a (%s) on stack at 0x%04x", sig_name, i, stack_name, ctx->ip_offset));
2948                         g_free (stack_name);
2949                         g_free (sig_name);
2950                 }
2951
2952                 if (stack_slot_is_managed_mutability_pointer (value))
2953                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer as argument of %s at 0x%04x", virtual ? "callvirt" : "call",  ctx->ip_offset));
2954
2955                 if ((ctx->prefix_set & PREFIX_TAIL) && stack_slot_is_managed_pointer (value)) {
2956                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot  pass a byref argument to a tail %s at 0x%04x", virtual ? "callvirt" : "call",  ctx->ip_offset));
2957                         return;
2958                 }
2959         }
2960
2961         if (sig->hasthis) {
2962                 MonoType *type = &method->klass->byval_arg;
2963                 ILStackDesc copy;
2964
2965                 if (mono_method_is_constructor (method) && !method->klass->valuetype) {
2966                         if (!mono_method_is_constructor (ctx->method))
2967                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a constructor outside one at 0x%04x", ctx->ip_offset));
2968                         if (method->klass != ctx->method->klass->parent && method->klass != ctx->method->klass)
2969                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a constructor to a type diferent that this or super at 0x%04x", ctx->ip_offset));
2970
2971                         ctx->super_ctor_called = TRUE;
2972                         value = stack_pop_safe (ctx);
2973                         if ((value->stype & THIS_POINTER_MASK) != THIS_POINTER_MASK)
2974                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid 'this ptr' argument for constructor at 0x%04x", ctx->ip_offset));
2975                 } else {
2976                         value = stack_pop (ctx);
2977                 }
2978                         
2979                 copy_stack_value (&copy, value);
2980                 //TODO we should extract this to a 'drop_byref_argument' and use everywhere
2981                 //Other parts of the code suffer from the same issue of 
2982                 copy.type = mono_type_get_type_byval (copy.type);
2983                 copy.stype &= ~POINTER_MASK;
2984
2985                 if (virt_check_this && !stack_slot_is_this_pointer (value) && !(method->klass->valuetype || stack_slot_is_boxed_value (value)))
2986                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the call opcode with a non-final virtual method on an object diferent thant the this pointer at 0x%04x", ctx->ip_offset));
2987
2988                 if (constrained && virtual) {
2989                         if (!stack_slot_is_managed_pointer (value))
2990                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Object is not a managed pointer for a constrained call at 0x%04x", ctx->ip_offset));
2991                         if (!mono_metadata_type_equal_full (mono_type_get_type_byval (value->type), ctx->constrained_type, TRUE))
2992                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Object not compatible with constrained type at 0x%04x", ctx->ip_offset));
2993                         copy.stype |= BOXED_MASK;
2994                 } else {
2995                         if (stack_slot_is_managed_pointer (value) && !mono_class_from_mono_type (value->type)->valuetype)
2996                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a reference type using a managed pointer to the this arg at 0x%04x", ctx->ip_offset));
2997         
2998                         if (!virtual && mono_class_from_mono_type (value->type)->valuetype && !method->klass->valuetype && !stack_slot_is_boxed_value (value))
2999                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a valuetype baseclass at 0x%04x", ctx->ip_offset));
3000         
3001                         if (virtual && mono_class_from_mono_type (value->type)->valuetype && !stack_slot_is_boxed_value (value))
3002                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a valuetype with callvirt at 0x%04x", ctx->ip_offset));
3003         
3004                         if (method->klass->valuetype && (stack_slot_is_boxed_value (value) || !stack_slot_is_managed_pointer (value)))
3005                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a boxed or literal valuetype to call a valuetype method at 0x%04x", ctx->ip_offset));
3006                 }
3007                 if (!verify_stack_type_compatibility (ctx, type, &copy)) {
3008                         char *expected = mono_type_full_name (type);
3009                         char *effective = stack_slot_full_name (&copy);
3010                         char *method_name = mono_method_full_name (method, TRUE);
3011                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible this argument on stack with method signature expected '%s' but got '%s' for a call to '%s' at 0x%04x",
3012                                         expected, effective, method_name, ctx->ip_offset));
3013                         g_free (method_name);
3014                         g_free (effective);
3015                         g_free (expected);
3016                 }
3017
3018                 if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, mono_class_from_mono_type (value->type))) {
3019                         char *name = mono_method_full_name (method, TRUE);
3020                         CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Method %s is not accessible at 0x%04x", name, ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
3021                         g_free (name);
3022                 }
3023
3024         } else if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, NULL)) {
3025                 char *name = mono_method_full_name (method, TRUE);
3026                 CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Method %s is not accessible at 0x%04x", name, ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
3027                 g_free (name);
3028         }
3029
3030         if (sig->ret->type != MONO_TYPE_VOID) {
3031                 if (check_overflow (ctx)) {
3032                         value = stack_push (ctx);
3033                         set_stack_value (ctx, value, sig->ret, FALSE);
3034                         if ((ctx->prefix_set & PREFIX_READONLY) && method->klass->rank && !strcmp (method->name, "Address")) {
3035                                 ctx->prefix_set &= ~PREFIX_READONLY;
3036                                 value->stype |= CMMP_MASK;
3037                         }
3038                 }
3039         }
3040
3041         if ((ctx->prefix_set & PREFIX_TAIL)) {
3042                 if (!mono_delegate_ret_equal (mono_method_signature (ctx->method)->ret, sig->ret))
3043                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Tail call with incompatible return type at 0x%04x", ctx->ip_offset));
3044                 if (ctx->header->code [ctx->ip_offset + 5] != CEE_RET)
3045                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Tail call not followed by ret at 0x%04x", ctx->ip_offset));
3046         }
3047
3048 }
3049
3050 static void
3051 do_push_static_field (VerifyContext *ctx, int token, gboolean take_addr)
3052 {
3053         MonoClassField *field;
3054         MonoClass *klass;
3055         if (!check_overflow (ctx))
3056                 return;
3057         if (!take_addr)
3058                 CLEAR_PREFIX (ctx, PREFIX_VOLATILE);
3059
3060         if (!(field = verifier_load_field (ctx, token, &klass, take_addr ? "ldsflda" : "ldsfld")))
3061                 return;
3062
3063         if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { 
3064                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot load non static field at 0x%04x", ctx->ip_offset));
3065                 return;
3066         }
3067         /*taking the address of initonly field only works from the static constructor */
3068         if (take_addr && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY) &&
3069                 !(field->parent == ctx->method->klass && (ctx->method->flags & (METHOD_ATTRIBUTE_SPECIAL_NAME | METHOD_ATTRIBUTE_STATIC)) && !strcmp (".cctor", ctx->method->name)))
3070                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a init-only field at 0x%04x", ctx->ip_offset));
3071
3072         if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, NULL))
3073                 CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
3074
3075         set_stack_value (ctx, stack_push (ctx), field->type, take_addr);
3076 }
3077
3078 static void
3079 do_store_static_field (VerifyContext *ctx, int token) {
3080         MonoClassField *field;
3081         MonoClass *klass;
3082         ILStackDesc *value;
3083         CLEAR_PREFIX (ctx, PREFIX_VOLATILE);
3084
3085         if (!check_underflow (ctx, 1))
3086                 return;
3087
3088         value = stack_pop (ctx);
3089
3090         if (!(field = verifier_load_field (ctx, token, &klass, "stsfld")))
3091                 return;
3092
3093         if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { 
3094                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot store non static field at 0x%04x", ctx->ip_offset));
3095                 return;
3096         }
3097
3098         if (field->type->type == MONO_TYPE_TYPEDBYREF) {
3099                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Typedbyref field is an unverfiable type in store static field at 0x%04x", ctx->ip_offset));
3100                 return;
3101         }
3102
3103         if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, NULL))
3104                 CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
3105
3106         if (!verify_stack_type_compatibility (ctx, field->type, value)) {
3107                 char *stack_name = stack_slot_full_name (value);
3108                 char *field_name = mono_type_full_name (field->type);
3109                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type in static field store expected '%s' but found '%s' at 0x%04x",
3110                                 field_name, stack_name, ctx->ip_offset));
3111                 g_free (field_name);
3112                 g_free (stack_name);
3113         }
3114 }
3115
3116 static gboolean
3117 check_is_valid_type_for_field_ops (VerifyContext *ctx, int token, ILStackDesc *obj, MonoClassField **ret_field, const char *opcode)
3118 {
3119         MonoClassField *field;
3120         MonoClass *klass;
3121         gboolean is_pointer;
3122
3123         /*must be a reference type, a managed pointer, an unamanaged pointer, or a valuetype*/
3124         if (!(field = verifier_load_field (ctx, token, &klass, opcode)))
3125                 return FALSE;
3126
3127         *ret_field = field;
3128         //the value on stack is going to be used as a pointer
3129         is_pointer = stack_slot_get_type (obj) == TYPE_PTR || (stack_slot_get_type (obj) == TYPE_NATIVE_INT && !get_stack_type (&field->parent->byval_arg));
3130
3131         if (field->type->type == MONO_TYPE_TYPEDBYREF) {
3132                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Typedbyref field is an unverfiable type at 0x%04x", ctx->ip_offset));
3133                 return FALSE;
3134         }
3135         g_assert (obj->type);
3136
3137         /*The value on the stack must be a subclass of the defining type of the field*/ 
3138         /* we need to check if we can load the field from the stack value*/
3139         if (is_pointer) {
3140                 if (stack_slot_get_underlying_type (obj) == TYPE_NATIVE_INT)
3141                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Native int is not a verifiable type to reference a field at 0x%04x", ctx->ip_offset));
3142
3143                 if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, NULL))
3144                                 CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
3145         } else {
3146                 if (!field->parent->valuetype && stack_slot_is_managed_pointer (obj))
3147                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is a managed pointer to a reference type and is not compatible to reference the field at 0x%04x", ctx->ip_offset));
3148
3149                 /*a value type can be loaded from a value or a managed pointer, but not a boxed object*/
3150                 if (field->parent->valuetype && stack_slot_is_boxed_value (obj))
3151                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is a boxed valuetype and is not compatible to reference the field at 0x%04x", ctx->ip_offset));
3152
3153                 if (!stack_slot_is_null_literal (obj) && !verify_stack_type_compatibility_full (ctx, &field->parent->byval_arg, obj, TRUE, FALSE)) {
3154                         char *found = stack_slot_full_name (obj);
3155                         char *expected = mono_type_full_name (&field->parent->byval_arg);
3156                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Expected type '%s' but found '%s' referencing the 'this' argument at 0x%04x", expected, found, ctx->ip_offset));
3157                         g_free (found);
3158                         g_free (expected);
3159                 }
3160
3161                 if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, mono_class_from_mono_type (obj->type)))
3162                         CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
3163         } 
3164
3165         check_unmanaged_pointer (ctx, obj);
3166         return TRUE;
3167 }
3168
3169 static void
3170 do_push_field (VerifyContext *ctx, int token, gboolean take_addr)
3171 {
3172         ILStackDesc *obj;
3173         MonoClassField *field;
3174
3175         if (!take_addr)
3176                 CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
3177
3178         if (!check_underflow (ctx, 1))
3179                 return;
3180         obj = stack_pop_safe (ctx);
3181
3182         if (!check_is_valid_type_for_field_ops (ctx, token, obj, &field, take_addr ? "ldflda" : "ldfld"))
3183                 return;
3184
3185         if (take_addr && field->parent->valuetype && !stack_slot_is_managed_pointer (obj))
3186                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a temporary value-type at 0x%04x", ctx->ip_offset));
3187
3188         if (take_addr && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY) &&
3189                 !(field->parent == ctx->method->klass && mono_method_is_constructor (ctx->method)))
3190                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a init-only field at 0x%04x", ctx->ip_offset));
3191
3192         set_stack_value (ctx, stack_push (ctx), field->type, take_addr);
3193 }
3194
3195 static void
3196 do_store_field (VerifyContext *ctx, int token)
3197 {
3198         ILStackDesc *value, *obj;
3199         MonoClassField *field;
3200         CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
3201
3202         if (!check_underflow (ctx, 2))
3203                 return;
3204
3205         value = stack_pop (ctx);
3206         obj = stack_pop_safe (ctx);
3207
3208         if (!check_is_valid_type_for_field_ops (ctx, token, obj, &field, "stfld"))
3209                 return;
3210
3211         if (!verify_stack_type_compatibility (ctx, field->type, value))
3212                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in field store at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));      
3213 }
3214
3215 /*TODO proper handle for Nullable<T>*/
3216 static void
3217 do_box_value (VerifyContext *ctx, int klass_token)
3218 {
3219         ILStackDesc *value;
3220         MonoType *type = get_boxable_mono_type (ctx, klass_token, "box");
3221         MonoClass *klass;       
3222
3223         if (!type)
3224                 return;
3225
3226         if (!check_underflow (ctx, 1))
3227                 return;
3228
3229         value = stack_pop (ctx);
3230         /*box is a nop for reference types*/
3231
3232         if (stack_slot_get_underlying_type (value) == TYPE_COMPLEX && MONO_TYPE_IS_REFERENCE (value->type) && MONO_TYPE_IS_REFERENCE (type)) {
3233                 stack_push_stack_val (ctx, value)->stype |= BOXED_MASK;
3234                 return;
3235         }
3236
3237
3238         if (!verify_stack_type_compatibility (ctx, type, value))
3239                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for boxing operation at 0x%04x", ctx->ip_offset));
3240
3241         klass = mono_class_from_mono_type (type);
3242         if (mono_class_is_nullable (klass))
3243                 type = &mono_class_get_nullable_param (klass)->byval_arg;
3244         stack_push_val (ctx, TYPE_COMPLEX | BOXED_MASK, type);
3245 }
3246
3247 static void
3248 do_unbox_value (VerifyContext *ctx, int klass_token)
3249 {
3250         ILStackDesc *value;
3251         MonoType *type = get_boxable_mono_type (ctx, klass_token, "unbox");
3252
3253         if (!type)
3254                 return;
3255  
3256         if (!check_underflow (ctx, 1))
3257                 return;
3258
3259         if (!mono_class_from_mono_type (type)->valuetype)
3260                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid reference type for unbox at 0x%04x", ctx->ip_offset));
3261
3262         value = stack_pop (ctx);
3263
3264         /*Value should be: a boxed valuetype or a reference type*/
3265         if (!(stack_slot_get_type (value) == TYPE_COMPLEX &&
3266                 (stack_slot_is_boxed_value (value) || !mono_class_from_mono_type (value->type)->valuetype)))
3267                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type %s at stack for unbox operation at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
3268
3269         set_stack_value (ctx, value = stack_push (ctx), mono_type_get_type_byref (type), FALSE);
3270         value->stype |= CMMP_MASK;
3271 }
3272
3273 static void
3274 do_unbox_any (VerifyContext *ctx, int klass_token)
3275 {
3276         ILStackDesc *value;
3277         MonoType *type = get_boxable_mono_type (ctx, klass_token, "unbox.any");
3278
3279         if (!type)
3280                 return;
3281  
3282         if (!check_underflow (ctx, 1))
3283                 return;
3284
3285         value = stack_pop (ctx);
3286
3287         /*Value should be: a boxed valuetype or a reference type*/
3288         if (!(stack_slot_get_type (value) == TYPE_COMPLEX &&
3289                 (stack_slot_is_boxed_value (value) || !mono_class_from_mono_type (value->type)->valuetype)))
3290                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type %s at stack for unbox.any operation at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
3291  
3292         set_stack_value (ctx, stack_push (ctx), type, FALSE);
3293 }
3294
3295 static void
3296 do_unary_math_op (VerifyContext *ctx, int op)
3297 {
3298         ILStackDesc *value;
3299         if (!check_underflow (ctx, 1))
3300                 return;
3301         value = stack_pop (ctx);
3302         switch (stack_slot_get_type (value)) {
3303         case TYPE_I4:
3304         case TYPE_I8:
3305         case TYPE_NATIVE_INT:
3306                 break;
3307         case TYPE_R8:
3308                 if (op == CEE_NEG)
3309                         break;
3310         case TYPE_COMPLEX: /*only enums are ok*/
3311                 if (mono_type_is_enum_type (value->type))
3312                         break;
3313         default:
3314                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for unary not at 0x%04x", ctx->ip_offset));
3315         }
3316         stack_push_stack_val (ctx, value);
3317 }
3318
3319 static void
3320 do_conversion (VerifyContext *ctx, int kind) 
3321 {
3322         ILStackDesc *value;
3323         if (!check_underflow (ctx, 1))
3324                 return;
3325         value = stack_pop (ctx);
3326
3327         switch (stack_slot_get_type (value)) {
3328         case TYPE_I4:
3329         case TYPE_I8:
3330         case TYPE_NATIVE_INT:
3331         case TYPE_R8:
3332                 break;
3333         default:
3334                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type (%s) at stack for conversion operation. Numeric type expected at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
3335         }
3336
3337         switch (kind) {
3338         case TYPE_I4:
3339                 stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
3340                 break;
3341         case TYPE_I8:
3342                 stack_push_val (ctx,TYPE_I8, &mono_defaults.int64_class->byval_arg);
3343                 break;
3344         case TYPE_R8:
3345                 stack_push_val (ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
3346                 break;
3347         case TYPE_NATIVE_INT:
3348                 stack_push_val (ctx, TYPE_NATIVE_INT, &mono_defaults.int_class->byval_arg);
3349                 break;
3350         default:
3351                 g_error ("unknown type %02x in conversion", kind);
3352
3353         }
3354 }
3355
3356 static void
3357 do_load_token (VerifyContext *ctx, int token) 
3358 {
3359         gpointer handle;
3360         MonoClass *handle_class;
3361         if (!check_overflow (ctx))
3362                 return;
3363
3364         switch (token & 0xff000000) {
3365         case MONO_TOKEN_TYPE_DEF:
3366         case MONO_TOKEN_TYPE_REF:
3367         case MONO_TOKEN_TYPE_SPEC:
3368         case MONO_TOKEN_FIELD_DEF:
3369         case MONO_TOKEN_METHOD_DEF:
3370         case MONO_TOKEN_METHOD_SPEC:
3371         case MONO_TOKEN_MEMBER_REF:
3372                 if (!token_bounds_check (ctx->image, token)) {
3373                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Table index out of range 0x%x for token %x for ldtoken at 0x%04x", mono_metadata_token_index (token), token, ctx->ip_offset));
3374                         return;
3375                 }
3376                 break;
3377         default:
3378                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid table 0x%x for token 0x%x for ldtoken at 0x%04x", mono_metadata_token_table (token), token, ctx->ip_offset));
3379                 return;
3380         }
3381
3382         handle = mono_ldtoken (ctx->image, token, &handle_class, ctx->generic_context);
3383         if (!handle) {
3384                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x", token, ctx->ip_offset));
3385                 return;
3386         }
3387         if (handle_class == mono_defaults.typehandle_class) {
3388                 mono_type_is_valid_in_context (ctx, (MonoType*)handle);
3389         } else if (handle_class == mono_defaults.methodhandle_class) {
3390                 mono_method_is_valid_in_context (ctx, (MonoMethod*)handle);             
3391         } else if (handle_class == mono_defaults.fieldhandle_class) {
3392                 mono_type_is_valid_in_context (ctx, &((MonoClassField*)handle)->parent->byval_arg);                             
3393         } else {
3394                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid ldtoken type %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
3395         }
3396         stack_push_val (ctx, TYPE_COMPLEX, mono_class_get_type (handle_class));
3397 }
3398
3399 static void
3400 do_ldobj_value (VerifyContext *ctx, int token) 
3401 {
3402         ILStackDesc *value;
3403         MonoType *type = get_boxable_mono_type (ctx, token, "ldobj");
3404         CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
3405
3406         if (!type)
3407                 return;
3408
3409         if (!check_underflow (ctx, 1))
3410                 return;
3411
3412         value = stack_pop (ctx);
3413         if (!stack_slot_is_managed_pointer (value) 
3414                         && stack_slot_get_type (value) != TYPE_NATIVE_INT
3415                         && !(stack_slot_get_type (value) == TYPE_PTR && value->type->type != MONO_TYPE_FNPTR)) {
3416                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid argument %s to ldobj at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
3417                 return;
3418         }
3419
3420         if (stack_slot_get_type (value) == TYPE_NATIVE_INT)
3421                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Using native pointer to ldobj at 0x%04x", ctx->ip_offset));
3422
3423         /*We have a byval on the stack, but the comparison must be strict. */
3424         if (!verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (value->type), TRUE))
3425                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldojb operation at 0x%04x", ctx->ip_offset));
3426
3427         set_stack_value (ctx, stack_push (ctx), type, FALSE);
3428 }
3429
3430 static void
3431 do_stobj (VerifyContext *ctx, int token) 
3432 {
3433         ILStackDesc *dest, *src;
3434         MonoType *type = get_boxable_mono_type (ctx, token, "stobj");
3435         CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
3436
3437         if (!type)
3438                 return;
3439
3440         if (!check_underflow (ctx, 2))
3441                 return;
3442
3443         src = stack_pop (ctx);
3444         dest = stack_pop (ctx);
3445
3446         if (stack_slot_is_managed_mutability_pointer (dest))
3447                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with stobj at 0x%04x", ctx->ip_offset));
3448
3449         if (!stack_slot_is_managed_pointer (dest)) 
3450                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid destination of stobj operation at 0x%04x", ctx->ip_offset));
3451
3452         if (stack_slot_is_boxed_value (src) && !MONO_TYPE_IS_REFERENCE (src->type) && !MONO_TYPE_IS_REFERENCE (type))
3453                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use stobj with a boxed source value that is not a reference type at 0x%04x", ctx->ip_offset));
3454
3455         if (!verify_stack_type_compatibility (ctx, type, src)) {
3456                 char *type_name = mono_type_full_name (type);
3457                 char *src_name = stack_slot_full_name (src);
3458                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Token '%s' and source '%s' of stobj don't match ' at 0x%04x", type_name, src_name, ctx->ip_offset));
3459                 g_free (type_name);
3460                 g_free (src_name);
3461         }
3462
3463         if (!verify_type_compatibility (ctx, mono_type_get_type_byval (dest->type), type))
3464                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Destination and token types of stobj don't match at 0x%04x", ctx->ip_offset));
3465 }
3466
3467 static void
3468 do_cpobj (VerifyContext *ctx, int token)
3469 {
3470         ILStackDesc *dest, *src;
3471         MonoType *type = get_boxable_mono_type (ctx, token, "cpobj");
3472         if (!type)
3473                 return;
3474
3475         if (!check_underflow (ctx, 2))
3476                 return;
3477
3478         src = stack_pop (ctx);
3479         dest = stack_pop (ctx);
3480
3481         if (!stack_slot_is_managed_pointer (src)) 
3482                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid source of cpobj operation at 0x%04x", ctx->ip_offset));
3483
3484         if (!stack_slot_is_managed_pointer (dest)) 
3485                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid destination of cpobj operation at 0x%04x", ctx->ip_offset));
3486
3487         if (stack_slot_is_managed_mutability_pointer (dest))
3488                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with cpobj at 0x%04x", ctx->ip_offset));
3489
3490         if (!verify_type_compatibility (ctx, type, mono_type_get_type_byval (src->type)))
3491                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Token and source types of cpobj don't match at 0x%04x", ctx->ip_offset));
3492
3493         if (!verify_type_compatibility (ctx, mono_type_get_type_byval (dest->type), type))
3494                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Destination and token types of cpobj don't match at 0x%04x", ctx->ip_offset));
3495 }
3496
3497 static void
3498 do_initobj (VerifyContext *ctx, int token)
3499 {
3500         ILStackDesc *obj;
3501         MonoType *stack, *type = get_boxable_mono_type (ctx, token, "initobj");
3502         if (!type)
3503                 return;
3504
3505         if (!check_underflow (ctx, 1))
3506                 return;
3507
3508         obj = stack_pop (ctx);
3509
3510         if (!stack_slot_is_managed_pointer (obj)) 
3511                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid object address for initobj at 0x%04x", ctx->ip_offset));
3512
3513         if (stack_slot_is_managed_mutability_pointer (obj))
3514                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with initobj at 0x%04x", ctx->ip_offset));
3515
3516         stack = mono_type_get_type_byval (obj->type);
3517         if (MONO_TYPE_IS_REFERENCE (stack)) {
3518                 if (!verify_type_compatibility (ctx, stack, type)) 
3519                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type token of initobj not compatible with value on stack at 0x%04x", ctx->ip_offset));
3520                 else if (IS_STRICT_MODE (ctx) && !mono_metadata_type_equal (type, stack)) 
3521                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type token of initobj not compatible with value on stack at 0x%04x", ctx->ip_offset));
3522         } else if (!verify_type_compatibility (ctx, stack, type)) {
3523                 char *expected_name = mono_type_full_name (type);
3524                 char *stack_name = mono_type_full_name (stack);
3525
3526                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Initobj %s not compatible with value on stack %s at 0x%04x", expected_name, stack_name, ctx->ip_offset));
3527                 g_free (expected_name);
3528                 g_free (stack_name);
3529         }
3530 }
3531
3532 static void
3533 do_newobj (VerifyContext *ctx, int token) 
3534 {
3535         ILStackDesc *value;
3536         int i;
3537         MonoMethodSignature *sig;
3538         MonoMethod *method;
3539         gboolean is_delegate = FALSE;
3540
3541         if (!(method = verifier_load_method (ctx, token, "newobj")))
3542                 return;
3543
3544         if (!mono_method_is_constructor (method)) {
3545                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method from token 0x%08x not a constructor at 0x%04x", token, ctx->ip_offset));
3546                 return;
3547         }
3548
3549         if (method->klass->flags & (TYPE_ATTRIBUTE_ABSTRACT | TYPE_ATTRIBUTE_INTERFACE))
3550                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Trying to instantiate an abstract or interface type at 0x%04x", ctx->ip_offset));
3551
3552         if (!mono_method_can_access_method_full (ctx->method, method, NULL)) {
3553                 char *from = mono_method_full_name (ctx->method, TRUE);
3554                 char *to = mono_method_full_name (method, TRUE);
3555                 CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Constructor %s not visible from %s at 0x%04x", to, from, ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
3556                 g_free (from);
3557                 g_free (to);
3558         }
3559
3560         //FIXME use mono_method_get_signature_full
3561         sig = mono_method_signature (method);
3562         if (!sig) {
3563                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid constructor signature to newobj at 0x%04x", ctx->ip_offset));
3564                 return;
3565         }
3566
3567         if (!sig->hasthis) {
3568                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid constructor signature missing hasthis at 0x%04x", ctx->ip_offset));
3569                 return;
3570         }
3571
3572         if (!check_underflow (ctx, sig->param_count))
3573                 return;
3574
3575         is_delegate = method->klass->parent == mono_defaults.multicastdelegate_class;
3576
3577         if (is_delegate) {
3578                 ILStackDesc *funptr;
3579                 //first arg is object, second arg is fun ptr
3580                 if (sig->param_count != 2) {
3581                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid delegate constructor at 0x%04x", ctx->ip_offset));
3582                         return;
3583                 }
3584                 funptr = stack_pop (ctx);
3585                 value = stack_pop (ctx);
3586                 verify_delegate_compatibility (ctx, method->klass, value, funptr);
3587         } else {
3588                 for (i = sig->param_count - 1; i >= 0; --i) {
3589                         VERIFIER_DEBUG ( printf ("verifying constructor argument %d\n", i); );
3590                         value = stack_pop (ctx);
3591                         if (!verify_stack_type_compatibility (ctx, sig->params [i], value)) {
3592                                 char *stack_name = stack_slot_full_name (value);
3593                                 char *sig_name = mono_type_full_name (sig->params [i]);
3594                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible parameter value with constructor signature: %s X %s at 0x%04x", sig_name, stack_name, ctx->ip_offset));
3595                                 g_free (stack_name);
3596                                 g_free (sig_name);
3597                         }
3598
3599                         if (stack_slot_is_managed_mutability_pointer (value))
3600                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer as argument of newobj at 0x%04x", ctx->ip_offset));
3601                 }
3602         }
3603
3604         if (check_overflow (ctx))
3605                 set_stack_value (ctx, stack_push (ctx),  &method->klass->byval_arg, FALSE);
3606 }
3607
3608 static void
3609 do_cast (VerifyContext *ctx, int token, const char *opcode) {
3610         ILStackDesc *value;
3611         MonoType *type;
3612         gboolean is_boxed;
3613         gboolean do_box;
3614
3615         if (!check_underflow (ctx, 1))
3616                 return;
3617
3618         if (!(type = get_boxable_mono_type (ctx, token, opcode)))
3619                 return;
3620
3621         if (type->byref) {
3622                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid %s type at 0x%04x", opcode, ctx->ip_offset));
3623                 return;
3624         }
3625
3626         value = stack_pop (ctx);
3627         is_boxed = stack_slot_is_boxed_value (value);
3628
3629         if (stack_slot_is_managed_pointer (value))
3630                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value for %s at 0x%04x", opcode, ctx->ip_offset));
3631         else if (!MONO_TYPE_IS_REFERENCE  (value->type) && !is_boxed) {
3632                 char *name = stack_slot_full_name (value);
3633                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Expected a reference type on stack for %s but found %s at 0x%04x", opcode, name, ctx->ip_offset));
3634                 g_free (name);
3635         }
3636
3637         switch (value->type->type) {
3638         case MONO_TYPE_FNPTR:
3639         case MONO_TYPE_PTR:
3640         case MONO_TYPE_TYPEDBYREF: 
3641                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value for %s at 0x%04x", opcode, ctx->ip_offset));
3642         }
3643
3644         do_box = is_boxed || mono_type_is_generic_argument(type) || mono_class_from_mono_type (type)->valuetype;
3645         stack_push_val (ctx, TYPE_COMPLEX | (do_box ? BOXED_MASK : 0), type);
3646 }
3647
3648 static MonoType *
3649 mono_type_from_opcode (int opcode) {
3650         switch (opcode) {
3651         case CEE_LDIND_I1:
3652         case CEE_LDIND_U1:
3653         case CEE_STIND_I1:
3654         case CEE_LDELEM_I1:
3655         case CEE_LDELEM_U1:
3656         case CEE_STELEM_I1:
3657                 return &mono_defaults.sbyte_class->byval_arg;
3658
3659         case CEE_LDIND_I2:
3660         case CEE_LDIND_U2:
3661         case CEE_STIND_I2:
3662         case CEE_LDELEM_I2:
3663         case CEE_LDELEM_U2:
3664         case CEE_STELEM_I2:
3665                 return &mono_defaults.int16_class->byval_arg;
3666
3667         case CEE_LDIND_I4:
3668         case CEE_LDIND_U4:
3669         case CEE_STIND_I4:
3670         case CEE_LDELEM_I4:
3671         case CEE_LDELEM_U4:
3672         case CEE_STELEM_I4:
3673                 return &mono_defaults.int32_class->byval_arg;
3674
3675         case CEE_LDIND_I8:
3676         case CEE_STIND_I8:
3677         case CEE_LDELEM_I8:
3678         case CEE_STELEM_I8:
3679                 return &mono_defaults.int64_class->byval_arg;
3680
3681         case CEE_LDIND_R4:
3682         case CEE_STIND_R4:
3683         case CEE_LDELEM_R4:
3684         case CEE_STELEM_R4:
3685                 return &mono_defaults.single_class->byval_arg;
3686
3687         case CEE_LDIND_R8:
3688         case CEE_STIND_R8:
3689         case CEE_LDELEM_R8:
3690         case CEE_STELEM_R8:
3691                 return &mono_defaults.double_class->byval_arg;
3692
3693         case CEE_LDIND_I:
3694         case CEE_STIND_I:
3695         case CEE_LDELEM_I:
3696         case CEE_STELEM_I:
3697                 return &mono_defaults.int_class->byval_arg;
3698
3699         case CEE_LDIND_REF:
3700         case CEE_STIND_REF:
3701         case CEE_LDELEM_REF:
3702         case CEE_STELEM_REF:
3703                 return &mono_defaults.object_class->byval_arg;
3704
3705         default:
3706                 g_error ("unknown opcode %02x in mono_type_from_opcode ", opcode);
3707                 return NULL;
3708         }
3709 }
3710
3711 static void
3712 do_load_indirect (VerifyContext *ctx, int opcode)
3713 {
3714         ILStackDesc *value;
3715         CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
3716
3717         if (!check_underflow (ctx, 1))
3718                 return;
3719         
3720         value = stack_pop (ctx);
3721         if (!stack_slot_is_managed_pointer (value)) {
3722                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Load indirect not using a manager pointer at 0x%04x", ctx->ip_offset));
3723                 set_stack_value (ctx, stack_push (ctx), mono_type_from_opcode (opcode), FALSE);
3724                 return;
3725         }
3726
3727         if (opcode == CEE_LDIND_REF) {
3728                 if (stack_slot_get_underlying_type (value) != TYPE_COMPLEX || mono_class_from_mono_type (value->type)->valuetype)
3729                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldind_ref expected object byref operation at 0x%04x", ctx->ip_offset));
3730                 set_stack_value (ctx, stack_push (ctx), mono_type_get_type_byval (value->type), FALSE);
3731         } else {
3732                 if (!verify_type_compatibility_full (ctx, mono_type_from_opcode (opcode), mono_type_get_type_byval (value->type), TRUE))
3733                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldind 0x%x operation at 0x%04x", opcode, ctx->ip_offset));
3734                 set_stack_value (ctx, stack_push (ctx), mono_type_from_opcode (opcode), FALSE);
3735         }
3736 }
3737
3738 static void
3739 do_store_indirect (VerifyContext *ctx, int opcode)
3740 {
3741         ILStackDesc *addr, *val;
3742         CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
3743
3744         if (!check_underflow (ctx, 2))
3745                 return;
3746
3747         val = stack_pop (ctx);
3748         addr = stack_pop (ctx); 
3749
3750         check_unmanaged_pointer (ctx, addr);
3751
3752         if (!stack_slot_is_managed_pointer (addr) && stack_slot_get_type (addr) != TYPE_PTR) {
3753                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid non-pointer argument to stind at 0x%04x", ctx->ip_offset));
3754                 return;
3755         }
3756
3757         if (stack_slot_is_managed_mutability_pointer (addr)) {
3758                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with stind at 0x%04x", ctx->ip_offset));
3759                 return;
3760         }
3761
3762         if (!verify_type_compatibility_full (ctx, mono_type_from_opcode (opcode), mono_type_get_type_byval (addr->type), TRUE))
3763                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid addr type at stack for stind 0x%x operation at 0x%04x", opcode, ctx->ip_offset));
3764
3765         if (!verify_stack_type_compatibility (ctx, mono_type_from_opcode (opcode), val))
3766                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value type at stack for stind 0x%x operation at 0x%04x", opcode, ctx->ip_offset));
3767 }
3768
3769 static void
3770 do_newarr (VerifyContext *ctx, int token) 
3771 {
3772         ILStackDesc *value;
3773         MonoType *type = get_boxable_mono_type (ctx, token, "newarr");
3774
3775         if (!type)
3776                 return;
3777
3778         if (!check_underflow (ctx, 1))
3779                 return;
3780
3781         value = stack_pop (ctx);
3782         if (stack_slot_get_type (value) != TYPE_I4 && stack_slot_get_type (value) != TYPE_NATIVE_INT)
3783                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Array size type on stack (%s) is not a verifiable type at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
3784
3785         set_stack_value (ctx, stack_push (ctx), mono_class_get_type (mono_array_class_get (mono_class_from_mono_type (type), 1)), FALSE);
3786 }
3787
3788 /*FIXME handle arrays that are not 0-indexed*/
3789 static void
3790 do_ldlen (VerifyContext *ctx)
3791 {
3792         ILStackDesc *value;
3793
3794         if (!check_underflow (ctx, 1))
3795                 return;
3796
3797         value = stack_pop (ctx);
3798
3799         if (stack_slot_get_type (value) != TYPE_COMPLEX || value->type->type != MONO_TYPE_SZARRAY)
3800                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type for ldlen at 0x%04x", ctx->ip_offset));
3801
3802         stack_push_val (ctx, TYPE_NATIVE_INT, &mono_defaults.int_class->byval_arg);     
3803 }
3804
3805 /*FIXME handle arrays that are not 0-indexed*/
3806 /*FIXME handle readonly prefix and CMMP*/
3807 static void
3808 do_ldelema (VerifyContext *ctx, int klass_token)
3809 {
3810         ILStackDesc *index, *array, *res;
3811         MonoType *type = get_boxable_mono_type (ctx, klass_token, "ldelema");
3812         gboolean valid; 
3813
3814         if (!type)
3815                 return;
3816
3817         if (!check_underflow (ctx, 2))
3818                 return;
3819
3820         index = stack_pop (ctx);
3821         array = stack_pop (ctx);
3822
3823         if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type (index) != TYPE_NATIVE_INT)
3824                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for ldelema is not an int or a native int at 0x%04x", stack_slot_get_name (index), ctx->ip_offset));
3825
3826         if (!stack_slot_is_null_literal (array)) {
3827                 if (stack_slot_get_type (array) != TYPE_COMPLEX || array->type->type != MONO_TYPE_SZARRAY)
3828                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type(%s) for ldelema at 0x%04x", stack_slot_get_name (array), ctx->ip_offset));
3829                 else {
3830                         if (get_stack_type (type) == TYPE_I4 || get_stack_type (type) == TYPE_NATIVE_INT) {
3831                                         valid = verify_type_compatibility_full (ctx, type, &array->type->data.klass->byval_arg, TRUE);
3832                         } else {
3833                                 valid = mono_metadata_type_equal (type, &array->type->data.klass->byval_arg);
3834                         }
3835                         if (!valid)
3836                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for ldelema at 0x%04x", ctx->ip_offset));
3837                 }
3838         }
3839
3840         res = stack_push (ctx);
3841         set_stack_value (ctx, res, type, TRUE);
3842         if (ctx->prefix_set & PREFIX_READONLY) {
3843                 ctx->prefix_set &= ~PREFIX_READONLY;
3844                 res->stype |= CMMP_MASK;
3845         }
3846 }
3847
3848 /*
3849  * FIXME handle arrays that are not 0-indexed
3850  * FIXME handle readonly prefix and CMMP
3851  */
3852 static void
3853 do_ldelem (VerifyContext *ctx, int opcode, int token)
3854 {
3855 #define IS_ONE_OF2(T, A, B) (T == A || T == B)
3856         ILStackDesc *index, *array;
3857         MonoType *type;
3858         if (!check_underflow (ctx, 2))
3859                 return;
3860
3861         if (opcode == CEE_LDELEM) {
3862                 if (!(type = verifier_load_type (ctx, token, "ldelem.any"))) {
3863                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Type (0x%08x) not found at 0x%04x", token, ctx->ip_offset));
3864                         return;
3865                 }
3866         } else {
3867                 type = mono_type_from_opcode (opcode);
3868         }
3869
3870         index = stack_pop (ctx);
3871         array = stack_pop (ctx);
3872
3873         if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type (index) != TYPE_NATIVE_INT)
3874                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for ldelem.X is not an int or a native int at 0x%04x", stack_slot_get_name (index), ctx->ip_offset));
3875
3876         if (!stack_slot_is_null_literal (array)) {
3877                 if (stack_slot_get_type (array) != TYPE_COMPLEX || array->type->type != MONO_TYPE_SZARRAY)
3878                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type(%s) for ldelem.X at 0x%04x", stack_slot_get_name (array), ctx->ip_offset));
3879                 else {
3880                         if (opcode == CEE_LDELEM_REF) {
3881                                 if (array->type->data.klass->valuetype)
3882                                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type is not a reference type for ldelem.ref 0x%04x", ctx->ip_offset));
3883                                 type = &array->type->data.klass->byval_arg;
3884                         } else {
3885                                 MonoType *candidate = &array->type->data.klass->byval_arg;
3886                                 if (IS_STRICT_MODE (ctx)) {
3887                                         MonoType *underlying_type = mono_type_get_underlying_type_any (type);
3888                                         MonoType *underlying_candidate = mono_type_get_underlying_type_any (candidate);
3889                                         if ((IS_ONE_OF2 (underlying_type->type, MONO_TYPE_I4, MONO_TYPE_U4) && IS_ONE_OF2 (underlying_candidate->type, MONO_TYPE_I, MONO_TYPE_U)) ||
3890                                                 (IS_ONE_OF2 (underlying_candidate->type, MONO_TYPE_I4, MONO_TYPE_U4) && IS_ONE_OF2 (underlying_type->type, MONO_TYPE_I, MONO_TYPE_U)))
3891                                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for ldelem.X at 0x%04x", ctx->ip_offset));
3892                                 }
3893                                 if (!verify_type_compatibility_full (ctx, type, candidate, TRUE))
3894                                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for ldelem.X at 0x%04x", ctx->ip_offset));
3895                         }
3896                 }
3897         }
3898
3899         set_stack_value (ctx, stack_push (ctx), type, FALSE);
3900 #undef IS_ONE_OF2
3901 }
3902
3903 /*
3904  * FIXME handle arrays that are not 0-indexed
3905  */
3906 static void
3907 do_stelem (VerifyContext *ctx, int opcode, int token)
3908 {
3909         ILStackDesc *index, *array, *value;
3910         MonoType *type;
3911         if (!check_underflow (ctx, 3))
3912                 return;
3913
3914         if (opcode == CEE_STELEM) {
3915                 if (!(type = verifier_load_type (ctx, token, "stelem.any"))) {
3916                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Type (0x%08x) not found at 0x%04x", token, ctx->ip_offset));
3917                         return;
3918                 }
3919         } else {
3920                 type = mono_type_from_opcode (opcode);
3921         }
3922         
3923         value = stack_pop (ctx);
3924         index = stack_pop (ctx);
3925         array = stack_pop (ctx);
3926
3927         if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type (index) != TYPE_NATIVE_INT)
3928                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for stdelem.X is not an int or a native int at 0x%04x", stack_slot_get_name (index), ctx->ip_offset));
3929
3930         if (!stack_slot_is_null_literal (array)) {
3931                 if (stack_slot_get_type (array) != TYPE_COMPLEX || array->type->type != MONO_TYPE_SZARRAY) {
3932                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type(%s) for stelem.X at 0x%04x", stack_slot_get_name (array), ctx->ip_offset));
3933                 } else {
3934                         if (opcode == CEE_STELEM_REF) {
3935                                 if (array->type->data.klass->valuetype)
3936                                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type is not a reference type for stelem.ref 0x%04x", ctx->ip_offset));
3937                         } else if (!verify_type_compatibility_full (ctx, &array->type->data.klass->byval_arg, type, TRUE)) {
3938                                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for stdelem.X at 0x%04x", ctx->ip_offset));
3939                         }
3940                 }
3941         }
3942         if (opcode == CEE_STELEM_REF) {
3943                 if (!stack_slot_is_boxed_value (value) && mono_class_from_mono_type (value->type)->valuetype)
3944                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value is not a reference type for stelem.ref 0x%04x", ctx->ip_offset));
3945         } else if (opcode != CEE_STELEM_REF) {
3946                 if (!verify_stack_type_compatibility (ctx, type, value))
3947                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value on stack for stdelem.X at 0x%04x", ctx->ip_offset));
3948
3949                 if (stack_slot_is_boxed_value (value) && !MONO_TYPE_IS_REFERENCE (value->type) && !MONO_TYPE_IS_REFERENCE (type))
3950                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use stobj with a boxed source value that is not a reference type at 0x%04x", ctx->ip_offset));
3951
3952         }
3953 }
3954
3955 static void
3956 do_throw (VerifyContext *ctx)
3957 {
3958         ILStackDesc *exception;
3959         if (!check_underflow (ctx, 1))
3960                 return;
3961         exception = stack_pop (ctx);
3962
3963         if (!stack_slot_is_null_literal (exception) && !(stack_slot_get_type (exception) == TYPE_COMPLEX && !mono_class_from_mono_type (exception->type)->valuetype))
3964                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type on stack for throw, expected reference type at 0x%04x", ctx->ip_offset));
3965
3966         if (mono_type_is_generic_argument (exception->type) && !stack_slot_is_boxed_value (exception)) {
3967                 char *name = mono_type_full_name (exception->type);
3968                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type on stack for throw, expected reference type but found unboxed %s  at 0x%04x ", name, ctx->ip_offset));
3969                 g_free (name);
3970         }
3971         /*The stack is left empty after a throw*/
3972         ctx->eval.size = 0;
3973 }
3974
3975
3976 static void
3977 do_endfilter (VerifyContext *ctx)
3978 {
3979         MonoExceptionClause *clause;
3980
3981         if (IS_STRICT_MODE (ctx)) {
3982                 if (ctx->eval.size != 1)
3983                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack size must have one item for endfilter at 0x%04x", ctx->ip_offset));
3984
3985                 if (ctx->eval.size >= 1 && stack_slot_get_type (stack_pop (ctx)) != TYPE_I4)
3986                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack item type is not an int32 for endfilter at 0x%04x", ctx->ip_offset));
3987         }
3988
3989         if ((clause = is_correct_endfilter (ctx, ctx->ip_offset))) {
3990                 if (IS_STRICT_MODE (ctx)) {
3991                         if (ctx->ip_offset != clause->handler_offset - 2)
3992                                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("endfilter is not the last instruction of the filter clause at 0x%04x", ctx->ip_offset));                       
3993                 } else {
3994                         if ((ctx->ip_offset != clause->handler_offset - 2) && !MONO_OFFSET_IN_HANDLER (clause, ctx->ip_offset))
3995                                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("endfilter is not the last instruction of the filter clause at 0x%04x", ctx->ip_offset));
3996                 }
3997         } else {
3998                 if (IS_STRICT_MODE (ctx) && !is_unverifiable_endfilter (ctx, ctx->ip_offset))
3999                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("endfilter outside filter clause at 0x%04x", ctx->ip_offset));
4000                 else
4001                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("endfilter outside filter clause at 0x%04x", ctx->ip_offset));
4002         }
4003
4004         ctx->eval.size = 0;
4005 }
4006
4007 static void
4008 do_leave (VerifyContext *ctx, int delta)
4009 {
4010         int target = ((gint32)ctx->ip_offset) + delta;
4011         if (target >= ctx->code_size || target < 0)
4012                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target out of code at 0x%04x", ctx->ip_offset));
4013
4014         if (!is_correct_leave (ctx->header, ctx->ip_offset, target))
4015                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Leave not allowed in finally block at 0x%04x", ctx->ip_offset));
4016         ctx->eval.size = 0;
4017         ctx->target = target;
4018 }
4019
4020 /* 
4021  * do_static_branch:
4022  * 
4023  * Verify br and br.s opcodes.
4024  */
4025 static void
4026 do_static_branch (VerifyContext *ctx, int delta)
4027 {
4028         int target = ctx->ip_offset + delta;
4029         if (target < 0 || target >= ctx->code_size) {
4030                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("branch target out of code at 0x%04x", ctx->ip_offset));
4031                 return;
4032         }
4033
4034         switch (is_valid_branch_instruction (ctx->header, ctx->ip_offset, target)) {
4035         case 1:
4036                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
4037                 break;
4038         case 2:
4039                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
4040                 break;
4041         }
4042
4043         ctx->target = target;
4044 }
4045
4046 static void
4047 do_switch (VerifyContext *ctx, int count, const unsigned char *data)
4048 {
4049         int i, base = ctx->ip_offset + 5 + count * 4;
4050         ILStackDesc *value;
4051
4052         if (!check_underflow (ctx, 1))
4053                 return;
4054
4055         value = stack_pop (ctx);
4056
4057         if (stack_slot_get_type (value) != TYPE_I4 && stack_slot_get_type (value) != TYPE_NATIVE_INT)
4058                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid argument to switch at 0x%04x", ctx->ip_offset));
4059
4060         for (i = 0; i < count; ++i) {
4061                 int target = base + read32 (data + i * 4);
4062
4063                 if (target < 0 || target >= ctx->code_size) {
4064                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Switch target %x out of code at 0x%04x", i, ctx->ip_offset));
4065                         return;
4066                 }
4067
4068                 switch (is_valid_branch_instruction (ctx->header, ctx->ip_offset, target)) {
4069                 case 1:
4070                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Switch target %x escapes out of exception block at 0x%04x", i, ctx->ip_offset));
4071                         break;
4072                 case 2:
4073                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Switch target %x escapes out of exception block at 0x%04x", i, ctx->ip_offset));
4074                         return;
4075                 }
4076                 merge_stacks (ctx, &ctx->eval, &ctx->code [target], FALSE, TRUE);
4077         }
4078 }
4079
4080 static void
4081 do_load_function_ptr (VerifyContext *ctx, guint32 token, gboolean virtual)
4082 {
4083         ILStackDesc *top;
4084         MonoMethod *method;
4085
4086         if (virtual && !check_underflow (ctx, 1))
4087                 return;
4088
4089         if (!virtual && !check_overflow (ctx))
4090                 return;
4091
4092         if (!IS_METHOD_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
4093                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid token %x for ldftn  at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
4094                 return;
4095         }
4096
4097         if (!(method = verifier_load_method (ctx, token, virtual ? "ldvirtfrn" : "ldftn")))
4098                 return;
4099
4100         if (mono_method_is_constructor (method))
4101                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use ldftn with a constructor at 0x%04x", ctx->ip_offset));
4102
4103         if (virtual) {
4104                 ILStackDesc *top = stack_pop (ctx);
4105         
4106                 if (stack_slot_get_type (top) != TYPE_COMPLEX || top->type->type == MONO_TYPE_VALUETYPE)
4107                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid argument to ldvirtftn at 0x%04x", ctx->ip_offset));
4108         
4109                 if (method->flags & METHOD_ATTRIBUTE_STATIC)
4110                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use ldvirtftn with a constructor at 0x%04x", ctx->ip_offset));
4111
4112                 if (!verify_stack_type_compatibility (ctx, &method->klass->byval_arg, top))
4113                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Unexpected object for ldvirtftn at 0x%04x", ctx->ip_offset));
4114         }
4115         
4116         if (!mono_method_can_access_method_full (ctx->method, method, NULL))
4117                 CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Loaded method is not visible for ldftn/ldvirtftn at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
4118
4119         top = stack_push_val(ctx, TYPE_PTR, mono_type_create_fnptr_from_mono_method (ctx, method));
4120         top->method = method;
4121 }
4122
4123 static void
4124 do_sizeof (VerifyContext *ctx, int token)
4125 {
4126         MonoType *type;
4127
4128         if (!IS_TYPE_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
4129                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid type token %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
4130                 return;
4131         }
4132         
4133         if (!(type = verifier_load_type (ctx, token, "sizeof")))
4134                 return;
4135
4136         if (type->byref && type->type != MONO_TYPE_TYPEDBYREF) {
4137                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of byref type at 0x%04x", ctx->ip_offset));
4138                 return;
4139         }
4140
4141         if (type->type == MONO_TYPE_VOID) {
4142                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of void type at 0x%04x", ctx->ip_offset));
4143                 return;
4144         }
4145
4146         if (check_overflow (ctx))
4147                 set_stack_value (ctx, stack_push (ctx), &mono_defaults.uint32_class->byval_arg, FALSE);
4148 }
4149
4150 /* Stack top can be of any type, the runtime doesn't care and treat everything as an int. */
4151 static void
4152 do_localloc (VerifyContext *ctx)
4153 {
4154         ILStackDesc *top;
4155         
4156         if (ctx->eval.size != 1) {
4157                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack must have only size item in localloc at 0x%04x", ctx->ip_offset));
4158                 return;         
4159         }
4160
4161         if (in_any_exception_block (ctx->header, ctx->ip_offset)) {
4162                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack must have only size item in localloc at 0x%04x", ctx->ip_offset));
4163                 return;
4164         }
4165
4166         /*TODO verify top type*/
4167         top = stack_pop (ctx);
4168
4169         set_stack_value (ctx, stack_push (ctx), &mono_defaults.int_class->byval_arg, FALSE);
4170         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Instruction localloc in never verifiable at 0x%04x", ctx->ip_offset));
4171 }
4172
4173 static void
4174 do_ldstr (VerifyContext *ctx, guint32 token)
4175 {
4176         GSList *error = NULL;
4177         if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
4178                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid string token %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
4179                 return;
4180         }
4181
4182         if (!ctx->image->dynamic && !mono_verifier_verify_string_signature (ctx->image, mono_metadata_token_index (token), &error)) {
4183                 if (error)
4184                         ctx->list = g_slist_concat (ctx->list, error);
4185                 ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid string index %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
4186                 return;
4187         }
4188
4189         if (check_overflow (ctx))
4190                 stack_push_val (ctx, TYPE_COMPLEX,  &mono_defaults.string_class->byval_arg);
4191 }
4192
4193 static void
4194 do_refanyval (VerifyContext *ctx, int token)
4195 {
4196         ILStackDesc *top;
4197         MonoType *type;
4198         if (!check_underflow (ctx, 1))
4199                 return;
4200
4201         if (!(type = get_boxable_mono_type (ctx, token, "refanyval")))
4202                 return;
4203
4204         top = stack_pop (ctx);
4205
4206         if (top->stype != TYPE_PTR || top->type->type != MONO_TYPE_TYPEDBYREF)
4207                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Expected a typedref as argument for refanyval, but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
4208
4209         set_stack_value (ctx, stack_push (ctx), type, TRUE);
4210 }
4211
4212 static void
4213 do_refanytype (VerifyContext *ctx)
4214 {
4215         ILStackDesc *top;
4216
4217         if (!check_underflow (ctx, 1))
4218                 return;
4219
4220         top = stack_pop (ctx);
4221
4222         if (top->stype != TYPE_PTR || top->type->type != MONO_TYPE_TYPEDBYREF)
4223                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Expected a typedref as argument for refanytype, but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
4224
4225         set_stack_value (ctx, stack_push (ctx), &mono_defaults.typehandle_class->byval_arg, FALSE);
4226
4227 }
4228
4229 static void
4230 do_mkrefany (VerifyContext *ctx, int token)
4231 {
4232         ILStackDesc *top;
4233         MonoType *type;
4234         if (!check_underflow (ctx, 1))
4235                 return;
4236
4237         if (!(type = get_boxable_mono_type (ctx, token, "refanyval")))
4238                 return;
4239
4240         top = stack_pop (ctx);
4241
4242         if (stack_slot_is_managed_mutability_pointer (top))
4243                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with mkrefany at 0x%04x", ctx->ip_offset));
4244
4245         if (!stack_slot_is_managed_pointer (top)) {
4246                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Expected a managed pointer for mkrefany, but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
4247         }else {
4248                 MonoType *stack_type = mono_type_get_type_byval (top->type);
4249                 if (MONO_TYPE_IS_REFERENCE (type) && !mono_metadata_type_equal (type, stack_type))
4250                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type not compatible for mkrefany at 0x%04x", ctx->ip_offset));
4251                         
4252                 if (!MONO_TYPE_IS_REFERENCE (type) && !verify_type_compatibility_full (ctx, type, stack_type, TRUE))
4253                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type not compatible for mkrefany at 0x%04x", ctx->ip_offset));
4254         }
4255
4256         set_stack_value (ctx, stack_push (ctx), &mono_defaults.typed_reference_class->byval_arg, FALSE);
4257 }
4258
4259 static void
4260 do_ckfinite (VerifyContext *ctx)
4261 {
4262         ILStackDesc *top;
4263         if (!check_underflow (ctx, 1))
4264                 return;
4265
4266         top = stack_pop (ctx);
4267
4268         if (stack_slot_get_underlying_type (top) != TYPE_R8)
4269                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Expected float32 or float64 on stack for ckfinit but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset)); 
4270         stack_push_stack_val (ctx, top);
4271 }
4272 /*
4273  * merge_stacks:
4274  * Merge the stacks and perform compat checks. The merge check if types of @from are mergeable with type of @to 
4275  * 
4276  * @from holds new values for a given control path
4277  * @to holds the current values of a given control path
4278  * 
4279  * TODO we can eliminate the from argument as all callers pass &ctx->eval
4280  */
4281 static void
4282 merge_stacks (VerifyContext *ctx, ILCodeDesc *from, ILCodeDesc *to, gboolean start, gboolean external) 
4283 {
4284         MonoError error;
4285         int i, j, k;
4286         stack_init (ctx, to);
4287
4288         if (start) {
4289                 if (to->flags == IL_CODE_FLAG_NOT_PROCESSED) 
4290                         from->size = 0;
4291                 else
4292                         stack_copy (&ctx->eval, to);
4293                 goto end_verify;
4294         } else if (!(to->flags & IL_CODE_STACK_MERGED)) {
4295                 stack_copy (to, &ctx->eval);
4296                 goto end_verify;
4297         }
4298         VERIFIER_DEBUG ( printf ("performing stack merge %d x %d\n", from->size, to->size); );
4299
4300         if (from->size != to->size) {
4301                 VERIFIER_DEBUG ( printf ("different stack sizes %d x %d at 0x%04x\n", from->size, to->size, ctx->ip_offset); );
4302                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not merge stacks, different sizes (%d x %d) at 0x%04x", from->size, to->size, ctx->ip_offset)); 
4303                 goto end_verify;
4304         }
4305
4306         //FIXME we need to preserve CMMP attributes
4307         //FIXME we must take null literals into consideration.
4308         for (i = 0; i < from->size; ++i) {
4309                 ILStackDesc *new_slot = from->stack + i;
4310                 ILStackDesc *old_slot = to->stack + i;
4311                 MonoType *new_type = mono_type_from_stack_slot (new_slot);
4312                 MonoType *old_type = mono_type_from_stack_slot (old_slot);
4313                 MonoClass *old_class = mono_class_from_mono_type (old_type);
4314                 MonoClass *new_class = mono_class_from_mono_type (new_type);
4315                 MonoClass *match_class = NULL;
4316
4317                 // S := T then U = S (new value is compatible with current value, keep current)
4318                 if (verify_stack_type_compatibility (ctx, old_type, new_slot)) {
4319                         copy_stack_value (new_slot, old_slot);
4320                         continue;
4321                 }
4322
4323                 // T := S then U = T (old value is compatible with current value, use new)
4324                 if (verify_stack_type_compatibility (ctx, new_type, old_slot)) {
4325                         copy_stack_value (old_slot, new_slot);
4326                         continue;
4327                 }
4328
4329                 if (mono_type_is_generic_argument (old_type) || mono_type_is_generic_argument (new_type)) {
4330                         char *old_name = stack_slot_full_name (old_slot); 
4331                         char *new_name = stack_slot_full_name (new_slot);
4332                         CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge stack at depth %d, types not compatible: %s X %s at 0x%04x", i, old_name, new_name, ctx->ip_offset));
4333                         g_free (old_name);
4334                         g_free (new_name);
4335                         goto end_verify;                        
4336                 } 
4337
4338                 //both are reference types, use closest common super type
4339                 if (!mono_class_from_mono_type (old_type)->valuetype 
4340                         && !mono_class_from_mono_type (new_type)->valuetype
4341                         && !stack_slot_is_managed_pointer (old_slot)
4342                         && !stack_slot_is_managed_pointer (new_slot)) {
4343                         
4344                         for (j = MIN (old_class->idepth, new_class->idepth) - 1; j > 0; --j) {
4345                                 if (mono_metadata_type_equal (&old_class->supertypes [j]->byval_arg, &new_class->supertypes [j]->byval_arg)) {
4346                                         match_class = old_class->supertypes [j];
4347                                         goto match_found;
4348                                 }
4349                         }
4350
4351                         mono_class_setup_interfaces (old_class, &error);
4352                         if (!mono_error_ok (&error)) {
4353                                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot merge stacks due to a TypeLoadException %s at 0x%04x", mono_error_get_message (&error), ctx->ip_offset));
4354                                 mono_error_cleanup (&error);
4355                                 goto end_verify;
4356                         }
4357                         for (j = 0; j < old_class->interface_count; ++j) {
4358                                 for (k = 0; k < new_class->interface_count; ++k) {
4359                                         if (mono_metadata_type_equal (&old_class->interfaces [j]->byval_arg, &new_class->interfaces [k]->byval_arg)) {
4360                                                 match_class = old_class->interfaces [j];
4361                                                 goto match_found;
4362                                         }
4363                                 }
4364                         }
4365
4366                         //No decent super type found, use object
4367                         match_class = mono_defaults.object_class;
4368                         goto match_found;
4369                 } else if (is_compatible_boxed_valuetype (ctx,old_type, new_type, new_slot, FALSE) || is_compatible_boxed_valuetype (ctx, new_type, old_type, old_slot, FALSE)) {
4370                         match_class = mono_defaults.object_class;
4371                         goto match_found;
4372                 }
4373
4374                 {
4375                 char *old_name = stack_slot_full_name (old_slot); 
4376                 char *new_name = stack_slot_full_name (new_slot);
4377                 CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge stack at depth %d, types not compatible: %s X %s at 0x%04x", i, old_name, new_name, ctx->ip_offset)); 
4378                 g_free (old_name);
4379                 g_free (new_name);
4380                 }
4381                 set_stack_value (ctx, old_slot, &new_class->byval_arg, stack_slot_is_managed_pointer (old_slot));
4382                 goto end_verify;
4383
4384 match_found:
4385                 g_assert (match_class);
4386                 set_stack_value (ctx, old_slot, &match_class->byval_arg, stack_slot_is_managed_pointer (old_slot));
4387                 set_stack_value (ctx, new_slot, &match_class->byval_arg, stack_slot_is_managed_pointer (old_slot));
4388                 continue;
4389         }
4390
4391 end_verify:
4392         if (external)
4393                 to->flags |= IL_CODE_FLAG_WAS_TARGET;
4394         to->flags |= IL_CODE_STACK_MERGED;
4395 }
4396
4397 #define HANDLER_START(clause) ((clause)->flags == MONO_EXCEPTION_CLAUSE_FILTER ? (clause)->data.filter_offset : clause->handler_offset)
4398 #define IS_CATCH_OR_FILTER(clause) ((clause)->flags == MONO_EXCEPTION_CLAUSE_FILTER || (clause)->flags == MONO_EXCEPTION_CLAUSE_NONE)
4399
4400 /*
4401  * is_clause_in_range :
4402  * 
4403  * Returns TRUE if either the protected block or the handler of @clause is in the @start - @end range.  
4404  */
4405 static gboolean
4406 is_clause_in_range (MonoExceptionClause *clause, guint32 start, guint32 end)
4407 {
4408         if (clause->try_offset >= start && clause->try_offset < end)
4409                 return TRUE;
4410         if (HANDLER_START (clause) >= start && HANDLER_START (clause) < end)
4411                 return TRUE;
4412         return FALSE;
4413 }
4414
4415 /*
4416  * is_clause_inside_range :
4417  * 
4418  * Returns TRUE if @clause lies completely inside the @start - @end range.  
4419  */
4420 static gboolean
4421 is_clause_inside_range (MonoExceptionClause *clause, guint32 start, guint32 end)
4422 {
4423         if (clause->try_offset < start || (clause->try_offset + clause->try_len) > end)
4424                 return FALSE;
4425         if (HANDLER_START (clause) < start || (clause->handler_offset + clause->handler_len) > end)
4426                 return FALSE;
4427         return TRUE;
4428 }
4429
4430 /*
4431  * is_clause_nested :
4432  * 
4433  * Returns TRUE if @nested is nested in @clause.   
4434  */
4435 static gboolean
4436 is_clause_nested (MonoExceptionClause *clause, MonoExceptionClause *nested)
4437 {
4438         if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER && is_clause_inside_range (nested, clause->data.filter_offset, clause->handler_offset))
4439                 return TRUE;
4440         return is_clause_inside_range (nested, clause->try_offset, clause->try_offset + clause->try_len) ||
4441         is_clause_inside_range (nested, clause->handler_offset, clause->handler_offset + clause->handler_len);
4442 }
4443
4444 /* Test the relationship between 2 exception clauses. Follow  P.1 12.4.2.7 of ECMA
4445  * the each pair of exception must have the following properties:
4446  *  - one is fully nested on another (the outer must not be a filter clause) (the nested one must come earlier)
4447  *  - completely disjoin (none of the 3 regions of each entry overlap with the other 3)
4448  *  - mutual protection (protected block is EXACT the same, handlers are disjoin and all handler are catch or all handler are filter)
4449  */
4450 static void
4451 verify_clause_relationship (VerifyContext *ctx, MonoExceptionClause *clause, MonoExceptionClause *to_test)
4452 {
4453         /*clause is nested*/
4454         if (to_test->flags == MONO_EXCEPTION_CLAUSE_FILTER && is_clause_inside_range (clause, to_test->data.filter_offset, to_test->handler_offset)) {
4455                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clause inside filter"));
4456                 return;
4457         }
4458
4459         /*wrong nesting order.*/
4460         if (is_clause_nested (clause, to_test)) {
4461                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Nested exception clause appears after enclosing clause"));
4462                 return;
4463         }
4464
4465         /*mutual protection*/
4466         if (clause->try_offset == to_test->try_offset && clause->try_len == to_test->try_len) {
4467                 /*handlers are not disjoint*/
4468                 if (is_clause_in_range (to_test, HANDLER_START (clause), clause->handler_offset + clause->handler_len)) {
4469                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception handlers overlap"));
4470                         return;
4471                 }
4472                 /* handlers are not catch or filter */
4473                 if (!IS_CATCH_OR_FILTER (clause) || !IS_CATCH_OR_FILTER (to_test)) {
4474                         ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clauses with shared protected block are neither catch or filter"));
4475                         return;
4476                 }
4477                 /*OK*/
4478                 return;
4479         }
4480
4481         /*not completelly disjoint*/
4482         if ((is_clause_in_range (to_test, clause->try_offset, clause->try_offset + clause->try_len) ||
4483                 is_clause_in_range (to_test, HANDLER_START (clause), clause->handler_offset + clause->handler_len)) && !is_clause_nested (to_test, clause))
4484                 ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clauses overlap"));
4485 }
4486
4487 #define code_bounds_check(size) \
4488         if (ADDP_IS_GREATER_OR_OVF (ip, size, end)) {\
4489                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Code overrun starting with 0x%x at 0x%04x", *ip, ctx.ip_offset)); \
4490                 break; \
4491         } \
4492
4493 static gboolean
4494 mono_opcode_is_prefix (int op)
4495 {
4496         switch (op) {
4497         case MONO_CEE_UNALIGNED_:
4498         case MONO_CEE_VOLATILE_:
4499         case MONO_CEE_TAIL_:
4500         case MONO_CEE_CONSTRAINED_:
4501         case MONO_CEE_READONLY_:
4502                 return TRUE;
4503         }
4504         return FALSE;
4505 }
4506
4507 /*
4508  * FIXME: need to distinguish between valid and verifiable.
4509  * Need to keep track of types on the stack.
4510  * Verify types for opcodes.
4511  */
4512 GSList*
4513 mono_method_verify (MonoMethod *method, int level)
4514 {
4515         MonoError error;
4516         const unsigned char *ip, *code_start;
4517         const unsigned char *end;
4518         MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL;
4519
4520         int i, n, need_merge = 0, start = 0;
4521         guint token, ip_offset = 0, prefix = 0;
4522         MonoGenericContext *generic_context = NULL;
4523         MonoImage *image;
4524         VerifyContext ctx;
4525         GSList *tmp;
4526         VERIFIER_DEBUG ( printf ("Verify IL for method %s %s %s\n",  method->klass->name_space,  method->klass->name, method->name); );
4527
4528         init_verifier_stats ();
4529
4530         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
4531                         (method->flags & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT))) {
4532                 return NULL;
4533         }
4534
4535         memset (&ctx, 0, sizeof (VerifyContext));
4536
4537         //FIXME use mono_method_get_signature_full
4538         ctx.signature = mono_method_signature (method);
4539         if (!ctx.signature) {
4540                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Could not decode method signature"));
4541
4542                 finish_collect_stats ();
4543                 return ctx.list;
4544         }
4545         ctx.header = mono_method_get_header (method);
4546         if (!ctx.header) {
4547                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Could not decode method header"));
4548                 finish_collect_stats ();
4549                 return ctx.list;
4550         }
4551         ctx.method = method;
4552         code_start = ip = ctx.header->code;
4553         end = ip + ctx.header->code_size;
4554         ctx.image = image = method->klass->image;
4555
4556
4557         ctx.max_args = ctx.signature->param_count + ctx.signature->hasthis;
4558         ctx.max_stack = ctx.header->max_stack;
4559         ctx.verifiable = ctx.valid = 1;
4560         ctx.level = level;
4561
4562         ctx.code = g_new (ILCodeDesc, ctx.header->code_size);
4563         ctx.code_size = ctx.header->code_size;
4564         MEM_ALLOC (sizeof (ILCodeDesc) * ctx.header->code_size);
4565
4566         memset(ctx.code, 0, sizeof (ILCodeDesc) * ctx.header->code_size);
4567
4568         ctx.num_locals = ctx.header->num_locals;
4569         ctx.locals = g_memdup (ctx.header->locals, sizeof (MonoType*) * ctx.header->num_locals);
4570         MEM_ALLOC (sizeof (MonoType*) * ctx.header->num_locals);
4571
4572         if (ctx.num_locals > 0 && !ctx.header->init_locals)
4573                 CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Method with locals variable but without init locals set"));
4574
4575         ctx.params = g_new (MonoType*, ctx.max_args);
4576         MEM_ALLOC (sizeof (MonoType*) * ctx.max_args);
4577
4578         if (ctx.signature->hasthis)
4579                 ctx.params [0] = method->klass->valuetype ? &method->klass->this_arg : &method->klass->byval_arg;
4580         memcpy (ctx.params + ctx.signature->hasthis, ctx.signature->params, sizeof (MonoType *) * ctx.signature->param_count);
4581
4582         if (ctx.signature->is_inflated)
4583                 ctx.generic_context = generic_context = mono_method_get_context (method);
4584
4585         if (!generic_context && (method->klass->generic_container || method->is_generic)) {
4586                 if (method->is_generic)
4587                         ctx.generic_context = generic_context = &(mono_method_get_generic_container (method)->context);
4588                 else
4589                         ctx.generic_context = generic_context = &method->klass->generic_container->context;
4590         }
4591
4592         for (i = 0; i < ctx.num_locals; ++i) {
4593                 MonoType *uninflated = ctx.locals [i];
4594                 ctx.locals [i] = mono_class_inflate_generic_type_checked (ctx.locals [i], ctx.generic_context, &error);
4595                 if (!mono_error_ok (&error)) {
4596                         char *name = mono_type_full_name (ctx.locals [i] ? ctx.locals [i] : uninflated);
4597                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid local %d of type %s", i, name));
4598                         g_free (name);
4599                         mono_error_cleanup (&error);
4600                         /* we must not free (in cleanup) what was not yet allocated (but only copied) */
4601                         ctx.num_locals = i;
4602                         ctx.max_args = 0;
4603                         goto cleanup;
4604                 }
4605         }
4606         for (i = 0; i < ctx.max_args; ++i) {
4607                 MonoType *uninflated = ctx.params [i];
4608                 ctx.params [i] = mono_class_inflate_generic_type_checked (ctx.params [i], ctx.generic_context, &error);
4609                 if (!mono_error_ok (&error)) {
4610                         char *name = mono_type_full_name (ctx.params [i] ? ctx.params [i] : uninflated);
4611                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid parameter %d of type %s", i, name));
4612                         g_free (name);
4613                         mono_error_cleanup (&error);
4614                         /* we must not free (in cleanup) what was not yet allocated (but only copied) */
4615                         ctx.max_args = i;
4616                         goto cleanup;
4617                 }
4618         }
4619         stack_init (&ctx, &ctx.eval);
4620
4621         for (i = 0; i < ctx.num_locals; ++i) {
4622                 if (!mono_type_is_valid_in_context (&ctx, ctx.locals [i]))
4623                         break;
4624                 if (get_stack_type (ctx.locals [i]) == TYPE_INV) {
4625                         char *name = mono_type_full_name (ctx.locals [i]);
4626                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid local %i of type %s", i, name));
4627                         g_free (name);
4628                         break;
4629                 }
4630                 
4631         }
4632
4633         for (i = 0; i < ctx.max_args; ++i) {
4634                 if (!mono_type_is_valid_in_context (&ctx, ctx.params [i]))
4635                         break;
4636
4637                 if (get_stack_type (ctx.params [i]) == TYPE_INV) {
4638                         char *name = mono_type_full_name (ctx.params [i]);
4639                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid parameter %i of type %s", i, name));
4640                         g_free (name);
4641                         break;
4642                 }
4643         }
4644
4645         if (!ctx.valid)
4646                 goto cleanup;
4647
4648         for (i = 0; i < ctx.header->num_clauses && ctx.valid; ++i) {
4649                 MonoExceptionClause *clause = ctx.header->clauses + i;
4650                 VERIFIER_DEBUG (printf ("clause try %x len %x filter at %x handler at %x len %x\n", clause->try_offset, clause->try_len, clause->data.filter_offset, clause->handler_offset, clause->handler_len); );
4651
4652                 if (clause->try_offset > ctx.code_size || ADD_IS_GREATER_OR_OVF (clause->try_offset, clause->try_len, ctx.code_size))
4653                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("try clause out of bounds at 0x%04x", clause->try_offset));
4654
4655                 if (clause->try_len <= 0)
4656                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("try clause len <= 0 at 0x%04x", clause->try_offset));
4657
4658                 if (clause->handler_offset > ctx.code_size || ADD_IS_GREATER_OR_OVF (clause->handler_offset, clause->handler_len, ctx.code_size))
4659                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("handler clause out of bounds at 0x%04x", clause->try_offset));
4660
4661                 if (clause->handler_len <= 0)
4662                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("handler clause len <= 0 at 0x%04x", clause->try_offset));
4663
4664                 if (clause->try_offset < clause->handler_offset && ADD_IS_GREATER_OR_OVF (clause->try_offset, clause->try_len, HANDLER_START (clause)))
4665                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("try block (at 0x%04x) includes handler block (at 0x%04x)", clause->try_offset, clause->handler_offset));
4666
4667                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
4668                         if (clause->data.filter_offset > ctx.code_size)
4669                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("filter clause out of bounds at 0x%04x", clause->try_offset));
4670
4671                         if (clause->data.filter_offset >= clause->handler_offset)
4672                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("filter clause must come before the handler clause at 0x%04x", clause->data.filter_offset));
4673                 }
4674
4675                 for (n = i + 1; n < ctx.header->num_clauses && ctx.valid; ++n)
4676                         verify_clause_relationship (&ctx, clause, ctx.header->clauses + n);
4677
4678                 if (!ctx.valid)
4679                         break;
4680
4681                 ctx.code [clause->try_offset].flags |= IL_CODE_FLAG_WAS_TARGET;
4682                 if (clause->try_offset + clause->try_len < ctx.code_size)
4683                         ctx.code [clause->try_offset + clause->try_len].flags |= IL_CODE_FLAG_WAS_TARGET;
4684                 if (clause->handler_offset + clause->handler_len < ctx.code_size)
4685                         ctx.code [clause->handler_offset + clause->handler_len].flags |= IL_CODE_FLAG_WAS_TARGET;
4686
4687                 if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
4688                         if (!clause->data.catch_class) {
4689                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Catch clause %d with invalid type", i));
4690                                 break;
4691                         }
4692                 
4693                         init_stack_with_value_at_exception_boundary (&ctx, ctx.code + clause->handler_offset, clause->data.catch_class);
4694                 }
4695                 else if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
4696                         init_stack_with_value_at_exception_boundary (&ctx, ctx.code + clause->data.filter_offset, mono_defaults.exception_class);
4697                         init_stack_with_value_at_exception_boundary (&ctx, ctx.code + clause->handler_offset, mono_defaults.exception_class);   
4698                 }
4699         }
4700
4701         original_bb = bb = mono_basic_block_split (method, &error);
4702         if (!mono_error_ok (&error)) {
4703                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid branch target: %s", mono_error_get_message (&error)));
4704                 mono_error_cleanup (&error);
4705                 goto cleanup;
4706         }
4707         g_assert (bb);
4708
4709         while (ip < end && ctx.valid) {
4710                 int op_size;
4711                 ip_offset = ip - code_start;
4712                 {
4713                         const unsigned char *ip_copy = ip;
4714                         int op;
4715
4716                         if (ip_offset > bb->end) {
4717                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or EH block at [0x%04x] targets middle instruction at 0x%04x", bb->end, ip_offset));
4718                                 goto cleanup;
4719                         }
4720
4721                         if (ip_offset == bb->end)
4722                                 bb = bb->next;
4723         
4724                         op_size = mono_opcode_value_and_size (&ip_copy, end, &op);
4725                         if (op_size == -1) {
4726                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction %x at 0x%04x", *ip, ip_offset));
4727                                 goto cleanup;
4728                         }
4729
4730                         if (ADD_IS_GREATER_OR_OVF (ip_offset, op_size, bb->end)) {
4731                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or EH block targets middle of instruction at 0x%04x", ip_offset));
4732                                 goto cleanup;
4733                         }
4734
4735                         /*Last Instruction*/
4736                         if (ip_offset + op_size == bb->end && mono_opcode_is_prefix (op)) {
4737                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or EH block targets between prefix '%s' and instruction at 0x%04x", mono_opcode_name (op), ip_offset));
4738                                 goto cleanup;
4739                         }
4740                 }
4741
4742                 ctx.ip_offset = ip_offset = ip - code_start;
4743
4744                 /*We need to check against fallthrou in and out of protected blocks.
4745                  * For fallout we check the once a protected block ends, if the start flag is not set.
4746                  * Likewise for fallthru in, we check if ip is the start of a protected block and start is not set
4747                  * TODO convert these checks to be done using flags and not this loop
4748                  */
4749                 for (i = 0; i < ctx.header->num_clauses && ctx.valid; ++i) {
4750                         MonoExceptionClause *clause = ctx.header->clauses + i;
4751
4752                         if ((clause->try_offset + clause->try_len == ip_offset) && start == 0) {
4753                                 CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("fallthru off try block at 0x%04x", ip_offset));
4754                                 start = 1;
4755                         }
4756
4757                         if ((clause->handler_offset + clause->handler_len == ip_offset) && start == 0) {
4758                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
4759                                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("fallout of handler block at 0x%04x", ip_offset));
4760                                 else
4761                                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("fallout of handler block at 0x%04x", ip_offset));
4762                                 start = 1;
4763                         }
4764
4765                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER && clause->handler_offset == ip_offset && start == 0) {
4766                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("fallout of filter block at 0x%04x", ip_offset));
4767                                 start = 1;
4768                         }
4769
4770                         if (clause->handler_offset == ip_offset && start == 0) {
4771                                 CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("fallthru handler block at 0x%04x", ip_offset));
4772                                 start = 1;
4773                         }
4774
4775                         if (clause->try_offset == ip_offset && ctx.eval.size > 0 && start == 0) {
4776                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Try to enter try block with a non-empty stack at 0x%04x", ip_offset));
4777                                 start = 1;
4778                         }
4779                 }
4780
4781                 /*This must be done after fallthru detection otherwise it won't happen.*/
4782                 if (bb->dead) {
4783                         /*FIXME remove this once we move all bad branch checking code to use BB only*/
4784                         ctx.code [ip_offset].flags |= IL_CODE_FLAG_SEEN;
4785                         ip += op_size;
4786                         continue;
4787                 }
4788
4789                 if (!ctx.valid)
4790                         break;
4791
4792                 if (need_merge) {
4793                         VERIFIER_DEBUG ( printf ("extra merge needed! 0x%04x \n", ctx.target); );
4794                         merge_stacks (&ctx, &ctx.eval, &ctx.code [ctx.target], FALSE, TRUE);
4795                         need_merge = 0; 
4796                 }
4797                 merge_stacks (&ctx, &ctx.eval, &ctx.code[ip_offset], start, FALSE);
4798                 start = 0;
4799
4800                 /*TODO we can fast detect a forward branch or exception block targeting code after prefix, we should fail fast*/
4801 #ifdef MONO_VERIFIER_DEBUG
4802                 {
4803                         char *discode;
4804                         discode = mono_disasm_code_one (NULL, method, ip, NULL);
4805                         discode [strlen (discode) - 1] = 0; /* no \n */
4806                         g_print ("[%d] %-29s (%d)\n",  ip_offset, discode, ctx.eval.size);
4807                         g_free (discode);
4808                 }
4809                 dump_stack_state (&ctx.code [ip_offset]);
4810                 dump_stack_state (&ctx.eval);
4811 #endif
4812
4813                 switch (*ip) {
4814                 case CEE_NOP:
4815                 case CEE_BREAK:
4816                         ++ip;
4817                         break;
4818
4819                 case CEE_LDARG_0:
4820                 case CEE_LDARG_1:
4821                 case CEE_LDARG_2:
4822                 case CEE_LDARG_3:
4823                         push_arg (&ctx, *ip - CEE_LDARG_0, FALSE);
4824                         ++ip;
4825                         break;
4826
4827                 case CEE_LDARG_S:
4828                 case CEE_LDARGA_S:
4829                         code_bounds_check (2);
4830                         push_arg (&ctx, ip [1],  *ip == CEE_LDARGA_S);
4831                         ip += 2;
4832                         break;
4833
4834                 case CEE_ADD_OVF_UN:
4835                         do_binop (&ctx, *ip, add_ovf_un_table);
4836                         ++ip;
4837                         break;
4838
4839                 case CEE_SUB_OVF_UN:
4840                         do_binop (&ctx, *ip, sub_ovf_un_table);
4841                         ++ip;
4842                         break;
4843
4844                 case CEE_ADD_OVF:
4845                 case CEE_SUB_OVF:
4846                 case CEE_MUL_OVF:
4847                 case CEE_MUL_OVF_UN:
4848                         do_binop (&ctx, *ip, bin_ovf_table);
4849                         ++ip;
4850                         break;
4851
4852                 case CEE_ADD:
4853                         do_binop (&ctx, *ip, add_table);
4854                         ++ip;
4855                         break;
4856
4857                 case CEE_SUB:
4858                         do_binop (&ctx, *ip, sub_table);
4859                         ++ip;
4860                         break;
4861
4862                 case CEE_MUL:
4863                 case CEE_DIV:
4864                 case CEE_REM:
4865                         do_binop (&ctx, *ip, bin_op_table);
4866                         ++ip;
4867                         break;
4868
4869                 case CEE_AND:
4870                 case CEE_DIV_UN:
4871                 case CEE_OR:
4872                 case CEE_REM_UN:
4873                 case CEE_XOR:
4874                         do_binop (&ctx, *ip, int_bin_op_table);
4875                         ++ip;
4876                         break;
4877
4878                 case CEE_SHL:
4879                 case CEE_SHR:
4880                 case CEE_SHR_UN:
4881                         do_binop (&ctx, *ip, shift_op_table);
4882                         ++ip;
4883                         break;
4884
4885                 case CEE_POP:
4886                         if (!check_underflow (&ctx, 1))
4887                                 break;
4888                         stack_pop_safe (&ctx);
4889                         ++ip;
4890                         break;
4891
4892                 case CEE_RET:
4893                         do_ret (&ctx);
4894                         ++ip;
4895                         start = 1;
4896                         break;
4897
4898                 case CEE_LDLOC_0:
4899                 case CEE_LDLOC_1:
4900                 case CEE_LDLOC_2:
4901                 case CEE_LDLOC_3:
4902                         /*TODO support definite assignment verification? */
4903                         push_local (&ctx, *ip - CEE_LDLOC_0, FALSE);
4904                         ++ip;
4905                         break;
4906
4907                 case CEE_STLOC_0:
4908                 case CEE_STLOC_1:
4909                 case CEE_STLOC_2:
4910                 case CEE_STLOC_3:
4911                         store_local (&ctx, *ip - CEE_STLOC_0);
4912                         ++ip;
4913                         break;
4914
4915                 case CEE_STLOC_S:
4916                         code_bounds_check (2);
4917                         store_local (&ctx, ip [1]);
4918                         ip += 2;
4919                         break;
4920
4921                 case CEE_STARG_S:
4922                         code_bounds_check (2);
4923                         store_arg (&ctx, ip [1]);
4924                         ip += 2;
4925                         break;
4926
4927                 case CEE_LDC_I4_M1:
4928                 case CEE_LDC_I4_0:
4929                 case CEE_LDC_I4_1:
4930                 case CEE_LDC_I4_2:
4931                 case CEE_LDC_I4_3:
4932                 case CEE_LDC_I4_4:
4933                 case CEE_LDC_I4_5:
4934                 case CEE_LDC_I4_6:
4935                 case CEE_LDC_I4_7:
4936                 case CEE_LDC_I4_8:
4937                         if (check_overflow (&ctx))
4938                                 stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
4939                         ++ip;
4940                         break;
4941
4942                 case CEE_LDC_I4_S:
4943                         code_bounds_check (2);
4944                         if (check_overflow (&ctx))
4945                                 stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
4946                         ip += 2;
4947                         break;
4948
4949                 case CEE_LDC_I4:
4950                         code_bounds_check (5);
4951                         if (check_overflow (&ctx))
4952                                 stack_push_val (&ctx,TYPE_I4, &mono_defaults.int32_class->byval_arg);
4953                         ip += 5;
4954                         break;
4955
4956                 case CEE_LDC_I8:
4957                         code_bounds_check (9);
4958                         if (check_overflow (&ctx))
4959                                 stack_push_val (&ctx,TYPE_I8, &mono_defaults.int64_class->byval_arg);
4960                         ip += 9;
4961                         break;
4962
4963                 case CEE_LDC_R4:
4964                         code_bounds_check (5);
4965                         if (check_overflow (&ctx))
4966                                 stack_push_val (&ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
4967                         ip += 5;
4968                         break;
4969
4970                 case CEE_LDC_R8:
4971                         code_bounds_check (9);
4972                         if (check_overflow (&ctx))
4973                                 stack_push_val (&ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
4974                         ip += 9;
4975                         break;
4976
4977                 case CEE_LDNULL:
4978                         if (check_overflow (&ctx))
4979                                 stack_push_val (&ctx, TYPE_COMPLEX | NULL_LITERAL_MASK, &mono_defaults.object_class->byval_arg);
4980                         ++ip;
4981                         break;
4982
4983                 case CEE_BEQ_S:
4984                 case CEE_BNE_UN_S:
4985                         code_bounds_check (2);
4986                         do_branch_op (&ctx, (signed char)ip [1] + 2, cmp_br_eq_op);
4987                         ip += 2;
4988                         need_merge = 1;
4989                         break;
4990
4991                 case CEE_BGE_S:
4992                 case CEE_BGT_S:
4993                 case CEE_BLE_S:
4994                 case CEE_BLT_S:
4995                 case CEE_BGE_UN_S:
4996                 case CEE_BGT_UN_S:
4997                 case CEE_BLE_UN_S:
4998                 case CEE_BLT_UN_S:
4999                         code_bounds_check (2);
5000                         do_branch_op (&ctx, (signed char)ip [1] + 2, cmp_br_op);
5001                         ip += 2;
5002                         need_merge = 1;
5003                         break;
5004
5005                 case CEE_BEQ:
5006                 case CEE_BNE_UN:
5007                         code_bounds_check (5);
5008                         do_branch_op (&ctx, (gint32)read32 (ip + 1) + 5, cmp_br_eq_op);
5009                         ip += 5;
5010                         need_merge = 1;
5011                         break;
5012
5013                 case CEE_BGE:
5014                 case CEE_BGT:
5015                 case CEE_BLE:
5016                 case CEE_BLT:
5017                 case CEE_BGE_UN:
5018                 case CEE_BGT_UN:
5019                 case CEE_BLE_UN:
5020                 case CEE_BLT_UN:
5021                         code_bounds_check (5);
5022                         do_branch_op (&ctx, (gint32)read32 (ip + 1) + 5, cmp_br_op);
5023                         ip += 5;
5024                         need_merge = 1;
5025                         break;
5026
5027                 case CEE_LDLOC_S:
5028                 case CEE_LDLOCA_S:
5029                         code_bounds_check (2);
5030                         push_local (&ctx, ip[1], *ip == CEE_LDLOCA_S);
5031                         ip += 2;
5032                         break;
5033
5034                 case CEE_UNUSED99:
5035                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
5036                         ++ip;
5037                         break; 
5038
5039                 case CEE_DUP: {
5040                         ILStackDesc *top;
5041                         if (!check_underflow (&ctx, 1))
5042                                 break;
5043                         if (!check_overflow (&ctx))
5044                                 break;
5045                         top = stack_push (&ctx);
5046                         copy_stack_value (top, stack_peek (&ctx, 1));
5047                         ++ip;
5048                         break;
5049                 }
5050
5051                 case CEE_JMP:
5052                         code_bounds_check (5);
5053                         if (ctx.eval.size)
5054                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Eval stack must be empty in jmp at 0x%04x", ip_offset));
5055                         token = read32 (ip + 1);
5056                         if (in_any_block (ctx.header, ip_offset))
5057                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("jmp cannot escape exception blocks at 0x%04x", ip_offset));
5058
5059                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Intruction jmp is not verifiable at 0x%04x", ctx.ip_offset));
5060                         /*
5061                          * FIXME: check signature, retval, arguments etc.
5062                          */
5063                         ip += 5;
5064                         break;
5065                 case CEE_CALL:
5066                 case CEE_CALLVIRT:
5067                         code_bounds_check (5);
5068                         do_invoke_method (&ctx, read32 (ip + 1), *ip == CEE_CALLVIRT);
5069                         ip += 5;
5070                         break;
5071
5072                 case CEE_CALLI:
5073                         code_bounds_check (5);
5074                         token = read32 (ip + 1);
5075                         /*
5076                          * FIXME: check signature, retval, arguments etc.
5077                          * FIXME: check requirements for tail call
5078                          */
5079                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Intruction calli is not verifiable at 0x%04x", ctx.ip_offset));
5080                         ip += 5;
5081                         break;
5082                 case CEE_BR_S:
5083                         code_bounds_check (2);
5084                         do_static_branch (&ctx, (signed char)ip [1] + 2);
5085                         need_merge = 1;
5086                         ip += 2;
5087                         start = 1;
5088                         break;
5089
5090                 case CEE_BRFALSE_S:
5091                 case CEE_BRTRUE_S:
5092                         code_bounds_check (2);
5093                         do_boolean_branch_op (&ctx, (signed char)ip [1] + 2);
5094                         ip += 2;
5095                         need_merge = 1;
5096                         break;
5097
5098                 case CEE_BR:
5099                         code_bounds_check (5);
5100                         do_static_branch (&ctx, (gint32)read32 (ip + 1) + 5);
5101                         need_merge = 1;
5102                         ip += 5;
5103                         start = 1;
5104                         break;
5105
5106                 case CEE_BRFALSE:
5107                 case CEE_BRTRUE:
5108                         code_bounds_check (5);
5109                         do_boolean_branch_op (&ctx, (gint32)read32 (ip + 1) + 5);
5110                         ip += 5;
5111                         need_merge = 1;
5112                         break;
5113
5114                 case CEE_SWITCH: {
5115                         guint32 entries;
5116                         code_bounds_check (5);
5117                         entries = read32 (ip + 1);
5118
5119                         if (entries > 0xFFFFFFFFU / sizeof (guint32))
5120                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Too many switch entries %x at 0x%04x", entries, ctx.ip_offset));
5121
5122                         ip += 5;
5123                         code_bounds_check (sizeof (guint32) * entries);
5124                         
5125                         do_switch (&ctx, entries, ip);
5126                         ip += sizeof (guint32) * entries;
5127                         break;
5128                 }
5129                 case CEE_LDIND_I1:
5130                 case CEE_LDIND_U1:
5131                 case CEE_LDIND_I2:
5132                 case CEE_LDIND_U2:
5133                 case CEE_LDIND_I4:
5134                 case CEE_LDIND_U4:
5135                 case CEE_LDIND_I8:
5136                 case CEE_LDIND_I:
5137                 case CEE_LDIND_R4:
5138                 case CEE_LDIND_R8:
5139                 case CEE_LDIND_REF:
5140                         do_load_indirect (&ctx, *ip);
5141                         ++ip;
5142                         break;
5143                         
5144                 case CEE_STIND_REF:
5145                 case CEE_STIND_I1:
5146                 case CEE_STIND_I2:
5147                 case CEE_STIND_I4:
5148                 case CEE_STIND_I8:
5149                 case CEE_STIND_R4:
5150                 case CEE_STIND_R8:
5151                 case CEE_STIND_I:
5152                         do_store_indirect (&ctx, *ip);
5153                         ++ip;
5154                         break;
5155
5156                 case CEE_NOT:
5157                 case CEE_NEG:
5158                         do_unary_math_op (&ctx, *ip);
5159                         ++ip;
5160                         break;
5161
5162                 case CEE_CONV_I1:
5163                 case CEE_CONV_I2:
5164                 case CEE_CONV_I4:
5165                 case CEE_CONV_U1:
5166                 case CEE_CONV_U2:
5167                 case CEE_CONV_U4:
5168                         do_conversion (&ctx, TYPE_I4);
5169                         ++ip;
5170                         break;                  
5171
5172                 case CEE_CONV_I8:
5173                 case CEE_CONV_U8:
5174                         do_conversion (&ctx, TYPE_I8);
5175                         ++ip;
5176                         break;                  
5177
5178                 case CEE_CONV_R4:
5179                 case CEE_CONV_R8:
5180                 case CEE_CONV_R_UN:
5181                         do_conversion (&ctx, TYPE_R8);
5182                         ++ip;
5183                         break;                  
5184
5185                 case CEE_CONV_I:
5186                 case CEE_CONV_U:
5187                         do_conversion (&ctx, TYPE_NATIVE_INT);
5188                         ++ip;
5189                         break;
5190
5191                 case CEE_CPOBJ:
5192                         code_bounds_check (5);
5193                         do_cpobj (&ctx, read32 (ip + 1));
5194                         ip += 5;
5195                         break;
5196
5197                 case CEE_LDOBJ:
5198                         code_bounds_check (5);
5199                         do_ldobj_value (&ctx, read32 (ip + 1));
5200                         ip += 5;
5201                         break;
5202
5203                 case CEE_LDSTR:
5204                         code_bounds_check (5);
5205                         do_ldstr (&ctx, read32 (ip + 1));
5206                         ip += 5;
5207                         break;
5208
5209                 case CEE_NEWOBJ:
5210                         code_bounds_check (5);
5211                         do_newobj (&ctx, read32 (ip + 1));
5212                         ip += 5;
5213                         break;
5214
5215                 case CEE_CASTCLASS:
5216                 case CEE_ISINST:
5217                         code_bounds_check (5);
5218                         do_cast (&ctx, read32 (ip + 1), *ip == CEE_CASTCLASS ? "castclass" : "isinst");
5219                         ip += 5;
5220                         break;
5221
5222                 case CEE_UNUSED58:
5223                 case CEE_UNUSED1:
5224                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
5225                         ++ip;
5226                         break;
5227
5228                 case CEE_UNBOX:
5229                         code_bounds_check (5);
5230                         do_unbox_value (&ctx, read32 (ip + 1));
5231                         ip += 5;
5232                         break;
5233
5234                 case CEE_THROW:
5235                         do_throw (&ctx);
5236                         start = 1;
5237                         ++ip;
5238                         break;
5239
5240                 case CEE_LDFLD:
5241                 case CEE_LDFLDA:
5242                         code_bounds_check (5);
5243                         do_push_field (&ctx, read32 (ip + 1), *ip == CEE_LDFLDA);
5244                         ip += 5;
5245                         break;
5246
5247                 case CEE_LDSFLD:
5248                 case CEE_LDSFLDA:
5249                         code_bounds_check (5);
5250                         do_push_static_field (&ctx, read32 (ip + 1), *ip == CEE_LDSFLDA);
5251                         ip += 5;
5252                         break;
5253
5254                 case CEE_STFLD:
5255                         code_bounds_check (5);
5256                         do_store_field (&ctx, read32 (ip + 1));
5257                         ip += 5;
5258                         break;
5259
5260                 case CEE_STSFLD:
5261                         code_bounds_check (5);
5262                         do_store_static_field (&ctx, read32 (ip + 1));
5263                         ip += 5;
5264                         break;
5265
5266                 case CEE_STOBJ:
5267                         code_bounds_check (5);
5268                         do_stobj (&ctx, read32 (ip + 1));
5269                         ip += 5;
5270                         break;
5271
5272                 case CEE_CONV_OVF_I1_UN:
5273                 case CEE_CONV_OVF_I2_UN:
5274                 case CEE_CONV_OVF_I4_UN:
5275                 case CEE_CONV_OVF_U1_UN:
5276                 case CEE_CONV_OVF_U2_UN:
5277                 case CEE_CONV_OVF_U4_UN:
5278                         do_conversion (&ctx, TYPE_I4);
5279                         ++ip;
5280                         break;                  
5281
5282                 case CEE_CONV_OVF_I8_UN:
5283                 case CEE_CONV_OVF_U8_UN:
5284                         do_conversion (&ctx, TYPE_I8);
5285                         ++ip;
5286                         break;                  
5287
5288                 case CEE_CONV_OVF_I_UN:
5289                 case CEE_CONV_OVF_U_UN:
5290                         do_conversion (&ctx, TYPE_NATIVE_INT);
5291                         ++ip;
5292                         break;
5293
5294                 case CEE_BOX:
5295                         code_bounds_check (5);
5296                         do_box_value (&ctx, read32 (ip + 1));
5297                         ip += 5;
5298                         break;
5299
5300                 case CEE_NEWARR:
5301                         code_bounds_check (5);
5302                         do_newarr (&ctx, read32 (ip + 1));
5303                         ip += 5;
5304                         break;
5305
5306                 case CEE_LDLEN:
5307                         do_ldlen (&ctx);
5308                         ++ip;
5309                         break;
5310
5311                 case CEE_LDELEMA:
5312                         code_bounds_check (5);
5313                         do_ldelema (&ctx, read32 (ip + 1));
5314                         ip += 5;
5315                         break;
5316
5317                 case CEE_LDELEM_I1:
5318                 case CEE_LDELEM_U1:
5319                 case CEE_LDELEM_I2:
5320                 case CEE_LDELEM_U2:
5321                 case CEE_LDELEM_I4:
5322                 case CEE_LDELEM_U4:
5323                 case CEE_LDELEM_I8:
5324                 case CEE_LDELEM_I:
5325                 case CEE_LDELEM_R4:
5326                 case CEE_LDELEM_R8:
5327                 case CEE_LDELEM_REF:
5328                         do_ldelem (&ctx, *ip, 0);
5329                         ++ip;
5330                         break;
5331
5332                 case CEE_STELEM_I:
5333                 case CEE_STELEM_I1:
5334                 case CEE_STELEM_I2:
5335                 case CEE_STELEM_I4:
5336                 case CEE_STELEM_I8:
5337                 case CEE_STELEM_R4:
5338                 case CEE_STELEM_R8:
5339                 case CEE_STELEM_REF:
5340                         do_stelem (&ctx, *ip, 0);
5341                         ++ip;
5342                         break;
5343
5344                 case CEE_LDELEM:
5345                         code_bounds_check (5);
5346                         do_ldelem (&ctx, *ip, read32 (ip + 1));
5347                         ip += 5;
5348                         break;
5349
5350                 case CEE_STELEM:
5351                         code_bounds_check (5);
5352                         do_stelem (&ctx, *ip, read32 (ip + 1));
5353                         ip += 5;
5354                         break;
5355                         
5356                 case CEE_UNBOX_ANY:
5357                         code_bounds_check (5);
5358                         do_unbox_any (&ctx, read32 (ip + 1));
5359                         ip += 5;
5360                         break;
5361
5362                 case CEE_CONV_OVF_I1:
5363                 case CEE_CONV_OVF_U1:
5364                 case CEE_CONV_OVF_I2:
5365                 case CEE_CONV_OVF_U2:
5366                 case CEE_CONV_OVF_I4:
5367                 case CEE_CONV_OVF_U4:
5368                         do_conversion (&ctx, TYPE_I4);
5369                         ++ip;
5370                         break;
5371
5372                 case CEE_CONV_OVF_I8:
5373                 case CEE_CONV_OVF_U8:
5374                         do_conversion (&ctx, TYPE_I8);
5375                         ++ip;
5376                         break;
5377
5378                 case CEE_CONV_OVF_I:
5379                 case CEE_CONV_OVF_U:
5380                         do_conversion (&ctx, TYPE_NATIVE_INT);
5381                         ++ip;
5382                         break;
5383
5384                 case CEE_REFANYVAL:
5385                         code_bounds_check (5);
5386                         do_refanyval (&ctx, read32 (ip + 1));
5387                         ip += 5;
5388                         break;
5389
5390                 case CEE_CKFINITE:
5391                         do_ckfinite (&ctx);
5392                         ++ip;
5393                         break;
5394
5395                 case CEE_MKREFANY:
5396                         code_bounds_check (5);
5397                         do_mkrefany (&ctx,  read32 (ip + 1));
5398                         ip += 5;
5399                         break;
5400
5401                 case CEE_LDTOKEN:
5402                         code_bounds_check (5);
5403                         do_load_token (&ctx, read32 (ip + 1));
5404                         ip += 5;
5405                         break;
5406
5407                 case CEE_ENDFINALLY:
5408                         if (!is_correct_endfinally (ctx.header, ip_offset))
5409                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("endfinally must be used inside a finally/fault handler at 0x%04x", ctx.ip_offset));
5410                         ctx.eval.size = 0;
5411                         start = 1;
5412                         ++ip;
5413                         break;
5414
5415                 case CEE_LEAVE:
5416                         code_bounds_check (5);
5417                         do_leave (&ctx, read32 (ip + 1) + 5);
5418                         ip += 5;
5419                         start = 1;
5420                         need_merge = 1;
5421                         break;
5422
5423                 case CEE_LEAVE_S:
5424                         code_bounds_check (2);
5425                         do_leave (&ctx, (signed char)ip [1] + 2);
5426                         ip += 2;
5427                         start = 1;
5428                         need_merge = 1;
5429                         break;
5430
5431                 case CEE_PREFIX1:
5432                         code_bounds_check (2);
5433                         ++ip;
5434                         switch (*ip) {
5435                         case CEE_STLOC:
5436                                 code_bounds_check (3);
5437                                 store_local (&ctx, read16 (ip + 1));
5438                                 ip += 3;
5439                                 break;
5440
5441                         case CEE_CEQ:
5442                                 do_cmp_op (&ctx, cmp_br_eq_op, *ip);
5443                                 ++ip;
5444                                 break;
5445
5446                         case CEE_CGT:
5447                         case CEE_CGT_UN:
5448                         case CEE_CLT:
5449                         case CEE_CLT_UN:
5450                                 do_cmp_op (&ctx, cmp_br_op, *ip);
5451                                 ++ip;
5452                                 break;
5453
5454                         case CEE_STARG:
5455                                 code_bounds_check (3);
5456                                 store_arg (&ctx, read16 (ip + 1) );
5457                                 ip += 3;
5458                                 break;
5459
5460
5461                         case CEE_ARGLIST:
5462                                 if (!check_overflow (&ctx))
5463                                         break;
5464                                 if (ctx.signature->call_convention != MONO_CALL_VARARG)
5465                                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Cannot use arglist on method without VARGARG calling convention at 0x%04x", ctx.ip_offset));
5466                                 set_stack_value (&ctx, stack_push (&ctx), &mono_defaults.argumenthandle_class->byval_arg, FALSE);
5467                                 ++ip;
5468                                 break;
5469         
5470                         case CEE_LDFTN:
5471                                 code_bounds_check (5);
5472                                 do_load_function_ptr (&ctx, read32 (ip + 1), FALSE);
5473                                 ip += 5;
5474                                 break;
5475
5476                         case CEE_LDVIRTFTN:
5477                                 code_bounds_check (5);
5478                                 do_load_function_ptr (&ctx, read32 (ip + 1), TRUE);
5479                                 ip += 5;
5480                                 break;
5481
5482                         case CEE_LDARG:
5483                         case CEE_LDARGA:
5484                                 code_bounds_check (3);
5485                                 push_arg (&ctx, read16 (ip + 1),  *ip == CEE_LDARGA);
5486                                 ip += 3;
5487                                 break;
5488
5489                         case CEE_LDLOC:
5490                         case CEE_LDLOCA:
5491                                 code_bounds_check (3);
5492                                 push_local (&ctx, read16 (ip + 1), *ip == CEE_LDLOCA);
5493                                 ip += 3;
5494                                 break;
5495
5496                         case CEE_LOCALLOC:
5497                                 do_localloc (&ctx);
5498                                 ++ip;
5499                                 break;
5500
5501                         case CEE_UNUSED56:
5502                         case CEE_UNUSED57:
5503                         case CEE_UNUSED70:
5504                         case CEE_UNUSED:
5505                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
5506                                 ++ip;
5507                                 break;
5508                         case CEE_ENDFILTER:
5509                                 do_endfilter (&ctx);
5510                                 start = 1;
5511                                 ++ip;
5512                                 break;
5513                         case CEE_UNALIGNED_:
5514                                 code_bounds_check (2);
5515                                 prefix |= PREFIX_UNALIGNED;
5516                                 ip += 2;
5517                                 break;
5518                         case CEE_VOLATILE_:
5519                                 prefix |= PREFIX_VOLATILE;
5520                                 ++ip;
5521                                 break;
5522                         case CEE_TAIL_:
5523                                 prefix |= PREFIX_TAIL;
5524                                 ++ip;
5525                                 if (ip < end && (*ip != CEE_CALL && *ip != CEE_CALLI && *ip != CEE_CALLVIRT))
5526                                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("tail prefix must be used only with call opcodes at 0x%04x", ip_offset));
5527                                 break;
5528
5529                         case CEE_INITOBJ:
5530                                 code_bounds_check (5);
5531                                 do_initobj (&ctx, read32 (ip + 1));
5532                                 ip += 5;
5533                                 break;
5534
5535                         case CEE_CONSTRAINED_:
5536                                 code_bounds_check (5);
5537                                 ctx.constrained_type = get_boxable_mono_type (&ctx, read32 (ip + 1), "constrained.");
5538                                 prefix |= PREFIX_CONSTRAINED;
5539                                 ip += 5;
5540                                 break;
5541         
5542                         case CEE_READONLY_:
5543                                 prefix |= PREFIX_READONLY;
5544                                 ip++;
5545                                 break;
5546
5547                         case CEE_CPBLK:
5548                                 CLEAR_PREFIX (&ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
5549                                 if (!check_underflow (&ctx, 3))
5550                                         break;
5551                                 CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Instruction cpblk is not verifiable at 0x%04x", ctx.ip_offset));
5552                                 ip++;
5553                                 break;
5554                                 
5555                         case CEE_INITBLK:
5556                                 CLEAR_PREFIX (&ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
5557                                 if (!check_underflow (&ctx, 3))
5558                                         break;
5559                                 CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Instruction initblk is not verifiable at 0x%04x", ctx.ip_offset));
5560                                 ip++;
5561                                 break;
5562                                 
5563                         case CEE_NO_:
5564                                 ip += 2;
5565                                 break;
5566                         case CEE_RETHROW:
5567                                 if (!is_correct_rethrow (ctx.header, ip_offset))
5568                                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("rethrow must be used inside a catch handler at 0x%04x", ctx.ip_offset));
5569                                 ctx.eval.size = 0;
5570                                 start = 1;
5571                                 ++ip;
5572                                 break;
5573
5574                         case CEE_SIZEOF:
5575                                 code_bounds_check (5);
5576                                 do_sizeof (&ctx, read32 (ip + 1));
5577                                 ip += 5;
5578                                 break;
5579
5580                         case CEE_REFANYTYPE:
5581                                 do_refanytype (&ctx);
5582                                 ++ip;
5583                                 break;
5584
5585                         default:
5586                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction FE %x at 0x%04x", *ip, ctx.ip_offset));
5587                                 ++ip;
5588                         }
5589                         break;
5590
5591                 default:
5592                         ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction %x at 0x%04x", *ip, ctx.ip_offset));
5593                         ++ip;
5594                 }
5595
5596                 /*TODO we can fast detect a forward branch or exception block targeting code after prefix, we should fail fast*/
5597                 if (prefix) {
5598                         if (!ctx.prefix_set) //first prefix
5599                                 ctx.code [ctx.ip_offset].flags |= IL_CODE_FLAG_SEEN;
5600                         ctx.prefix_set |= prefix;
5601                         ctx.has_flags = TRUE;
5602                         prefix = 0;
5603                 } else {
5604                         if (!ctx.has_flags)
5605                                 ctx.code [ctx.ip_offset].flags |= IL_CODE_FLAG_SEEN;
5606
5607                         if (ctx.prefix_set & PREFIX_CONSTRAINED)
5608                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after constrained prefix at 0x%04x", ctx.ip_offset));
5609                         if (ctx.prefix_set & PREFIX_READONLY)
5610                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after readonly prefix at 0x%04x", ctx.ip_offset));
5611                         if (ctx.prefix_set & PREFIX_VOLATILE)
5612                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after volatile prefix at 0x%04x", ctx.ip_offset));
5613                         if (ctx.prefix_set & PREFIX_UNALIGNED)
5614                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after unaligned prefix at 0x%04x", ctx.ip_offset));
5615                         ctx.prefix_set = prefix = 0;
5616                         ctx.has_flags = FALSE;
5617                 }
5618         }
5619         /*
5620          * if ip != end we overflowed: mark as error.
5621          */
5622         if ((ip != end || !start) && ctx.verifiable && !ctx.list) {
5623                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Run ahead of method code at 0x%04x", ip_offset));
5624         }
5625
5626         /*We should guard against the last decoded opcode, otherwise we might add errors that doesn't make sense.*/
5627         for (i = 0; i < ctx.code_size && i < ip_offset; ++i) {
5628                 if (ctx.code [i].flags & IL_CODE_FLAG_WAS_TARGET) {
5629                         if (!(ctx.code [i].flags & IL_CODE_FLAG_SEEN))
5630                                 ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or exception block target middle of intruction at 0x%04x", i));
5631
5632                         if (ctx.code [i].flags & IL_CODE_DELEGATE_SEQUENCE)
5633                                 CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Branch to delegate code sequence at 0x%04x", i));
5634                 }
5635                 if ((ctx.code [i].flags & IL_CODE_LDFTN_DELEGATE_NONFINAL_VIRTUAL) && ctx.has_this_store)
5636                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Invalid ldftn with virtual function in method with stdarg 0 at  0x%04x", i));
5637
5638                 if ((ctx.code [i].flags & IL_CODE_CALL_NONFINAL_VIRTUAL) && ctx.has_this_store)
5639                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Invalid call to a non-final virtual function in method with stdarg.0 or ldarga.0 at  0x%04x", i));
5640         }
5641
5642         if (mono_method_is_constructor (ctx.method) && !ctx.super_ctor_called && !ctx.method->klass->valuetype && ctx.method->klass != mono_defaults.object_class) {
5643                 char *method_name = mono_method_full_name (ctx.method, TRUE);
5644                 char *type = mono_type_get_full_name (ctx.method->klass);
5645                 if (ctx.method->klass->parent && ctx.method->klass->parent->exception_type != MONO_EXCEPTION_NONE)
5646                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Constructor %s for type %s not calling base type ctor due to a TypeLoadException on base type.", method_name, type));
5647                 else
5648                         CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Constructor %s for type %s not calling base type ctor.", method_name, type));
5649                 g_free (method_name);
5650                 g_free (type);
5651         }
5652
5653 cleanup:
5654         if (ctx.code) {
5655                 for (i = 0; i < ctx.header->code_size; ++i) {
5656                         if (ctx.code [i].stack)
5657                                 g_free (ctx.code [i].stack);
5658                 }
5659         }
5660
5661         for (tmp = ctx.funptrs; tmp; tmp = tmp->next)
5662                 g_free (tmp->data);
5663         g_slist_free (ctx.funptrs);
5664
5665         for (tmp = ctx.exception_types; tmp; tmp = tmp->next)
5666                 mono_metadata_free_type (tmp->data);
5667         g_slist_free (ctx.exception_types);
5668
5669         for (i = 0; i < ctx.num_locals; ++i) {
5670                 if (ctx.locals [i])
5671                         mono_metadata_free_type (ctx.locals [i]);
5672         }
5673         for (i = 0; i < ctx.max_args; ++i) {
5674                 if (ctx.params [i])
5675                         mono_metadata_free_type (ctx.params [i]);
5676         }
5677
5678         if (ctx.eval.stack)
5679                 g_free (ctx.eval.stack);
5680         if (ctx.code)
5681                 g_free (ctx.code);
5682         g_free (ctx.locals);
5683         g_free (ctx.params);
5684         mono_basic_block_free (original_bb);
5685         mono_metadata_free_mh (ctx.header);
5686
5687         finish_collect_stats ();
5688         return ctx.list;
5689 }
5690
5691 char*
5692 mono_verify_corlib ()
5693 {
5694         /* This is a public API function so cannot be removed */
5695         return NULL;
5696 }
5697
5698 /*
5699  * Returns true if @method needs to be verified.
5700  * 
5701  */
5702 gboolean
5703 mono_verifier_is_enabled_for_method (MonoMethod *method)
5704 {
5705         return mono_verifier_is_enabled_for_class (method->klass) && method->wrapper_type == MONO_WRAPPER_NONE;
5706 }
5707
5708 /*
5709  * Returns true if @klass need to be verified.
5710  * 
5711  */
5712 gboolean
5713 mono_verifier_is_enabled_for_class (MonoClass *klass)
5714 {
5715         return verify_all || (verifier_mode > MONO_VERIFIER_MODE_OFF && !(klass->image->assembly && klass->image->assembly->in_gac) && klass->image != mono_defaults.corlib);
5716 }
5717
5718 gboolean
5719 mono_verifier_is_enabled_for_image (MonoImage *image)
5720 {
5721         return verify_all || verifier_mode > MONO_VERIFIER_MODE_OFF;
5722 }
5723
5724 gboolean
5725 mono_verifier_is_method_full_trust (MonoMethod *method)
5726 {
5727         return mono_verifier_is_class_full_trust (method->klass);
5728 }
5729
5730 /*
5731  * Returns if @klass is under full trust or not.
5732  * 
5733  * TODO This code doesn't take CAS into account.
5734  * 
5735  * Under verify_all all user code must be verifiable if no security option was set 
5736  * 
5737  */
5738 gboolean
5739 mono_verifier_is_class_full_trust (MonoClass *klass)
5740 {
5741         /* under CoreCLR code is trusted if it is part of the "platform" otherwise all code inside the GAC is trusted */
5742         gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ? 
5743                 (klass->image->assembly && klass->image->assembly->in_gac) : mono_security_core_clr_is_platform_image (klass->image);
5744
5745         if (verify_all && verifier_mode == MONO_VERIFIER_MODE_OFF)
5746                 return trusted_location || klass->image == mono_defaults.corlib;
5747         return verifier_mode < MONO_VERIFIER_MODE_VERIFIABLE || trusted_location || klass->image == mono_defaults.corlib;
5748 }
5749
5750 GSList*
5751 mono_method_verify_with_current_settings (MonoMethod *method, gboolean skip_visibility)
5752 {
5753         return mono_method_verify (method, 
5754                         (verifier_mode != MONO_VERIFIER_MODE_STRICT ? MONO_VERIFY_NON_STRICT: 0)
5755                         | (!mono_verifier_is_method_full_trust (method) ? MONO_VERIFY_FAIL_FAST : 0)
5756                         | (skip_visibility ? MONO_VERIFY_SKIP_VISIBILITY : 0));
5757 }
5758
5759 static int
5760 get_field_end (MonoClassField *field)
5761 {
5762         int align;
5763         int size = mono_type_size (field->type, &align);
5764         if (size == 0)
5765                 size = 4; /*FIXME Is this a safe bet?*/
5766         return size + field->offset;
5767 }
5768
5769 static gboolean
5770 verify_class_for_overlapping_reference_fields (MonoClass *class)
5771 {
5772         int i = 0, j;
5773         gpointer iter = NULL;
5774         MonoClassField *field;
5775         gboolean is_fulltrust = mono_verifier_is_class_full_trust (class);
5776         /*We can't skip types with !has_references since this is calculated after we have run.*/
5777         if (!((class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT))
5778                 return TRUE;
5779
5780
5781         /*We must check for stuff overlapping reference fields.
5782           The outer loop uses mono_class_get_fields to ensure that MonoClass:fields get inited.
5783         */
5784         while ((field = mono_class_get_fields (class, &iter))) {
5785                 int fieldEnd = get_field_end (field);
5786                 gboolean is_valuetype = !MONO_TYPE_IS_REFERENCE (field->type);
5787                 ++i;
5788
5789                 if (mono_field_is_deleted (field) || (field->type->attrs & FIELD_ATTRIBUTE_STATIC))
5790                         continue;
5791
5792                 for (j = i; j < class->field.count; ++j) {
5793                         MonoClassField *other = &class->fields [j];
5794                         int otherEnd = get_field_end (other);
5795                         if (mono_field_is_deleted (other) || (is_valuetype && !MONO_TYPE_IS_REFERENCE (other->type)) || (other->type->attrs & FIELD_ATTRIBUTE_STATIC))
5796                                 continue;
5797
5798                         if (!is_valuetype && MONO_TYPE_IS_REFERENCE (other->type) && field->offset == other->offset && is_fulltrust)
5799                                 continue;
5800
5801                         if ((otherEnd > field->offset && otherEnd <= fieldEnd) || (other->offset >= field->offset && other->offset < fieldEnd))
5802                                 return FALSE;
5803                 }
5804         }
5805         return TRUE;
5806 }
5807
5808 static guint
5809 field_hash (gconstpointer key)
5810 {
5811         const MonoClassField *field = key;
5812         return g_str_hash (field->name) ^ mono_metadata_type_hash (field->type); /**/
5813 }
5814
5815 static gboolean
5816 field_equals (gconstpointer _a, gconstpointer _b)
5817 {
5818         const MonoClassField *a = _a;
5819         const MonoClassField *b = _b;
5820         return !strcmp (a->name, b->name) && mono_metadata_type_equal (a->type, b->type);
5821 }
5822
5823
5824 static gboolean
5825 verify_class_fields (MonoClass *class)
5826 {
5827         gpointer iter = NULL;
5828         MonoClassField *field;
5829         MonoGenericContext *context = mono_class_get_context (class);
5830         GHashTable *unique_fields = g_hash_table_new_full (&field_hash, &field_equals, NULL, NULL);
5831         if (class->generic_container)
5832                 context = &class->generic_container->context;
5833
5834         while ((field = mono_class_get_fields (class, &iter)) != NULL) {
5835                 if (!mono_type_is_valid_type_in_context (field->type, context)) {
5836                         g_hash_table_destroy (unique_fields);
5837                         return FALSE;
5838                 }
5839                 if (g_hash_table_lookup (unique_fields, field)) {
5840                         g_hash_table_destroy (unique_fields);
5841                         return FALSE;
5842                 }
5843                 g_hash_table_insert (unique_fields, field, field);
5844         }
5845         g_hash_table_destroy (unique_fields);
5846         return TRUE;
5847 }
5848
5849 static gboolean
5850 verify_interfaces (MonoClass *class)
5851 {
5852         int i;
5853         for (i = 0; i < class->interface_count; ++i) {
5854                 MonoClass *iface = class->interfaces [i];
5855                 if (!(iface->flags & TYPE_ATTRIBUTE_INTERFACE))
5856                         return FALSE;
5857         }
5858         return TRUE;
5859 }
5860
5861 static gboolean
5862 verify_valuetype_layout_with_target (MonoClass *class, MonoClass *target_class)
5863 {
5864         int type;
5865         gpointer iter = NULL;
5866         MonoClassField *field;
5867         MonoClass *field_class;
5868
5869         if (!class->valuetype)
5870                 return TRUE;
5871
5872         type = class->byval_arg.type;
5873         /*primitive type fields are not properly decoded*/
5874         if ((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_R8) || (type >= MONO_TYPE_I && type <= MONO_TYPE_U))
5875                 return TRUE;
5876
5877         while ((field = mono_class_get_fields (class, &iter)) != NULL) {
5878                 if (!field->type)
5879                         return FALSE;
5880
5881                 if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
5882                         continue;
5883
5884                 field_class = mono_class_get_generic_type_definition (mono_class_from_mono_type (field->type));
5885
5886                 if (field_class == target_class || class == field_class || !verify_valuetype_layout_with_target (field_class, target_class))
5887                         return FALSE;
5888         }
5889
5890         return TRUE;
5891 }
5892
5893 static gboolean
5894 verify_valuetype_layout (MonoClass *class)
5895 {
5896         gboolean res;
5897         res = verify_valuetype_layout_with_target (class, class);
5898         return res;
5899 }
5900
5901 static gboolean
5902 recursive_mark_constraint_args (MonoBitSet *used_args, MonoGenericContainer *gc, MonoType *type)
5903 {
5904         int idx;
5905         MonoClass **constraints;
5906         MonoGenericParamInfo *param_info;
5907
5908         g_assert (mono_type_is_generic_argument (type));
5909
5910         idx = mono_type_get_generic_param_num (type);
5911         if (mono_bitset_test_fast (used_args, idx))
5912                 return FALSE;
5913
5914         mono_bitset_set_fast (used_args, idx);
5915         param_info = mono_generic_container_get_param_info (gc, idx);
5916
5917         if (!param_info->constraints)
5918                 return TRUE;
5919
5920         for (constraints = param_info->constraints; *constraints; ++constraints) {
5921                 MonoClass *ctr = *constraints;
5922                 MonoType *constraint_type = &ctr->byval_arg;
5923
5924                 if (mono_type_is_generic_argument (constraint_type) && !recursive_mark_constraint_args (used_args, gc, constraint_type))
5925                         return FALSE;
5926         }
5927         return TRUE;
5928 }
5929
5930 static gboolean
5931 verify_generic_parameters (MonoClass *class)
5932 {
5933         int i;
5934         MonoGenericContainer *gc = class->generic_container;
5935         MonoBitSet *used_args = mono_bitset_new (gc->type_argc, 0);
5936
5937         for (i = 0; i < gc->type_argc; ++i) {
5938                 MonoGenericParamInfo *param_info = mono_generic_container_get_param_info (gc, i);
5939                 MonoClass **constraints;
5940
5941                 if (!param_info->constraints)
5942                         continue;
5943
5944                 mono_bitset_clear_all (used_args);
5945                 mono_bitset_set_fast (used_args, i);
5946
5947                 for (constraints = param_info->constraints; *constraints; ++constraints) {
5948                         MonoClass *ctr = *constraints;
5949                         MonoType *constraint_type = &ctr->byval_arg;
5950
5951                         if (!mono_type_is_valid_type_in_context (constraint_type, &gc->context))
5952                                 goto fail;
5953
5954                         if (mono_type_is_generic_argument (constraint_type) && !recursive_mark_constraint_args (used_args, gc, constraint_type))
5955                                 goto fail;
5956                         if (ctr->generic_class && !mono_class_is_valid_generic_instantiation (NULL, ctr))
5957                                 goto fail;
5958                 }
5959         }
5960         mono_bitset_free (used_args);
5961         return TRUE;
5962
5963 fail:
5964         mono_bitset_free (used_args);
5965         return FALSE;
5966 }
5967
5968 /*
5969  * Check if the class is verifiable.
5970  * 
5971  * Right now there are no conditions that make a class a valid but not verifiable. Both overlapping reference
5972  * field and invalid generic instantiation are fatal errors.
5973  * 
5974  * This method must be safe to be called from mono_class_init and all code must be carefull about that.
5975  * 
5976  */
5977 gboolean
5978 mono_verifier_verify_class (MonoClass *class)
5979 {
5980         /*Neither <Module>, object or ifaces have parent.*/
5981         if (!class->parent &&
5982                 class != mono_defaults.object_class && 
5983                 !MONO_CLASS_IS_INTERFACE (class) &&
5984                 (!class->image->dynamic && class->type_token != 0x2000001)) /*<Module> is the first type in the assembly*/
5985                 return FALSE;
5986         if (class->parent) {
5987                 if (MONO_CLASS_IS_INTERFACE (class->parent))
5988                         return FALSE;
5989                 if (!class->generic_class && class->parent->generic_container)
5990                         return FALSE;
5991         }
5992         if (class->generic_container && (class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
5993                 return FALSE;
5994         if (class->generic_container && !verify_generic_parameters (class))
5995                 return FALSE;
5996         if (!verify_class_for_overlapping_reference_fields (class))
5997                 return FALSE;
5998         if (class->generic_class && !mono_class_is_valid_generic_instantiation (NULL, class))
5999                 return FALSE;
6000         if (class->generic_class == NULL && !verify_class_fields (class))
6001                 return FALSE;
6002         if (class->valuetype && !verify_valuetype_layout (class))
6003                 return FALSE;
6004         if (!verify_interfaces (class))
6005                 return FALSE;
6006         return TRUE;
6007 }
6008 #else
6009
6010 gboolean
6011 mono_verifier_verify_class (MonoClass *class)
6012 {
6013         /* The verifier was disabled at compile time */
6014         return TRUE;
6015 }
6016
6017 GSList*
6018 mono_method_verify_with_current_settings (MonoMethod *method, gboolean skip_visibility)
6019 {
6020         /* The verifier was disabled at compile time */
6021         return NULL;
6022 }
6023
6024 gboolean
6025 mono_verifier_is_class_full_trust (MonoClass *klass)
6026 {
6027         /* The verifier was disabled at compile time */
6028         return TRUE;
6029 }
6030
6031 gboolean
6032 mono_verifier_is_method_full_trust (MonoMethod *method)
6033 {
6034         /* The verifier was disabled at compile time */
6035         return TRUE;
6036 }
6037
6038 gboolean
6039 mono_verifier_is_enabled_for_image (MonoImage *image)
6040 {
6041         /* The verifier was disabled at compile time */
6042         return FALSE;
6043 }
6044
6045 gboolean
6046 mono_verifier_is_enabled_for_class (MonoClass *klass)
6047 {
6048         /* The verifier was disabled at compile time */
6049         return FALSE;
6050 }
6051
6052 gboolean
6053 mono_verifier_is_enabled_for_method (MonoMethod *method)
6054 {
6055         /* The verifier was disabled at compile time */
6056         return FALSE;
6057 }
6058
6059 GSList*
6060 mono_method_verify (MonoMethod *method, int level)
6061 {
6062         /* The verifier was disabled at compile time */
6063         return NULL;
6064 }
6065
6066 void
6067 mono_free_verify_list (GSList *list)
6068 {
6069         /* The verifier was disabled at compile time */
6070         /* will always be null if verifier is disabled */
6071 }
6072
6073 #endif