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