753e5269e921bdb9dec91aa0fdac4faf9f4f817b
[mono.git] / mono / metadata / metadata-verify.c
1 /*
2  * metadata-verify.c: Metadata verfication support
3  *
4  * Author:
5  *      Mono Project (http://www.mono-project.com)
6  *
7  * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
8  */
9 #include <mono/metadata/object-internals.h>
10 #include <mono/metadata/verify.h>
11 #include <mono/metadata/verify-internals.h>
12 #include <mono/metadata/opcodes.h>
13 #include <mono/metadata/tabledefs.h>
14 #include <mono/metadata/reflection.h>
15 #include <mono/metadata/debug-helpers.h>
16 #include <mono/metadata/mono-endian.h>
17 #include <mono/metadata/metadata.h>
18 #include <mono/metadata/metadata-internals.h>
19 #include <mono/metadata/class-internals.h>
20 #include <mono/metadata/tokentype.h>
21 #include <mono/metadata/security-manager.h>
22 #include <mono/metadata/security-core-clr.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/attrdefs.h>
25 #include <mono/utils/strenc.h>
26 #include <mono/utils/mono-error-internals.h>
27 #include <mono/utils/bsearch.h>
28 #include <string.h>
29 //#include <signal.h>
30 #include <ctype.h>
31
32 #ifndef DISABLE_VERIFIER
33 /*
34  TODO add fail fast mode
35  TODO add PE32+ support
36  TODO verify the entry point RVA and content.
37  TODO load_section_table and load_data_directories must take PE32+ into account
38  TODO add section relocation support
39  TODO verify the relocation table, since we really don't use, no need so far.
40  TODO do full PECOFF resources verification 
41  TODO verify in the CLI header entry point and resources
42  TODO implement null token typeref validation  
43  TODO verify table wide invariants for typedef (sorting and uniqueness)
44  TODO implement proper authenticode data directory validation
45  TODO verify properties that require multiple tables to be valid 
46  FIXME use subtraction based bounds checking to avoid overflows
47  FIXME get rid of metadata_streams and other fields from VerifyContext
48 */
49
50 #ifdef MONO_VERIFIER_DEBUG
51 #define VERIFIER_DEBUG(code) do { code; } while (0)
52 #else
53 #define VERIFIER_DEBUG(code)
54 #endif
55
56 #define INVALID_OFFSET ((guint32)-1)
57 #define INVALID_ADDRESS 0xffffffff
58
59 enum {
60         STAGE_PE,
61         STAGE_CLI,
62         STAGE_TABLES
63 };
64
65 enum {
66         IMPORT_TABLE_IDX = 1, 
67         RESOURCE_TABLE_IDX = 2,
68         CERTIFICATE_TABLE_IDX = 4,
69         RELOCATION_TABLE_IDX = 5,
70         IAT_IDX = 12,
71         CLI_HEADER_IDX = 14,
72 };
73
74 enum {
75         STRINGS_STREAM,
76         USER_STRINGS_STREAM,
77         BLOB_STREAM,
78         GUID_STREAM,
79         TILDE_STREAM
80 };
81
82
83 #define INVALID_TABLE (0xFF)
84 /*format: number of bits, number of tables, tables{n. tables} */
85 const static unsigned char coded_index_desc[] = {
86 #define TYPEDEF_OR_REF_DESC (0)
87         2, /*bits*/
88         3, /*tables*/
89         MONO_TABLE_TYPEDEF,
90         MONO_TABLE_TYPEREF,
91         MONO_TABLE_TYPESPEC,
92
93 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
94         2, /*bits*/
95         3, /*tables*/
96         MONO_TABLE_FIELD,
97         MONO_TABLE_PARAM,
98         MONO_TABLE_PROPERTY,
99
100 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
101         5, /*bits*/
102         20, /*tables*/
103         MONO_TABLE_METHOD,
104         MONO_TABLE_FIELD,
105         MONO_TABLE_TYPEREF,
106         MONO_TABLE_TYPEDEF,
107         MONO_TABLE_PARAM,
108         MONO_TABLE_INTERFACEIMPL,
109         MONO_TABLE_MEMBERREF,
110         MONO_TABLE_MODULE,
111         MONO_TABLE_DECLSECURITY,
112         MONO_TABLE_PROPERTY, 
113         MONO_TABLE_EVENT,
114         MONO_TABLE_STANDALONESIG,
115         MONO_TABLE_MODULEREF,
116         MONO_TABLE_TYPESPEC,
117         MONO_TABLE_ASSEMBLY,
118         MONO_TABLE_ASSEMBLYREF,
119         MONO_TABLE_FILE,
120         MONO_TABLE_EXPORTEDTYPE,
121         MONO_TABLE_MANIFESTRESOURCE,
122         MONO_TABLE_GENERICPARAM,
123
124 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
125         1, /*bits*/
126         2, /*tables*/
127         MONO_TABLE_FIELD,
128         MONO_TABLE_PARAM,
129
130 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
131         2, /*bits*/
132         3, /*tables*/
133         MONO_TABLE_TYPEDEF,
134         MONO_TABLE_METHOD,
135         MONO_TABLE_ASSEMBLY,
136
137 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
138         3, /*bits*/
139         5, /*tables*/
140         MONO_TABLE_TYPEDEF,
141         MONO_TABLE_TYPEREF,
142         MONO_TABLE_MODULEREF,
143         MONO_TABLE_METHOD,
144         MONO_TABLE_TYPESPEC,
145
146 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
147         1, /*bits*/
148         2, /*tables*/
149         MONO_TABLE_EVENT,
150         MONO_TABLE_PROPERTY,
151
152 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
153         1, /*bits*/
154         2, /*tables*/
155         MONO_TABLE_METHOD,
156         MONO_TABLE_MEMBERREF,
157
158 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
159         1, /*bits*/
160         2, /*tables*/
161         MONO_TABLE_FIELD,
162         MONO_TABLE_METHOD,
163
164 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
165         2, /*bits*/
166         3, /*tables*/
167         MONO_TABLE_FILE,
168         MONO_TABLE_ASSEMBLYREF,
169         MONO_TABLE_EXPORTEDTYPE,
170
171 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
172         3, /*bits*/
173         5, /*tables*/
174         INVALID_TABLE,
175         INVALID_TABLE,
176         MONO_TABLE_METHOD,
177         MONO_TABLE_MEMBERREF,
178         INVALID_TABLE,
179
180 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
181         2, /*bits*/
182         4, /*tables*/
183         MONO_TABLE_MODULE,
184         MONO_TABLE_MODULEREF,
185         MONO_TABLE_ASSEMBLYREF,
186         MONO_TABLE_TYPEREF,
187
188 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
189         1, /*bits*/
190         2, /*tables*/
191         MONO_TABLE_TYPEDEF,
192         MONO_TABLE_METHOD
193 };
194
195 typedef struct {
196         guint32 rva;
197         guint32 size;
198         guint32 translated_offset;
199 } DataDirectory;
200
201 typedef struct {
202         guint32 offset;
203         guint32 size;
204 } OffsetAndSize;
205
206 typedef struct {
207         guint32 baseRVA;
208         guint32 baseOffset;
209         guint32 size;
210         guint32 rellocationsRVA;
211         guint16 numberOfRelocations;
212 } SectionHeader;
213
214 typedef struct {
215         guint32 row_count;
216         guint32 row_size;
217         guint32 offset;
218 } TableInfo;
219
220 typedef struct {
221         const char *data;
222         guint32 size, token;
223         GSList *errors;
224         int valid;
225         MonoImage *image;
226         gboolean report_error;
227         gboolean report_warning;
228         int stage;
229
230         DataDirectory data_directories [16];
231         guint32 section_count;
232         SectionHeader *sections;
233
234         OffsetAndSize metadata_streams [5]; //offset from begin of the image
235 } VerifyContext;
236
237 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception)    \
238         do {    \
239                 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1);      \
240                 vinfo->info.status = __status;  \
241                 vinfo->info.message = ( __msg); \
242                 vinfo->exception_type = (__exception);  \
243                 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo);     \
244         } while (0)
245
246 #define ADD_WARNING(__ctx, __msg)       \
247         do {    \
248                 if ((__ctx)->report_warning) { \
249                         ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
250                         (__ctx)->valid = 0; \
251                         return; \
252                 } \
253         } while (0)
254
255 #define ADD_ERROR_NO_RETURN(__ctx, __msg)       \
256         do {    \
257                 if ((__ctx)->report_error) \
258                         ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
259                 (__ctx)->valid = 0; \
260         } while (0)
261
262 #define ADD_ERROR(__ctx, __msg) \
263         do {    \
264                 if ((__ctx)->report_error) \
265                         ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
266                 (__ctx)->valid = 0; \
267                 return; \
268         } while (0)
269
270 #define FAIL(__ctx, __msg)      \
271         do {    \
272                 if ((__ctx)->report_error) \
273                         ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
274                 (__ctx)->valid = 0; \
275                 return FALSE; \
276         } while (0)
277
278 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
279
280 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
281
282 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
283 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
284
285 #if SIZEOF_VOID_P == 4
286 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
287 #else
288 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
289 #endif
290
291 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
292 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
293
294 static const char *
295 dword_align (const char *ptr)
296 {
297 #if SIZEOF_VOID_P == 8
298         return (const char *) (((guint64) (ptr + 3)) & ~3);
299 #else
300         return (const char *) (((guint32) (ptr + 3)) & ~3);
301 #endif
302 }
303
304 static void
305 add_from_mono_error (VerifyContext *ctx, MonoError *error)
306 {
307         if (mono_error_ok (error))
308                 return;
309
310         ADD_ERROR (ctx, g_strdup (mono_error_get_message (error)));
311         mono_error_cleanup (error);
312 }
313
314 static guint32
315 pe_signature_offset (VerifyContext *ctx)
316 {
317         return read32 (ctx->data + 0x3c);
318 }
319
320 static guint32
321 pe_header_offset (VerifyContext *ctx)
322 {
323         return read32 (ctx->data + 0x3c) + 4;
324 }
325
326 static gboolean
327 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
328 {
329         int i;
330
331         if (rva + size < rva) //overflow
332                 return FALSE;
333
334         if (ctx->stage > STAGE_PE) {
335                 MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
336                 const int top = iinfo->cli_section_count;
337                 MonoSectionTable *tables = iinfo->cli_section_tables;
338                 int i;
339                 
340                 for (i = 0; i < top; i++) {
341                         guint32 base = tables->st_virtual_address;
342                         guint32 end = base + tables->st_raw_data_size;
343
344                         if (rva >= base && rva + size <= end)
345                                 return TRUE;
346
347                         /*if ((addr >= tables->st_virtual_address) &&
348                             (addr < tables->st_virtual_address + tables->st_raw_data_size)){
349
350                                 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
351                         }*/
352                         tables++;
353                 }
354                 return FALSE;
355         }
356
357         if (!ctx->sections)
358                 return FALSE;
359
360         for (i = 0; i < ctx->section_count; ++i) {
361                 guint32 base = ctx->sections [i].baseRVA;
362                 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
363                 if (rva >= base && rva + size <= end)
364                         return TRUE;
365         }
366         return FALSE;
367 }
368
369 static gboolean
370 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
371 {
372         if (dir->translated_offset > offset)
373                 return FALSE;
374         if (dir->size < size)
375                 return FALSE;
376         return offset + size <= dir->translated_offset + dir->size;
377 }
378
379 static gboolean
380 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
381 {
382         if (off->offset > offset)
383                 return FALSE;
384         
385         if (off->size < size)
386                 return FALSE;
387
388         return offset + size <= off->offset + off->size;
389 }
390
391 static guint32
392 translate_rva (VerifyContext *ctx, guint32 rva)
393 {
394         int i;
395
396         if (ctx->stage > STAGE_PE)
397                 return mono_cli_rva_image_map (ctx->image, rva);
398                 
399         if (!ctx->sections)
400                 return FALSE;
401
402         for (i = 0; i < ctx->section_count; ++i) {
403                 guint32 base = ctx->sections [i].baseRVA;
404                 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
405                 if (rva >= base && rva <= end) {
406                         guint32 res = (rva - base) + ctx->sections [i].baseOffset;
407                         /* double check */
408                         return res >= ctx->size ? INVALID_OFFSET : res;
409                 }
410         }
411
412         return INVALID_OFFSET;
413 }
414
415 static void
416 verify_msdos_header (VerifyContext *ctx)
417 {
418         guint32 lfanew;
419         if (ctx->size < 128)
420                 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
421         if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
422                 ADD_ERROR (ctx,  g_strdup ("Invalid MS-DOS watermark"));
423         lfanew = pe_signature_offset (ctx);
424         if (lfanew > ctx->size - 4)
425                 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
426 }
427
428 static void
429 verify_pe_header (VerifyContext *ctx)
430 {
431         guint32 offset = pe_signature_offset (ctx);
432         const char *pe_header = ctx->data + offset;
433         if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
434                 ADD_ERROR (ctx,  g_strdup ("Invalid PE header watermark"));
435         pe_header += 4;
436         offset += 4;
437
438         if (offset > ctx->size - 20)
439                 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
440         if (read16 (pe_header) != 0x14c)
441                 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
442 }
443
444 static void
445 verify_pe_optional_header (VerifyContext *ctx)
446 {
447         guint32 offset = pe_header_offset (ctx);
448         guint32 header_size, file_alignment;
449         const char *pe_header = ctx->data + offset;
450         const char *pe_optional_header = pe_header + 20;
451
452         header_size = read16 (pe_header + 16);
453         offset += 20;
454
455         if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
456                 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
457
458         if (offset > ctx->size - header_size || header_size > ctx->size)
459                 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
460
461         if (read16 (pe_optional_header) == 0x10b) {
462                 if (header_size != 224)
463                         ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
464
465                 /* LAMESPEC MS plays around this value and ignore it during validation
466                 if (read32 (pe_optional_header + 28) != 0x400000)
467                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
468                 if (read32 (pe_optional_header + 32) != 0x2000)
469                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
470                 file_alignment = read32 (pe_optional_header + 36);
471                 if (file_alignment != 0x200 && file_alignment != 0x1000)
472                         ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
473                 /* All the junk in the middle is irrelevant, specially for mono. */
474                 if (read32 (pe_optional_header + 92) > 0x10)
475                         ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
476         } else {
477                 if (read16 (pe_optional_header) == 0x20B)
478                         ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
479                 else
480                         ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
481         }
482 }
483
484 static void
485 load_section_table (VerifyContext *ctx)
486 {
487         int i;
488         SectionHeader *sections;
489         guint32 offset =  pe_header_offset (ctx);
490         const char *ptr = ctx->data + offset;
491         guint16 num_sections = ctx->section_count = read16 (ptr + 2);
492
493         offset += 244;/*FIXME, this constant is different under PE32+*/
494         ptr += 244;
495
496         if (num_sections * 40 > ctx->size - offset)
497                 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
498
499         sections = ctx->sections = g_new0 (SectionHeader, num_sections);
500         for (i = 0; i < num_sections; ++i) {
501                 sections [i].size = read32 (ptr + 8);
502                 sections [i].baseRVA = read32 (ptr + 12);
503                 sections [i].baseOffset = read32 (ptr + 20);
504                 sections [i].rellocationsRVA = read32 (ptr + 24);
505                 sections [i].numberOfRelocations = read16 (ptr + 32);
506                 ptr += 40;
507         }
508
509         ptr = ctx->data + offset; /*reset it to the beggining*/
510         for (i = 0; i < num_sections; ++i) {
511                 guint32 raw_size, flags;
512                 if (sections [i].baseOffset == 0)
513                         ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
514                 if (sections [i].baseOffset >= ctx->size)
515                         ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
516                 if (sections [i].size > ctx->size - sections [i].baseOffset)
517                         ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
518
519                 raw_size = read32 (ptr + 16);
520                 if (raw_size < sections [i].size)
521                         ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
522
523                 if (raw_size > ctx->size - sections [i].baseOffset)
524                         ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
525
526                 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
527                         ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
528
529                 flags = read32 (ptr + 36);
530                 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
531                 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
532                         ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
533
534                 ptr += 40;
535         }
536 }
537
538 static gboolean
539 is_valid_data_directory (int i)
540 {
541         /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
542         return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6; 
543 }
544
545 static void
546 load_data_directories (VerifyContext *ctx)
547 {
548         guint32 offset =  pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
549         const char *ptr = ctx->data + offset;
550         int i;
551
552         for (i = 0; i < 16; ++i) {
553                 guint32 rva = read32 (ptr);
554                 guint32 size = read32 (ptr + 4);
555
556                 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
557                 if (i == CERTIFICATE_TABLE_IDX) {
558                         ptr += 8;
559                         continue;
560                 }
561                 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
562                         ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
563
564                 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
565                         ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
566
567                 ctx->data_directories [i].rva = rva;
568                 ctx->data_directories [i].size = size;
569                 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
570
571                 ptr += 8;
572         }
573 }
574
575 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
576
577 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
578
579 static void
580 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
581 {
582         const char *ptr;
583         guint32 hint_table_rva;
584
585         import_rva = translate_rva (ctx, import_rva);
586         g_assert (import_rva != INVALID_OFFSET);
587
588         hint_table_rva = read32 (ctx->data + import_rva);
589         if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
590                 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
591
592         hint_table_rva = translate_rva (ctx, hint_table_rva);
593         g_assert (hint_table_rva != INVALID_OFFSET);
594         ptr = ctx->data + hint_table_rva + 2;
595
596         if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
597                 char name[SIZE_OF_CORMAIN];
598                 memcpy (name, ptr, SIZE_OF_CORMAIN);
599                 name [SIZE_OF_CORMAIN - 1] = 0;
600                 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
601         }
602 }
603
604 static void
605 verify_import_table (VerifyContext *ctx)
606 {
607         DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
608         guint32 offset = it.translated_offset;
609         const char *ptr = ctx->data + offset;
610         guint32 name_rva, ilt_rva, iat_rva;
611
612         g_assert (offset != INVALID_OFFSET);
613
614         if (it.size < 40)
615                 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
616
617         ilt_rva = read32 (ptr);
618         if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
619                 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
620
621         name_rva = read32 (ptr + 12);
622         if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
623                 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
624
625         iat_rva = read32 (ptr + 16);
626         if (iat_rva) {
627                 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
628                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
629
630                 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
631                         ADD_ERROR (ctx, g_strdup_printf ("Import Address Table rva %x different from data directory entry %x", read32 (ptr + 16), ctx->data_directories [IAT_IDX].rva));
632         }
633
634         if (name_rva) {
635                 name_rva = translate_rva (ctx, name_rva);
636                 g_assert (name_rva != INVALID_OFFSET);
637                 ptr = ctx->data + name_rva;
638         
639                 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
640                         char name[SIZE_OF_MSCOREE];
641                         memcpy (name, ptr, SIZE_OF_MSCOREE);
642                         name [SIZE_OF_MSCOREE - 1] = 0;
643                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
644                 }
645         }
646         
647         if (ilt_rva) {
648                 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
649                 CHECK_ERROR ();
650         }
651
652         if (iat_rva)
653                 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
654 }
655
656 static void
657 verify_resources_table (VerifyContext *ctx)
658 {
659         DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
660         guint32 offset;
661         guint16 named_entries, id_entries;
662         const char *ptr;
663
664         if (it.rva == 0)
665                 return;
666
667         if (it.size < 16)
668                 ADD_ERROR (ctx, g_strdup_printf ("Resource section is too small, must be at least 16 bytes long but it's %d long", it.size));
669
670         offset = it.translated_offset;
671         ptr = ctx->data + offset;
672
673         g_assert (offset != INVALID_OFFSET);
674
675         named_entries = read16 (ptr + 12);
676         id_entries = read16 (ptr + 14);
677
678         if ((named_entries + id_entries) * 8 + 16 > it.size)
679                 ADD_ERROR (ctx, g_strdup_printf ("Resource section is too small, the number of entries (%d) doesn't fit on it's size %d", named_entries + id_entries, it.size));
680
681         /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource () 
682         if (named_entries || id_entries)
683                 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
684         */
685 }
686
687 /*----------nothing from here on can use data_directory---*/
688
689 static DataDirectory
690 get_data_dir (VerifyContext *ctx, int idx)
691 {
692         MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
693         MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
694         DataDirectory res;
695
696         entry += idx;
697         res.rva = entry->rva;
698         res.size = entry->size;
699         res.translated_offset = translate_rva (ctx, res.rva);
700         return res;
701
702 }
703 static void
704 verify_cli_header (VerifyContext *ctx)
705 {
706         DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
707         guint32 offset;
708         const char *ptr;
709         int i;
710
711         if (it.rva == 0)
712                 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
713
714         if (it.size != 72)
715                 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
716
717         offset = it.translated_offset;
718         ptr = ctx->data + offset;
719
720         g_assert (offset != INVALID_OFFSET);
721
722         if (read16 (ptr) != 72)
723                 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
724
725         if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
726                 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
727
728
729         if (!read32 (ptr + 8) || !read32 (ptr + 12))
730                 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
731
732         if ((read32 (ptr + 16) & ~0x0001000B) != 0)
733                 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
734
735         ptr += 24;
736         for (i = 0; i < 6; ++i) {
737                 guint32 rva = read32 (ptr);
738                 guint32 size = read32 (ptr + 4);
739
740                 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
741                         ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
742
743                 ptr += 8;
744
745                 if (rva && i > 1)
746                         ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
747         }
748 }
749
750 static guint32
751 pad4 (guint32 offset)
752 {
753         if (offset & 0x3) //pad to the next 4 byte boundary
754                 offset = (offset & ~0x3) + 4;
755         return offset;
756 }
757
758 static void
759 verify_metadata_header (VerifyContext *ctx)
760 {
761         int i;
762         DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
763         guint32 offset, section_count;
764         const char *ptr;
765
766         offset = it.translated_offset;
767         ptr = ctx->data + offset;
768         g_assert (offset != INVALID_OFFSET);
769
770         //build a directory entry for the metadata root
771         ptr += 8;
772         it.rva = read32 (ptr);
773         ptr += 4;
774         it.size = read32 (ptr);
775         it.translated_offset = offset = translate_rva (ctx, it.rva);
776
777         ptr = ctx->data + offset;
778         g_assert (offset != INVALID_OFFSET);
779
780         if (it.size < 20)
781                 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
782
783         if (read32 (ptr) != 0x424A5342)
784                 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
785
786         offset = pad4 (offset + 16 + read32 (ptr + 12));
787
788         if (!bounds_check_datadir (&it, offset, 4))
789                 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least %d bytes required for flags decoding)", it.size, offset + 4 - it.translated_offset));
790
791         ptr = ctx->data + offset; //move to streams header 
792
793         section_count = read16 (ptr + 2);
794         if (section_count < 2)
795                 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
796
797         ptr += 4;
798         offset += 4;
799
800         for (i = 0; i < section_count; ++i) {
801                 guint32 stream_off, stream_size;
802                 int string_size, stream_idx;
803
804                 if (!bounds_check_datadir (&it, offset, 8))
805                         ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small for initial decode of stream header %d, missing %d bytes", i, offset + 9 - it.translated_offset));
806
807                 stream_off = it.translated_offset + read32 (ptr);
808                 stream_size = read32 (ptr + 4);
809
810                 if (!bounds_check_datadir (&it,  stream_off, stream_size))
811                         ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
812
813                 ptr += 8;
814                 offset += 8;
815
816                 for (string_size = 0; string_size < 32; ++string_size) {
817                         if (!bounds_check_datadir (&it, offset++, 1))
818                                 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
819                         if (!ptr [string_size])
820                                 break;
821                 }
822
823                 if (ptr [string_size])
824                         ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
825
826                 if (!strncmp ("#Strings", ptr, 9))
827                         stream_idx = STRINGS_STREAM;
828                 else if (!strncmp ("#US", ptr, 4))
829                         stream_idx = USER_STRINGS_STREAM;
830                 else if (!strncmp ("#Blob", ptr, 6))
831                         stream_idx = BLOB_STREAM;
832                 else if (!strncmp ("#GUID", ptr, 6))
833                         stream_idx = GUID_STREAM;
834                 else if (!strncmp ("#~", ptr, 3))
835                         stream_idx = TILDE_STREAM;
836                 else {
837                         ADD_WARNING (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
838                         offset = pad4 (offset);
839                         ptr = ctx->data + offset;
840                         continue;
841                 }
842
843                 if (ctx->metadata_streams [stream_idx].offset != 0)
844                         ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
845
846                 ctx->metadata_streams [stream_idx].offset = stream_off;
847                 ctx->metadata_streams [stream_idx].size = stream_size;
848
849                 offset = pad4 (offset);
850                 ptr = ctx->data + offset;
851         }
852
853         if (!ctx->metadata_streams [TILDE_STREAM].size)
854                 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
855         if (!ctx->metadata_streams [GUID_STREAM].size)
856                 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
857 }
858
859 static void
860 verify_tables_schema (VerifyContext *ctx)
861 {
862         OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
863         unsigned offset = tables_area.offset;
864         const char *ptr = ctx->data + offset;
865         guint64 valid_tables;
866         guint32 count;
867         int i;
868
869         if (tables_area.size < 24)
870                 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
871
872         if (ptr [4] != 2 && ptr [4] != 1)
873                 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
874         if (ptr [5] != 0)
875                 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
876
877         if ((ptr [6] & ~0x7) != 0)
878                 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata heap sizes 0x%02x, only bits 0, 1 and 2 can be set", ((unsigned char *) ptr) [6]));
879
880         valid_tables = read64 (ptr + 8);
881         count = 0;
882         for (i = 0; i < 64; ++i) {
883                 if (!(valid_tables & ((guint64)1 << i)))
884                         continue;
885
886                 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
887                   Unused: 0x1E 0x1F 0x2D-0x3F
888                   We don't care about the MS extensions.*/
889                 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
890                         ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i));
891                 if (i == 0x1E || i == 0x1F || i >= 0x2D)
892                         ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
893                 ++count;
894         }
895
896         if (tables_area.size < 24 + count * 4)
897                 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for decoding row counts (requires %d bytes)", tables_area.size, 24 + count * 4));
898         ptr += 24;
899
900         for (i = 0; i < 64; ++i) {
901                 if (valid_tables & ((guint64)1 << i)) {
902                         guint32 row_count = read32 (ptr);
903                         if (row_count > (1 << 24) - 1)
904                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
905                         ptr += 4;
906                 }
907         }
908 }
909
910 /*----------nothing from here on can use data_directory or metadata_streams ---*/
911
912 static guint32
913 get_col_offset (VerifyContext *ctx, int table, int column)
914 {
915         guint32 bitfield = ctx->image->tables [table].size_bitfield;
916         guint32 offset = 0;
917
918         while (column-- > 0)
919                 offset += mono_metadata_table_size (bitfield, column);
920
921         return offset;
922 }
923
924 static guint32
925 get_col_size (VerifyContext *ctx, int table, int column)
926 {
927         return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
928 }
929
930 static OffsetAndSize
931 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
932 {
933         OffsetAndSize res;
934         res.offset = header->data - ctx->data;
935         res.size = header->size;
936
937         return res;
938 }
939
940 static gboolean
941 is_valid_string_full_with_image (MonoImage *image, guint32 offset, gboolean allow_empty)
942 {
943         guint32 heap_offset = (char*)image->heap_strings.data - image->raw_data;
944         guint32 heap_size = image->heap_strings.size;
945
946         glong length;
947         const char *data = image->raw_data + heap_offset;
948
949         if (offset >= heap_size)
950                 return FALSE;
951         if (CHECK_ADDP_OVERFLOW_UN (data, offset))
952                 return FALSE;
953
954         if (!mono_utf8_validate_and_len_with_bounds (data + offset, heap_size - offset, &length, NULL))
955                 return FALSE;
956         return allow_empty || length > 0;
957 }
958
959
960 static gboolean
961 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
962 {
963         return is_valid_string_full_with_image (ctx->image, offset, allow_empty);
964 }
965
966 static gboolean
967 is_valid_string (VerifyContext *ctx, guint32 offset)
968 {
969         return is_valid_string_full (ctx, offset, TRUE);
970 }
971
972 static gboolean
973 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
974 {
975         return is_valid_string_full (ctx, offset, FALSE);
976 }
977
978 static gboolean
979 is_valid_guid (VerifyContext *ctx, guint32 offset)
980 {
981         OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
982         return guids.size >= 8 && guids.size - 8 >= offset;
983 }
984
985 static guint32
986 get_coded_index_token (int token_kind, guint32 coded_token)
987 {
988         guint32 bits = coded_index_desc [token_kind];
989         return coded_token >> bits;
990 }
991
992 static guint32
993 get_coded_index_table (int kind, guint32 coded_token)
994 {
995         guint32 idx, bits = coded_index_desc [kind];
996         kind += 2;
997         idx = coded_token & ((1 << bits) - 1);
998         return coded_index_desc [kind + idx];
999 }
1000
1001 static guint32
1002 make_coded_token (int kind, guint32 table, guint32 table_idx)
1003 {
1004         guint32 bits = coded_index_desc [kind++];
1005         guint32 tables = coded_index_desc [kind++];
1006         guint32 i;
1007         for (i = 0; i < tables; ++i) {
1008                 if (coded_index_desc [kind++] == table)
1009                         return ((table_idx + 1) << bits) | i; 
1010         }
1011         g_assert_not_reached ();
1012         return -1;
1013 }
1014
1015 static gboolean
1016 is_valid_coded_index_with_image (MonoImage *image, int token_kind, guint32 coded_token)
1017 {
1018         guint32 bits = coded_index_desc [token_kind++];
1019         guint32 table_count = coded_index_desc [token_kind++];
1020         guint32 table = coded_token & ((1 << bits) - 1);
1021         guint32 token = coded_token >> bits;
1022
1023         if (table >= table_count)
1024                 return FALSE;
1025
1026         /*token_kind points to the first table idx*/
1027         table = coded_index_desc [token_kind + table];
1028
1029         if (table == INVALID_TABLE)
1030                 return FALSE;
1031         return token <= image->tables [table].rows;
1032 }
1033
1034 static gboolean
1035 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
1036 {
1037         return is_valid_coded_index_with_image (ctx->image, token_kind, coded_token);
1038 }
1039
1040 typedef struct {
1041         guint32 token;
1042         guint32 col_size;
1043         guint32 col_offset;
1044         MonoTableInfo *table;
1045 } RowLocator;
1046
1047 static int
1048 token_locator (const void *a, const void *b)
1049 {
1050         RowLocator *loc = (RowLocator *)a;
1051         unsigned const char *row = (unsigned const char *)b;
1052         guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1053
1054         VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1055         return (int)loc->token - (int)token;
1056 }
1057
1058 static int
1059 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1060 {
1061         MonoTableInfo *tinfo = &ctx->image->tables [table];
1062         RowLocator locator;
1063         const char *res, *base;
1064         locator.token = coded_token;
1065         locator.col_offset = get_col_offset (ctx, table, column);
1066         locator.col_size = get_col_size (ctx, table, column);
1067         locator.table = tinfo;
1068
1069         base = tinfo->base;
1070
1071         VERIFIER_DEBUG ( printf ("looking token %x table %d col %d rsize %d roff %d\n", coded_token, table, column, locator.col_size, locator.col_offset) );
1072         res = (const char *)mono_binary_search (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1073         if (!res)
1074                 return -1;
1075
1076         return (res - base) / tinfo->row_size;
1077 }
1078
1079 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1080 static const char*
1081 get_string_ptr (VerifyContext *ctx, guint offset)
1082 {
1083         return ctx->image->heap_strings.data + offset;
1084 }
1085
1086 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1087 static int
1088 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1089 {
1090         if (offset == 0)
1091                 return strcmp (str, "");
1092
1093         return strcmp (str, get_string_ptr (ctx, offset));
1094 }
1095
1096 static gboolean
1097 mono_verifier_is_corlib (MonoImage *image)
1098 {
1099         gboolean trusted_location = !mono_security_core_clr_enabled () ?
1100                         TRUE : mono_security_core_clr_is_platform_image (image);
1101
1102         return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1103 }
1104
1105 static gboolean
1106 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1107 {
1108         return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1109 }
1110
1111 static gboolean
1112 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1113 {
1114         unsigned char b;
1115         const unsigned char *ptr = (const unsigned char *)_ptr;
1116
1117         if (!available)
1118                 return FALSE;
1119
1120         b = *ptr;
1121         *value = *size = 0;
1122         
1123         if ((b & 0x80) == 0) {
1124                 *size = 1;
1125                 *value = b;
1126         } else if ((b & 0x40) == 0) {
1127                 if (available < 2)
1128                         return FALSE;
1129                 *size = 2;
1130                 *value = ((b & 0x3f) << 8 | ptr [1]);
1131         } else {
1132                 if (available < 4)
1133                         return FALSE;
1134                 *size = 4;
1135                 *value  = ((b & 0x1f) << 24) |
1136                         (ptr [1] << 16) |
1137                         (ptr [2] << 8) |
1138                         ptr [3];
1139         }
1140
1141         return TRUE;
1142 }
1143
1144 static gboolean
1145 decode_signature_header (VerifyContext *ctx, guint32 offset, guint32 *size, const char **first_byte)
1146 {
1147         MonoStreamHeader blob = ctx->image->heap_blob;
1148         guint32 value, enc_size;
1149
1150         if (offset >= blob.size)
1151                 return FALSE;
1152
1153         if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1154                 return FALSE;
1155
1156         if (CHECK_ADD4_OVERFLOW_UN (offset, enc_size))
1157                 return FALSE;
1158
1159         offset += enc_size;
1160
1161         if (ADD_IS_GREATER_OR_OVF (offset, value, blob.size))
1162                 return FALSE;
1163
1164         *size = value;
1165         *first_byte = blob.data + offset;
1166         return TRUE;
1167 }
1168
1169 static gboolean
1170 safe_read (const char **_ptr, const char *limit, unsigned *dest, int size)
1171 {
1172         const char *ptr = *_ptr;
1173         if (ptr + size > limit)
1174                 return FALSE;
1175         switch (size) {
1176         case 1:
1177                 *dest = *((guint8*)ptr);
1178                 ++ptr;
1179                 break;
1180         case 2:
1181                 *dest = read16 (ptr);
1182                 ptr += 2;
1183                 break;
1184         case 4:
1185                 *dest = read32 (ptr);
1186                 ptr += 4;
1187                 break;
1188         }
1189         *_ptr = ptr;
1190         return TRUE;
1191 }
1192
1193 static gboolean
1194 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1195 {
1196         unsigned size = 0;
1197         const char *ptr = *_ptr;
1198         gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1199         *_ptr = ptr + size;
1200         return res;
1201 }
1202
1203 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1204 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1205 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1206 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1207
1208 static gboolean
1209 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1210
1211 static gboolean
1212 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1213
1214 static gboolean
1215 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1216 {
1217         const char *ptr = *_ptr;
1218         unsigned type = 0;
1219         unsigned token = 0;
1220
1221         while (TRUE) {
1222                 if (!safe_read8 (type, ptr, end))
1223                         FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1224         
1225                 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1226                         --ptr;
1227                         break;
1228                 }
1229         
1230                 if (!safe_read_cint (token, ptr, end))
1231                         FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1232         
1233                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1234                         FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1235         }
1236
1237         *_ptr = ptr;
1238         return TRUE;
1239 }
1240
1241 static gboolean
1242 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1243 {
1244         const char *ptr = *_ptr;
1245         unsigned val = 0;
1246         unsigned size, num, i;
1247
1248         if (!safe_read8 (val, ptr, end))
1249                 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1250
1251         if (val == 0)
1252                 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1253
1254         if (!safe_read_cint (size, ptr, end))
1255                 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1256
1257         for (i = 0; i < size; ++i) {
1258                 if (!safe_read_cint (num, ptr, end))
1259                         FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1260         }
1261
1262         if (!safe_read_cint (size, ptr, end))
1263                 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1264
1265         for (i = 0; i < size; ++i) {
1266                 if (!safe_read_cint (num, ptr, end))
1267                         FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1268         }
1269
1270         *_ptr = ptr;
1271         return TRUE;
1272 }
1273
1274 static gboolean
1275 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1276 {
1277         const char *ptr = *_ptr;
1278         unsigned type;
1279         unsigned count, token, i;
1280
1281         if (!safe_read8 (type, ptr, end))
1282                 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1283
1284         if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1285                 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1286
1287         if (!safe_read_cint (token, ptr, end))
1288                 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1289
1290         if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1291                 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1292
1293         if (ctx->token) {
1294                 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1295                         mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1296                         FAIL (ctx, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx->token));
1297         }
1298
1299         if (!safe_read_cint (count, ptr, end))
1300                 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1301
1302         if (count == 0)
1303                 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1304
1305         for (i = 0; i < count; ++i) {
1306                 if (!parse_custom_mods (ctx, &ptr, end))
1307                         FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1308
1309                 if (!parse_type (ctx, &ptr, end))
1310                         FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1311         }
1312         *_ptr = ptr;
1313         return TRUE;
1314 }
1315
1316 static gboolean
1317 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1318 {
1319         const char *ptr = *_ptr;
1320         unsigned type;
1321         unsigned token = 0;
1322
1323         if (!safe_read8 (type, ptr, end))
1324                 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1325
1326         if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1327                 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1328                 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1329                 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1330                 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1331
1332         switch (type) {
1333         case MONO_TYPE_PTR:
1334                 if (!parse_custom_mods (ctx, &ptr, end))
1335                         FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1336
1337                 if (!safe_read8 (type, ptr, end))
1338                         FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1339
1340                 if (type != MONO_TYPE_VOID) {
1341                         --ptr;
1342                         if (!parse_type (ctx, &ptr, end))
1343                                 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1344                 }
1345                 break;
1346
1347         case MONO_TYPE_VALUETYPE:
1348         case MONO_TYPE_CLASS:
1349                 if (!safe_read_cint (token, ptr, end))
1350                         FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1351         
1352                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1353                         FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1354
1355                 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1356                         FAIL (ctx, g_strdup_printf ("Type: zero TypeDefOrRef token %x", token));
1357                 if (ctx->token) {
1358                         if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1359                                 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1360                                 FAIL (ctx, g_strdup_printf ("Type: Recursive type specification (%x). A type signature can't reference itself", ctx->token));
1361                 }
1362                 break;
1363
1364         case MONO_TYPE_VAR:
1365         case MONO_TYPE_MVAR:
1366                 if (!safe_read_cint (token, ptr, end))
1367                         FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1368                 break;
1369
1370         case MONO_TYPE_ARRAY:
1371                 if (!parse_type (ctx, &ptr, end))
1372                         FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1373                 if (!parse_array_shape (ctx, &ptr, end))
1374                         FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1375                 break;
1376
1377         case MONO_TYPE_GENERICINST:
1378                 if (!parse_generic_inst (ctx, &ptr, end))
1379                         FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1380                 break;
1381
1382         case MONO_TYPE_FNPTR:
1383                 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1384                         FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1385                 break;
1386
1387         case MONO_TYPE_SZARRAY:
1388                 if (!parse_custom_mods (ctx, &ptr, end))
1389                         FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1390                 if (!parse_type (ctx, &ptr, end))
1391                         FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1392                 break;
1393         }
1394         *_ptr = ptr;
1395         return TRUE;
1396 }
1397
1398 static gboolean
1399 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1400 {
1401         const char *ptr;
1402         unsigned type = 0;
1403
1404         if (!parse_custom_mods (ctx, _ptr, end))
1405                 return FALSE;
1406
1407         ptr = *_ptr;
1408         if (!safe_read8 (type, ptr, end))
1409                 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1410
1411         if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1412                 *_ptr = ptr;
1413                 return TRUE;
1414         }
1415
1416         //it's a byref, update the cursor ptr
1417         if (type == MONO_TYPE_BYREF)
1418                 *_ptr = ptr;
1419
1420         return parse_type (ctx, _ptr, end);
1421 }
1422
1423 static gboolean
1424 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1425 {
1426         const char *ptr;
1427         unsigned type = 0;
1428
1429         if (!parse_custom_mods (ctx, _ptr, end))
1430                 return FALSE;
1431
1432         ptr = *_ptr;
1433         if (!safe_read8 (type, ptr, end))
1434                 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1435
1436         if (type == MONO_TYPE_TYPEDBYREF) {
1437                 *_ptr = ptr;
1438                 return TRUE;
1439         }
1440
1441         //it's a byref, update the cursor ptr
1442         if (type == MONO_TYPE_BYREF) {
1443                 *_ptr = ptr;
1444                 if (!parse_custom_mods (ctx, _ptr, end))
1445                         return FALSE;
1446         }
1447
1448         return parse_type (ctx, _ptr, end);
1449 }
1450
1451 static gboolean
1452 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1453 {
1454         unsigned cconv = 0;
1455         unsigned param_count = 0, gparam_count = 0, type = 0, i;
1456         const char *ptr = *_ptr;
1457         gboolean saw_sentinel = FALSE;
1458
1459         if (!safe_read8 (cconv, ptr, end))
1460                 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1461
1462         if (cconv & 0x80)
1463                 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1464
1465         if (allow_unmanaged) {
1466                 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1467                         FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1468         } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1469                 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1470
1471         if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1472                 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1473
1474         if ((cconv & 0x10) && gparam_count == 0)
1475                 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1476
1477         if (allow_unmanaged && (cconv & 0x10))
1478                 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1479
1480         if (!safe_read_cint (param_count, ptr, end))
1481                 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1482
1483         if (!parse_return_type (ctx, &ptr, end))
1484                 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1485
1486         for (i = 0; i < param_count; ++i) {
1487                 if (allow_sentinel) {
1488                         if (!safe_read8 (type, ptr, end))
1489                                 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1490
1491                         if (type == MONO_TYPE_SENTINEL) {
1492                                 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1493                                         FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1494
1495                                 if (saw_sentinel)
1496                                         FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1497
1498                                 saw_sentinel = TRUE;
1499                         } else {
1500                                 --ptr;
1501                         }
1502                 }
1503
1504                 if (!parse_param (ctx, &ptr, end))
1505                         FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1506         }
1507
1508         *_ptr = ptr;
1509         return TRUE;
1510 }
1511
1512 static gboolean
1513 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1514 {
1515         unsigned sig = 0;
1516         unsigned param_count = 0, i;
1517         const char *ptr = *_ptr;
1518
1519         if (!safe_read8 (sig, ptr, end))
1520                 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1521
1522         if (sig != 0x08 && sig != 0x28)
1523                 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1524
1525         if (!safe_read_cint (param_count, ptr, end))
1526                 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1527
1528         if (!parse_custom_mods (ctx, &ptr, end))
1529                 return FALSE;
1530
1531         if (!parse_type (ctx, &ptr, end))
1532                 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1533
1534         for (i = 0; i < param_count; ++i) {
1535                 if (!parse_custom_mods (ctx, &ptr, end))
1536                         FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1537                 if (!parse_type (ctx, &ptr, end))
1538                         FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1539         }
1540
1541         *_ptr = ptr;
1542         return TRUE;
1543 }
1544
1545 static gboolean
1546 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1547 {
1548         const char *ptr = *_ptr;
1549         unsigned signature = 0;
1550
1551         if (!safe_read8 (signature, ptr, end))
1552                 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1553
1554         if (signature != 0x06)
1555                 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1556
1557         if (!parse_custom_mods (ctx, &ptr, end))
1558                 return FALSE;
1559
1560         if (safe_read8 (signature, ptr, end)) {
1561                 if (signature != MONO_TYPE_BYREF)
1562                         --ptr;
1563         }
1564         *_ptr = ptr;
1565
1566         return parse_type (ctx, _ptr, end);
1567 }
1568
1569 static gboolean
1570 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1571 {
1572         unsigned sig = 0;
1573         unsigned locals_count = 0, i;
1574         const char *ptr = *_ptr;        
1575
1576         if (!safe_read8 (sig, ptr, end))
1577                 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1578
1579         if (sig != 0x07)
1580                 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1581
1582         if (!safe_read_cint (locals_count, ptr, end))
1583                 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1584
1585         /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1586         if (locals_count == 0)
1587                 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1588         */
1589
1590         for (i = 0; i < locals_count; ++i) {
1591                 if (!safe_read8 (sig, ptr, end))
1592                         FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1593
1594                 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1595                         if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1596                                 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1597                         if (!safe_read8 (sig, ptr, end))
1598                                 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1599                 }
1600
1601                 if (sig == MONO_TYPE_BYREF) {
1602                         if (!safe_read8 (sig, ptr, end))
1603                                 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1604                         if (sig == MONO_TYPE_TYPEDBYREF)
1605                                 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1606                 }
1607
1608                 if (sig == MONO_TYPE_TYPEDBYREF)
1609                         continue;
1610
1611                 --ptr;
1612
1613                 if (!parse_type (ctx, &ptr, end))
1614                         FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1615         }
1616
1617         *_ptr = ptr;
1618         return TRUE;
1619 }
1620
1621 static gboolean
1622 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1623 {
1624         guint32 size = 0;
1625         unsigned signature = 0;
1626         const char *ptr = NULL, *end;
1627
1628         if (!decode_signature_header (ctx, offset, &size, &ptr))
1629                 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1630         end = ptr + size;
1631
1632         if (!safe_read8 (signature, ptr, end))
1633                 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1634
1635         if (signature != 6)
1636                 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1637         --ptr;
1638
1639         return parse_field (ctx, &ptr, end);
1640 }
1641
1642 static gboolean
1643 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1644 {
1645         guint32 size = 0;
1646         const char *ptr = NULL, *end;
1647
1648         if (!decode_signature_header (ctx, offset, &size, &ptr))
1649                 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1650         end = ptr + size;
1651
1652         return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1653 }
1654
1655 static gboolean
1656 is_valid_memberref_method_signature (VerifyContext *ctx, guint32 offset)
1657 {
1658         guint32 size = 0;
1659         const char *ptr = NULL, *end;
1660
1661         if (!decode_signature_header (ctx, offset, &size, &ptr))
1662                 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1663         end = ptr + size;
1664
1665         return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1666 }
1667
1668
1669 static gboolean
1670 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1671 {
1672         guint32 size = 0;
1673         unsigned signature = 0;
1674         const char *ptr = NULL, *end;
1675
1676         if (!decode_signature_header (ctx, offset, &size, &ptr))
1677                 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1678         end = ptr + size;
1679
1680         if (!safe_read8 (signature, ptr, end))
1681                 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1682         --ptr;
1683
1684         if (signature == 0x06)
1685                 return parse_field (ctx, &ptr, end);
1686
1687         return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1688 }
1689
1690 static gboolean
1691 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1692 {
1693         guint32 size = 0;
1694         unsigned prolog = 0;
1695         const char *ptr = NULL, *end;
1696
1697         if (!offset)
1698                 return TRUE;
1699
1700         if (!decode_signature_header (ctx, offset, &size, &ptr))
1701                 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1702         end = ptr + size;
1703
1704         if (!safe_read16 (prolog, ptr, end))
1705                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1706
1707         if (prolog != 1)
1708                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1709
1710         return TRUE;
1711 }
1712
1713 static gboolean
1714 is_valid_cattr_type (MonoType *type)
1715 {
1716         MonoClass *klass;
1717
1718         if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1719                 return TRUE;
1720
1721         if (type->type == MONO_TYPE_VALUETYPE) {
1722                 klass = mono_class_from_mono_type (type);
1723                 return klass && klass->enumtype;
1724         }
1725
1726         if (type->type == MONO_TYPE_CLASS)
1727                 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1728
1729         return FALSE;
1730 }
1731
1732 static gboolean
1733 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1734 {
1735         guint32 size = 0;
1736         const char *ptr = *_ptr;
1737
1738         *str_start = NULL;
1739         *str_len = 0;
1740
1741         if (ptr >= end)
1742                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1743
1744         /*NULL string*/
1745         if (*ptr == (char)0xFF) {
1746                 *_ptr = ptr + 1;
1747                 return TRUE;
1748         }
1749
1750         if (!safe_read_cint (size, ptr, end))
1751                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1752
1753         if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1754                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1755
1756         *str_start = ptr;
1757         *str_len = size;
1758
1759         *_ptr = ptr + size;
1760         return TRUE;
1761 }
1762
1763 static gboolean
1764 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1765 {
1766         const char *dummy_str;
1767         guint32 dummy_int;
1768         return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1769 }
1770
1771 static MonoClass*
1772 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1773 {
1774         MonoType *type;
1775         MonoClass *klass;
1776         const char *str_start = NULL;
1777         const char *ptr = *_ptr;
1778         char *enum_name;
1779         guint32 str_len = 0;
1780
1781         if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1782                 return NULL;
1783
1784         /*NULL or empty string*/
1785         if (str_start == NULL || str_len == 0) {
1786                 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1787                 return NULL;
1788         }
1789
1790         enum_name = (char *)g_memdup (str_start, str_len + 1);
1791         enum_name [str_len] = 0;
1792         type = mono_reflection_type_from_name (enum_name, ctx->image);
1793         if (!type) {
1794                 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1795                 g_free (enum_name);
1796                 return NULL;
1797         }
1798         g_free (enum_name);
1799
1800         klass = mono_class_from_mono_type (type);
1801         if (!klass || !klass->enumtype) {
1802                 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1803                 return NULL;
1804         }
1805
1806         *_ptr = ptr;
1807         return klass;
1808 }
1809
1810 static gboolean
1811 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1812 {
1813         MonoClass *klass;
1814         const char *ptr = *_ptr;
1815         int elem_size = 0;
1816         guint32 element_count, i;
1817         int type;
1818
1819         klass = mono_type->data.klass;
1820         type = mono_type->type;
1821
1822 handle_enum:
1823         switch (type) {
1824         case MONO_TYPE_BOOLEAN:
1825         case MONO_TYPE_I1:
1826         case MONO_TYPE_U1:
1827                 elem_size = 1;
1828                 break;
1829         case MONO_TYPE_I2:
1830         case MONO_TYPE_U2:
1831         case MONO_TYPE_CHAR:
1832                 elem_size = 2;
1833                 break;
1834         case MONO_TYPE_I4:
1835         case MONO_TYPE_U4:
1836         case MONO_TYPE_R4:
1837                 elem_size = 4;
1838                 break;
1839         case MONO_TYPE_I8:
1840         case MONO_TYPE_U8:
1841         case MONO_TYPE_R8:
1842                 elem_size = 8;
1843                 break;
1844
1845         case MONO_TYPE_STRING:
1846                 *_ptr = ptr;
1847                 return is_valid_ser_string (ctx, _ptr, end);
1848
1849         case MONO_TYPE_OBJECT: {
1850                 unsigned sub_type = 0;
1851                 if (!safe_read8 (sub_type, ptr, end))
1852                         FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1853
1854                 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1855                         type = sub_type;
1856                         goto handle_enum;
1857                 }
1858                 if (sub_type == MONO_TYPE_ENUM) {
1859                         klass = get_enum_by_encoded_name (ctx, &ptr, end);
1860                         if (!klass)
1861                                 return FALSE;
1862
1863                         klass = klass->element_class;
1864                         type = klass->byval_arg.type;
1865                         goto handle_enum;
1866                 }
1867                 if (sub_type == 0x50) { /*Type*/
1868                         *_ptr = ptr;
1869                         return is_valid_ser_string (ctx, _ptr, end);
1870                 }
1871                 if (sub_type == MONO_TYPE_SZARRAY) {
1872                         MonoType simple_type = {{0}};
1873                         unsigned etype = 0;
1874                         if (!safe_read8 (etype, ptr, end))
1875                                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1876
1877                         if (etype == MONO_TYPE_ENUM) {
1878                                 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1879                                 if (!klass)
1880                                         return FALSE;
1881                         } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
1882                                 klass = mono_defaults.systemtype_class;
1883                         } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1884                                 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : (MonoTypeEnum)etype;
1885                                 klass = mono_class_from_mono_type (&simple_type);
1886                         } else
1887                                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1888
1889                         type = MONO_TYPE_SZARRAY;
1890                         goto handle_enum;
1891                 }
1892                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1893         }
1894
1895
1896         case MONO_TYPE_CLASS:
1897                 if (klass != mono_defaults.systemtype_class)
1898                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1899                 *_ptr = ptr;
1900                 return is_valid_ser_string (ctx, _ptr, end);
1901
1902         case MONO_TYPE_VALUETYPE:
1903                 if (!klass || !klass->enumtype)
1904                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1905
1906                 klass = klass->element_class;
1907                 type = klass->byval_arg.type;
1908                 goto handle_enum;
1909
1910         case MONO_TYPE_SZARRAY:
1911                 mono_type = &klass->byval_arg;
1912                 if (!is_valid_cattr_type (mono_type))
1913                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1914                 if (!safe_read32 (element_count, ptr, end))
1915                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1916                 if (element_count == 0xFFFFFFFFu) {
1917                         *_ptr = ptr;
1918                         return TRUE;
1919                 }
1920                 for (i = 0; i < element_count; ++i) {
1921                         if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1922                                 return FALSE;
1923                 }
1924                 *_ptr = ptr;
1925                 return TRUE;
1926         default:
1927                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1928         }
1929
1930         if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1931                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1932         *_ptr = ptr + elem_size;
1933         return TRUE;
1934 }
1935
1936 static gboolean
1937 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1938 {
1939         MonoError error;
1940         unsigned prolog = 0;
1941         const char *end;
1942         MonoMethodSignature *sig;
1943         int args, i;
1944         unsigned num_named;
1945
1946         if (!ctor)
1947                 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1948
1949         sig = mono_method_signature_checked (ctor, &error);
1950         if (!mono_error_ok (&error)) {
1951                 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1952                 mono_error_cleanup (&error);
1953                 return FALSE;
1954         }
1955
1956         if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1957                 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1958
1959         end = ptr + size;
1960
1961         if (!safe_read16 (prolog, ptr, end))
1962                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1963
1964         if (prolog != 1)
1965                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1966
1967         args = sig->param_count;
1968         for (i = 0; i < args; ++i) {
1969                 MonoType *arg_type = sig->params [i];
1970                 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1971                         return FALSE;
1972         }
1973
1974         if (!safe_read16 (num_named, ptr, end))
1975                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1976
1977         for (i = 0; i < num_named; ++i) {
1978                 MonoType *type, simple_type = {{0}};
1979                 unsigned kind;
1980
1981                 if (!safe_read8 (kind, ptr, end))
1982                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1983                 if (kind != 0x53 && kind != 0x54)
1984                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1985                 if (!safe_read8 (kind, ptr, end))
1986                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1987
1988                 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1989                         simple_type.type = (MonoTypeEnum)kind;
1990                         type = &simple_type;
1991                 } else if (kind == MONO_TYPE_ENUM) {
1992                         MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1993                         if (!klass)
1994                                 return FALSE;
1995                         type = &klass->byval_arg;
1996                 } else if (kind == 0x50) {
1997                         type = &mono_defaults.systemtype_class->byval_arg;
1998                 } else if (kind == 0x51) {
1999                         type = &mono_defaults.object_class->byval_arg;
2000                 } else if (kind == MONO_TYPE_SZARRAY) {
2001                         MonoClass *klass;
2002                         unsigned etype = 0;
2003                         if (!safe_read8 (etype, ptr, end))
2004                                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
2005
2006                         if (etype == MONO_TYPE_ENUM) {
2007                                 klass = get_enum_by_encoded_name (ctx, &ptr, end);
2008                                 if (!klass)
2009                                         return FALSE;
2010                         } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
2011                                 klass = mono_defaults.systemtype_class;
2012                         } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
2013                                 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : (MonoTypeEnum)etype;
2014                                 klass = mono_class_from_mono_type (&simple_type);
2015                         } else
2016                                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
2017
2018                         type = &mono_array_class_get (klass, 1)->byval_arg;
2019                 } else {
2020                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
2021                 }
2022
2023                 if (!is_valid_ser_string (ctx, &ptr, end))
2024                         return FALSE;
2025
2026                 if (!is_valid_fixed_param (ctx, type, &ptr, end))
2027                         return FALSE;
2028
2029         }
2030
2031         return TRUE;
2032 }
2033
2034 static gboolean
2035 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
2036 {
2037         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2038         //TODO do proper verification
2039         return blob.size >= 1 && blob.size - 1 >= offset;
2040 }
2041
2042 static gboolean
2043 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
2044 {
2045         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2046         //TODO do proper verification
2047         return blob.size >= 1 && blob.size - 1 >= offset;
2048 }
2049
2050 static gboolean
2051 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2052 {
2053         guint32 size = 0;
2054         unsigned signature = 0;
2055         const char *ptr = NULL, *end;
2056
2057         if (!decode_signature_header (ctx, offset, &size, &ptr))
2058                 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2059         end = ptr + size;
2060
2061         if (!safe_read8 (signature, ptr, end))
2062                 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2063
2064         --ptr;
2065         if (signature == 0x07)
2066                 return parse_locals_signature (ctx, &ptr, end);
2067
2068         /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2069         if (signature == 0x06)
2070                 return parse_field (ctx, &ptr, end);
2071
2072         return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2073 }
2074
2075 static gboolean
2076 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2077 {
2078         guint32 size = 0;
2079         const char *ptr = NULL, *end;
2080
2081         if (!decode_signature_header (ctx, offset, &size, &ptr))
2082                 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2083         end = ptr + size;
2084
2085         return parse_property_signature (ctx, &ptr, end);
2086 }
2087
2088 static gboolean
2089 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2090 {
2091         guint32 size = 0;
2092         const char *ptr = NULL, *end;
2093         unsigned type = 0;
2094         
2095         if (!decode_signature_header (ctx, offset, &size, &ptr))
2096                 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2097         end = ptr + size;
2098
2099         if (!parse_custom_mods (ctx, &ptr, end))
2100                 return FALSE;
2101
2102         if (!safe_read8 (type, ptr, end))
2103                 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2104
2105         if (type == MONO_TYPE_BYREF) {
2106                 if (!safe_read8 (type, ptr, end)) 
2107                         FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2108                 if (type == MONO_TYPE_TYPEDBYREF)
2109                         FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2110         }
2111         
2112         if (type == MONO_TYPE_TYPEDBYREF)
2113                 return TRUE;
2114
2115         --ptr;
2116         return parse_type (ctx, &ptr, end);
2117 }
2118
2119 static gboolean
2120 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2121 {
2122         guint32 size = 0;
2123         const char *ptr = NULL, *end;
2124         unsigned type = 0;
2125         unsigned count = 0, i;
2126
2127         if (!decode_signature_header (ctx, offset, &size, &ptr))
2128                 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2129         end = ptr + size;
2130
2131         if (!safe_read8 (type, ptr, end))
2132                 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2133
2134         if (type != 0x0A)
2135                 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2136
2137         if (!safe_read_cint (count, ptr, end))
2138                 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2139
2140         if (!count)
2141                 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2142
2143         for (i = 0; i < count; ++i) {
2144                 if (!parse_custom_mods (ctx, &ptr, end))
2145                         return FALSE;
2146                 if (!parse_type (ctx, &ptr, end))
2147                         FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2148         }
2149         return TRUE;
2150 }
2151
2152 static gboolean
2153 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2154 {
2155         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2156         guint32 entry_size, bytes;
2157
2158         if (blob.size < offset)
2159                 return FALSE;
2160
2161         if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2162                 return FALSE;
2163
2164         if (entry_size < minsize)
2165                 return FALSE;
2166
2167         if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2168                 return FALSE;
2169         entry_size += bytes;
2170
2171         return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2172 }
2173
2174 static gboolean
2175 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2176 {
2177         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2178         guint32 size, entry_size, bytes;
2179
2180         if (blob.size < offset)
2181                 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2182         
2183         if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2184                 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2185
2186         if (type == MONO_TYPE_STRING) {
2187                 //String is encoded as: compressed_int:len len *bytes
2188                 offset += bytes;
2189
2190                 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2191                         FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));  
2192
2193                 return TRUE;
2194         }
2195
2196         switch (type) {
2197         case MONO_TYPE_BOOLEAN:
2198         case MONO_TYPE_I1:
2199         case MONO_TYPE_U1:
2200                 size = 1;
2201                 break;
2202         case MONO_TYPE_CHAR:
2203         case MONO_TYPE_I2:
2204         case MONO_TYPE_U2:
2205                 size = 2;
2206                 break;
2207         case MONO_TYPE_I4:
2208         case MONO_TYPE_U4:
2209         case MONO_TYPE_R4:
2210         case MONO_TYPE_CLASS:
2211                 size = 4;
2212                 break;
2213
2214         case MONO_TYPE_I8:
2215         case MONO_TYPE_U8:
2216         case MONO_TYPE_R8:
2217                 size = 8;
2218                 break;
2219         default:
2220                 g_assert_not_reached ();
2221         }
2222
2223         if (size != entry_size)
2224                 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2225
2226         offset += bytes;
2227
2228         if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2229                 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2230
2231         if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2232                 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2233         return TRUE;
2234 }
2235
2236 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2237 //only 0x01, 0x40 and 0x80 are allowed
2238 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2239
2240 static gboolean
2241 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2242 {
2243         unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2244         unsigned header = 0;
2245         unsigned fat_header = 0, size = 0, max_stack;
2246         const char *ptr = NULL, *end;
2247
2248         *locals_token = 0;
2249
2250         if (offset == INVALID_ADDRESS)
2251                 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2252
2253         ptr = ctx->data + offset;
2254         end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2255
2256         if (!safe_read8 (header, ptr, end))
2257                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2258
2259         switch (header & 0x3) {
2260         case 0:
2261         case 1:
2262                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2263         case 2:
2264                 header >>= 2;
2265                 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end)) 
2266                         FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2267                 return TRUE;
2268         }
2269         //FAT HEADER
2270         --ptr;
2271         if (!safe_read16 (fat_header, ptr, end))
2272                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2273
2274         size = (fat_header >> 12) & 0xF;
2275         if (size != 3)
2276                 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2277
2278         if (!safe_read16 (max_stack, ptr, end))
2279                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2280
2281         if (!safe_read32 (code_size, ptr, end))
2282                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2283
2284         if (!safe_read32 (local_vars_tok, ptr, end))
2285                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2286
2287         if (local_vars_tok) {
2288                 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2289                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2290                 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)   
2291                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2292                 if (!(local_vars_tok & 0xFFFFFF))
2293                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature with zero index"));
2294                 *locals_token = local_vars_tok & 0xFFFFFF;
2295         }
2296
2297         if (fat_header & FAT_HEADER_INVALID_FLAGS)
2298                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2299
2300         if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2301                 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2302
2303         if (!(fat_header & 0x08))
2304                 return TRUE;
2305
2306         ptr += code_size;
2307
2308         do {
2309                 unsigned section_header = 0, section_size = 0;
2310                 gboolean is_fat;
2311
2312                 ptr = dword_align (ptr);
2313                 if (!safe_read32 (section_header, ptr, end))
2314                         FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2315
2316                 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2317                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2318                         
2319                 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2320                 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2321
2322                 if (section_size < 4)
2323                         FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2324
2325                 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2326                         FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2327
2328                 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2329                         guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2330                         /*
2331                                 LAMEIMPL: MS emits section_size without accounting for header size.
2332                                 Mono does as the spec says. section_size is header + section
2333                                 MS's peverify happily accepts both. 
2334                         */
2335                         if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2336                                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the expected size %d", section_size, clauses * (is_fat ? 24 : 12)));
2337
2338                         /* only verify the class token is verified as the rest is done by the IL verifier*/
2339                         for (i = 0; i < clauses; ++i) {
2340                                 unsigned flags = *(unsigned char*)ptr;
2341                                 unsigned class_token = 0;
2342                                 ptr += (is_fat ? 20 : 8);
2343                                 if (!safe_read32 (class_token, ptr, end))
2344                                         FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2345                                 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2346                                         guint table = mono_metadata_token_table (class_token);
2347                                         if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2348                                                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2349                                         if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2350                                                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2351                                 }
2352                         }
2353                 }
2354
2355                 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2356                         break;
2357         } while (1);
2358         return TRUE;
2359 }
2360
2361 static void
2362 verify_module_table (VerifyContext *ctx)
2363 {
2364         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2365         guint32 data [MONO_MODULE_SIZE];
2366
2367         if (table->rows != 1)
2368                 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2369
2370         mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2371
2372         if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2373                 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2374
2375         if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2376                 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2377
2378         if (data [MONO_MODULE_ENC] != 0)
2379                 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2380
2381         if (data [MONO_MODULE_ENCBASE] != 0)
2382                 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2383 }
2384
2385 static void
2386 verify_typeref_table (VerifyContext *ctx)
2387 {
2388         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2389         MonoError error;
2390         guint32 i;
2391
2392         for (i = 0; i < table->rows; ++i) {
2393                 mono_verifier_verify_typeref_row (ctx->image, i, &error);
2394                 add_from_mono_error (ctx, &error);
2395         }
2396 }
2397
2398 /*bits 9,11,14,15,19,21,24-31 */
2399 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2400 static void
2401 verify_typedef_table (VerifyContext *ctx)
2402 {
2403         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2404         guint32 data [MONO_TYPEDEF_SIZE];
2405         guint32 fieldlist = 1, methodlist = 1, visibility;
2406         int i;
2407
2408         if (table->rows == 0)
2409                 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2410
2411         for (i = 0; i < table->rows; ++i) {
2412                 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2413                 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2414                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2415
2416                 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2417                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2418
2419                 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2420                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2421
2422                 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2423                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2424
2425                 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2426                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2427
2428                 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2429                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2430
2431                 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2432                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2433
2434                 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2435                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2436
2437                 if (data [MONO_TYPEDEF_EXTENDS] && !get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2438                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d zero coded extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2439
2440                 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2441                 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2442                         search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2443                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2444
2445                 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2446                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2447
2448                 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2449                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2450
2451                 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2452                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_TYPEDEF_FIELD_LIST], fieldlist));
2453
2454                 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2455                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2456
2457                 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2458                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2459
2460                 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2461                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_TYPEDEF_METHOD_LIST], methodlist));
2462
2463                 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2464                 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2465         }
2466 }
2467
2468 static void
2469 verify_typedef_table_full (VerifyContext *ctx)
2470 {
2471         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2472         guint32 data [MONO_TYPEDEF_SIZE];
2473         int i;
2474
2475         if (table->rows == 0)
2476                 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2477
2478         for (i = 0; i < table->rows; ++i) {
2479                 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2480
2481                 if (i == 0) {
2482                         /*XXX it's ok if <module> extends object, or anything at all, actually. */
2483                         /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2484                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2485                         */
2486                         continue;
2487                 }
2488
2489                 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2490                         if (data [MONO_TYPEDEF_EXTENDS])
2491                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2492                 } else {
2493                         gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2494                         gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2495
2496                         if (is_sys_obj) {
2497                                 if (has_parent)
2498                                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2499                         } else {
2500                                 if (!has_parent) {
2501                                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2502                                 }
2503                         }
2504                 }
2505         }
2506 }
2507
2508 /*bits 3,11,14 */
2509 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2510 static void
2511 verify_field_table (VerifyContext *ctx)
2512 {
2513         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2514         guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2515         int i;
2516
2517         module_field_list = (guint32)-1;
2518         if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2519                 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2520                 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2521         }
2522         
2523         for (i = 0; i < table->rows; ++i) {
2524                 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2525                 flags = data [MONO_FIELD_FLAGS];
2526
2527                 if (flags & INVALID_FIELD_FLAG_BITS)
2528                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2529
2530                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)         
2531                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2532
2533                 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2534                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2535
2536                 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2537                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2538
2539                 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2540                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2541
2542                 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2543                                 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2544                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2545
2546                 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2547                                 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2548                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2549
2550                 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2551                                 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2552                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2553
2554                 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2555                                 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2556                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2557
2558                 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2559                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2560
2561                 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2562                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2563
2564                 //TODO verify contant flag
2565
2566                 if (i + 1 < module_field_list) {
2567                         guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2568                         if (!(flags & FIELD_ATTRIBUTE_STATIC))
2569                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2570                         if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2571                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2572                 }
2573         }
2574 }
2575
2576 static void
2577 verify_field_table_full (VerifyContext *ctx)
2578 {
2579         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2580         guint32 data [MONO_FIELD_SIZE];
2581         int i;
2582         
2583         for (i = 0; i < table->rows; ++i) {
2584                 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2585
2586                 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2587                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2588         }
2589 }
2590
2591 /*bits 8,9,10,11,13,14,15*/
2592 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2593 static void
2594 verify_method_table (VerifyContext *ctx)
2595 {
2596         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2597         guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2598         guint32 paramlist = 1;
2599         gboolean is_ctor, is_cctor;
2600         const char *name;
2601         int i;
2602
2603         module_method_list = (guint32)-1;
2604         if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2605                 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2606                 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2607         }
2608
2609         for (i = 0; i < table->rows; ++i) {
2610                 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2611                 rva = data [MONO_METHOD_RVA];
2612                 implflags = data [MONO_METHOD_IMPLFLAGS];
2613                 flags = data [MONO_METHOD_FLAGS];
2614                 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2615                 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2616                 
2617
2618                 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2619                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2620
2621                 if (access == 0x7)
2622                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2623
2624                 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2625                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2626
2627                 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2628                 is_ctor = !strcmp (".ctor", name);
2629                 is_cctor = !strcmp (".cctor", name);
2630
2631                 if ((is_ctor || is_cctor) &&
2632                         search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2633                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2634
2635                 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2636                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2637                 
2638                 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2639                         if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2640                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2641                         if (flags & METHOD_ATTRIBUTE_FINAL)
2642                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2643                         if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2644                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2645                 }
2646
2647                 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2648                         ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2649
2650                 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2651                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2652
2653                 //XXX no checks against cas stuff 10,11,12,13)
2654
2655                 //TODO check iface with .ctor (15,16)
2656
2657                 if (i + 1 < module_method_list) {
2658                         if (!(flags & METHOD_ATTRIBUTE_STATIC))
2659                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2660                         if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2661                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2662                         if (access == METHOD_ATTRIBUTE_FAMILY || access == METHOD_ATTRIBUTE_FAM_AND_ASSEM || access == METHOD_ATTRIBUTE_FAM_OR_ASSEM)
2663                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public, Private or Assembly", i));
2664                 }
2665
2666                 //TODO check valuetype for synchronized
2667
2668                 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2669                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2670
2671                 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2672                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2673                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2674                         if (!(flags & METHOD_ATTRIBUTE_STATIC))
2675                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2676                 }
2677
2678                 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && 
2679                                 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2680                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2681
2682                 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2683                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2684
2685                 //TODO check signature contents
2686
2687                 if (rva) {
2688                         if ((flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) || (implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2689                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is either Abstract, InternalCall or PinvokeImpl", i));
2690                         if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2691                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2692                 } else {
2693                         if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2694                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2695                 }
2696
2697                 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2698                         if (rva)
2699                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2700                         if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2701                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2702                 }
2703                 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2704                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2705
2706                 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2707                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2708
2709                 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2710                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2711
2712                 if (data [MONO_METHOD_PARAMLIST] == 0)
2713                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2714
2715                 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2716                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_METHOD_PARAMLIST], paramlist));
2717
2718                 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2719                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2720
2721                 paramlist = data [MONO_METHOD_PARAMLIST];
2722
2723         }
2724 }
2725
2726 static void
2727 verify_method_table_full (VerifyContext *ctx)
2728 {
2729         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2730         guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2731         int i;
2732
2733         for (i = 0; i < table->rows; ++i) {
2734                 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2735                 rva = data [MONO_METHOD_RVA];
2736
2737                 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2738                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2739
2740                 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2741                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2742         }
2743 }
2744
2745 static guint32
2746 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2747 {
2748         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2749         guint32 row = *current_method;
2750         guint32 paramlist, tmp;
2751
2752
2753         paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2754         while (row < table->rows) {
2755                 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2756                 if (tmp > paramlist) {
2757                         *current_method = row;
2758                         return tmp - paramlist;
2759                 }
2760                 ++row;
2761         }
2762
2763         /*no more methods, all params apply to the last one*/
2764         *current_method = table->rows;
2765         return (guint32)-1;
2766 }
2767
2768
2769 #define INVALID_PARAM_FLAGS_BITS ((1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15))
2770 static void
2771 verify_param_table (VerifyContext *ctx)
2772 {
2773         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2774         guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2775         gboolean first_param = TRUE;
2776         int i;
2777
2778         if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2779                 if (table->rows > 0)
2780                         ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2781                 return;
2782         }
2783         
2784         remaining_params = get_next_param_count (ctx, &current_method);
2785
2786         for (i = 0; i < table->rows; ++i) {
2787                 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2788                 flags = data [MONO_PARAM_FLAGS];
2789
2790                 if (flags & INVALID_PARAM_FLAGS_BITS)
2791                         ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2792
2793                 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2794                         if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2795                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2796                 } else {
2797                         if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2798                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2799                 }
2800
2801                 if ((flags & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL) && search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_PARAM, i)) == -1)
2802                         ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2803
2804                 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2805                         ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2806
2807                 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2808                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2809
2810                 first_param = FALSE;
2811                 sequence = data [MONO_PARAM_SEQUENCE];
2812                 if (--remaining_params == 0) {
2813                         remaining_params = get_next_param_count (ctx, &current_method);
2814                         first_param = TRUE;
2815                 }
2816         }
2817 }
2818
2819 static void
2820 verify_interfaceimpl_table (VerifyContext *ctx)
2821 {
2822         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2823         guint32 data [MONO_INTERFACEIMPL_SIZE];
2824         int i;
2825
2826         for (i = 0; i < table->rows; ++i) {
2827                 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2828                 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2829                         ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_INTERFACEIMPL_CLASS]));
2830
2831                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2832                         ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2833
2834                 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2835                         ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2836         }
2837 }
2838
2839 static void
2840 verify_memberref_table (VerifyContext *ctx)
2841 {
2842         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2843         guint32 data [MONO_MEMBERREF_SIZE];
2844         int i;
2845
2846         for (i = 0; i < table->rows; ++i) {
2847                 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2848
2849                 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2850                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2851
2852                 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2853                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2854
2855                 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2856                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2857
2858                 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2859                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2860         }
2861 }
2862
2863
2864 static void
2865 verify_memberref_table_full (VerifyContext *ctx)
2866 {
2867         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2868         guint32 data [MONO_MEMBERREF_SIZE];
2869         int i;
2870
2871         for (i = 0; i < table->rows; ++i) {
2872                 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2873
2874                 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2875                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field  0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2876         }
2877 }
2878
2879 static void
2880 verify_constant_table (VerifyContext *ctx)
2881 {
2882         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2883         guint32 data [MONO_CONSTANT_SIZE], type;
2884         int i;
2885
2886         for (i = 0; i < table->rows; ++i) {
2887                 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2888                 type = data [MONO_CONSTANT_TYPE];
2889
2890                 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2891                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2892
2893                 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2894                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2895
2896                 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2897                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2898
2899                 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2900                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2901         }
2902 }
2903
2904 static void
2905 verify_cattr_table (VerifyContext *ctx)
2906 {
2907         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2908         guint32 data [MONO_CUSTOM_ATTR_SIZE];
2909         int i;
2910
2911         for (i = 0; i < table->rows; ++i) {
2912                 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2913
2914                 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2915                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2916
2917                 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]) || !get_coded_index_token (CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2918                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Type field 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2919
2920                 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2921                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2922         }
2923 }
2924
2925 static void
2926 verify_cattr_table_full (VerifyContext *ctx)
2927 {
2928         MonoError error;
2929         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2930         MonoMethod *ctor;
2931         const char *ptr;
2932         guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2933         int i;
2934
2935         for (i = 0; i < table->rows; ++i) {
2936                 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2937
2938                 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2939                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2940
2941                 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2942                 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2943                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2944                         mtoken |= MONO_TOKEN_METHOD_DEF;
2945                         break;
2946                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2947                         mtoken |= MONO_TOKEN_MEMBER_REF;
2948                         break;
2949                 default:
2950                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2951                 }
2952
2953                 ctor = mono_get_method_checked (ctx->image, mtoken, NULL, NULL, &error);
2954
2955                 if (!ctor) {
2956                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Could not load ctor due to %s", i, mono_error_get_message (&error)));
2957                         mono_error_cleanup (&error);
2958                 }
2959
2960                 /*This can't fail since this is checked in is_valid_cattr_blob*/
2961                 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2962
2963                 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2964                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2965         }
2966 }
2967
2968 static void
2969 verify_field_marshal_table (VerifyContext *ctx)
2970 {
2971         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2972         guint32 data [MONO_FIELD_MARSHAL_SIZE];
2973         int i;
2974
2975         for (i = 0; i < table->rows; ++i) {
2976                 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2977
2978                 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2979                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2980
2981                 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2982                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2983
2984                 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2985                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2986
2987                 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2988                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2989         }
2990 }
2991
2992 static void
2993 verify_field_marshal_table_full (VerifyContext *ctx)
2994 {
2995         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2996         guint32 data [MONO_FIELD_MARSHAL_SIZE];
2997         int i;
2998
2999         for (i = 0; i < table->rows; ++i) {
3000                 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
3001
3002                 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
3003                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
3004         }
3005 }
3006
3007 static void
3008 verify_decl_security_table (VerifyContext *ctx)
3009 {
3010         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3011         guint32 data [MONO_DECL_SECURITY_SIZE];
3012         int i;
3013
3014         for (i = 0; i < table->rows; ++i) {
3015                 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3016
3017                 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3018                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
3019
3020                 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3021                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
3022
3023                 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
3024                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
3025         }
3026 }
3027
3028 static void
3029 verify_decl_security_table_full (VerifyContext *ctx)
3030 {
3031         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3032         guint32 data [MONO_DECL_SECURITY_SIZE];
3033         int i;
3034
3035         for (i = 0; i < table->rows; ++i) {
3036                 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3037
3038                 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
3039                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
3040         }
3041 }
3042
3043 static void
3044 verify_class_layout_table (VerifyContext *ctx)
3045 {
3046         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
3047         guint32 data [MONO_CLASS_LAYOUT_SIZE];
3048         int i;
3049
3050         for (i = 0; i < table->rows; ++i) {
3051                 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
3052
3053                 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3054                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
3055
3056                 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3057                 case 0:
3058                 case 1:
3059                 case 2:
3060                 case 4:
3061                 case 8:
3062                 case 16:
3063                 case 32:
3064                 case 64:
3065                 case 128:
3066                         break;
3067                 default:
3068                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3069                 }
3070         }
3071 }
3072
3073 static void
3074 verify_field_layout_table (VerifyContext *ctx)
3075 {
3076         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3077         guint32 data [MONO_FIELD_LAYOUT_SIZE];
3078         int i;
3079
3080         for (i = 0; i < table->rows; ++i) {
3081                 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3082
3083                 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3084                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3085         }
3086 }
3087
3088 static void
3089 verify_standalonesig_table (VerifyContext *ctx)
3090 {
3091         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3092         guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3093         int i;
3094
3095         for (i = 0; i < table->rows; ++i) {
3096                 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3097
3098                 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3099                         ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3100         }
3101 }
3102
3103 static void
3104 verify_standalonesig_table_full (VerifyContext *ctx)
3105 {
3106         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3107         guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3108         int i;
3109
3110         for (i = 0; i < table->rows; ++i) {
3111                 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3112
3113                 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3114                         ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3115         }
3116 }
3117
3118 static void
3119 verify_eventmap_table (VerifyContext *ctx)
3120 {
3121         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3122         guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3123         int i;
3124
3125         for (i = 0; i < table->rows; ++i) {
3126                 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3127
3128                 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3129                         ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3130
3131                 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3132                         ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3133
3134                 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3135         }
3136 }
3137
3138 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3139 static void
3140 verify_event_table (VerifyContext *ctx)
3141 {
3142         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3143         guint32 data [MONO_EVENT_SIZE];
3144         int i;
3145
3146         for (i = 0; i < table->rows; ++i) {
3147                 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3148
3149                 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3150                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3151
3152                 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3153                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3154
3155                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3156                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3157         }
3158 }
3159
3160 static void
3161 verify_event_table_full (VerifyContext *ctx)
3162 {
3163         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3164         MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3165         guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3166         gboolean found_add, found_remove;
3167         int i, idx;
3168
3169         for (i = 0; i < table->rows; ++i) {
3170                 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3171
3172                 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3173                 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3174                 if (idx == -1)
3175                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3176
3177                 //first we move to the first row for this event
3178                 while (idx > 0) {
3179                         if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3180                                 break;
3181                         --idx;
3182                 }
3183                 //now move forward looking for AddOn and RemoveOn rows
3184                 found_add = found_remove = FALSE;
3185                 while (idx < sema_table->rows) {
3186                         mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3187                         if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3188                                 break;
3189                         if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3190                                 found_add = TRUE;
3191                         if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3192                                 found_remove = TRUE;
3193                         if (found_add && found_remove)
3194                                 break;
3195                         ++idx;
3196                 }
3197
3198                 if (!found_add)
3199                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3200                 if (!found_remove)
3201                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no RemoveOn associated method", i));
3202         }
3203 }
3204
3205 static void
3206 verify_propertymap_table (VerifyContext *ctx)
3207 {
3208         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3209         guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3210         int i;
3211
3212         for (i = 0; i < table->rows; ++i) {
3213                 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3214
3215                 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3216                         ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3217
3218                 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3219                         ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3220
3221                 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3222         }
3223 }
3224
3225 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3226 static void
3227 verify_property_table (VerifyContext *ctx)
3228 {
3229         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3230         guint32 data [MONO_PROPERTY_SIZE];
3231         int i;
3232
3233         for (i = 0; i < table->rows; ++i) {
3234                 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3235
3236                 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3237                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3238
3239                 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3240                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3241
3242                 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3243                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3244
3245                 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3246                                 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3247                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3248
3249         }
3250 }
3251
3252 static void
3253 verify_methodimpl_table (VerifyContext *ctx)
3254 {
3255         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3256         guint32 data [MONO_METHODIMPL_SIZE];
3257         int i;
3258
3259         for (i = 0; i < table->rows; ++i) {
3260                 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3261
3262                 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3263                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3264                         
3265                 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3266                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3267                 
3268                 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3269                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3270
3271                 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3272                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3273                 
3274                 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3275                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3276         }
3277 }
3278
3279 static void
3280 verify_moduleref_table (VerifyContext *ctx)
3281 {
3282         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3283         guint32 data [MONO_MODULEREF_SIZE];
3284         int i;
3285
3286         for (i = 0; i < table->rows; ++i) {
3287                 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3288
3289                 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3290                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ModuleRef row %d name field %08x", i, data [MONO_MODULEREF_NAME]));
3291         }
3292 }
3293
3294 static void
3295 verify_typespec_table (VerifyContext *ctx)
3296 {
3297         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3298         guint32 data [MONO_TYPESPEC_SIZE];
3299         int i;
3300
3301         for (i = 0; i < table->rows; ++i) {
3302                 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3303
3304                 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3305                         ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3306         }
3307 }
3308
3309 static void
3310 verify_typespec_table_full (VerifyContext *ctx)
3311 {
3312         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3313         guint32 data [MONO_TYPESPEC_SIZE];
3314         int i;
3315
3316         for (i = 0; i < table->rows; ++i) {
3317                 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3318                 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3319                 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3320                         ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3321         }
3322         ctx->token = 0;
3323 }
3324
3325 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13))
3326 static void
3327 verify_implmap_table (VerifyContext *ctx)
3328 {
3329         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3330         guint32 data [MONO_IMPLMAP_SIZE], cconv;
3331         int i;
3332
3333         for (i = 0; i < table->rows; ++i) {
3334                 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3335
3336                 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3337                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3338
3339                 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3340                 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3341                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3342
3343                 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3344                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3345
3346                 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3347                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3348
3349                 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3350                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3351
3352                 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3353                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3354
3355                 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows)
3356                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3357         }
3358 }
3359
3360 static void
3361 verify_fieldrva_table (VerifyContext *ctx)
3362 {
3363         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3364         guint32 data [MONO_FIELD_RVA_SIZE];
3365         int i;
3366
3367         for (i = 0; i < table->rows; ++i) {
3368                 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3369
3370                 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3371                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3372
3373                 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3374                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3375         }
3376 }
3377
3378 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 14) | (1 << 15))
3379 static void
3380 verify_assembly_table (VerifyContext *ctx)
3381 {
3382         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3383         guint32 data [MONO_ASSEMBLY_SIZE], hash;
3384         int i;
3385
3386         if (table->rows > 1)
3387                 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3388
3389         for (i = 0; i < table->rows; ++i) {
3390                 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3391
3392                 hash = data [MONO_ASSEMBLY_HASH_ALG];
3393                 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3394                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3395
3396                 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3397                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3398
3399                 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3400                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3401
3402                 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3403                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3404
3405                 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3406                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3407         }
3408 }
3409
3410 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
3411 static void
3412 verify_assemblyref_table (VerifyContext *ctx)
3413 {
3414         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3415         guint32 data [MONO_ASSEMBLYREF_SIZE];
3416         int i;
3417
3418         for (i = 0; i < table->rows; ++i) {
3419                 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3420
3421                 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3422                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3423
3424                 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3425                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3426
3427                 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3428                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3429
3430                 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3431                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3432
3433                 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3434                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3435         }
3436 }
3437
3438 #define INVALID_FILE_FLAGS_BITS ~(1)
3439 static void
3440 verify_file_table (VerifyContext *ctx)
3441 {
3442         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3443         guint32 data [MONO_FILE_SIZE];
3444         int i;
3445
3446         for (i = 0; i < table->rows; ++i) {
3447                 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3448                 
3449                 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3450                         ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3451
3452                 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3453                         ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3454
3455                 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3456                         ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3457         }
3458 }
3459
3460 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3461 static void
3462 verify_exportedtype_table (VerifyContext *ctx)
3463 {
3464         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3465         guint32 data [MONO_EXP_TYPE_SIZE];
3466         int i;
3467
3468         for (i = 0; i < table->rows; ++i) {
3469                 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3470                 
3471                 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3472                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3473
3474                 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3475                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3476
3477                 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3478                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3479
3480                 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3481                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3482
3483                 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3484                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3485
3486                 /*nested type can't have a namespace*/
3487                 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3488                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3489         }
3490 }
3491
3492 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3493 static void
3494 verify_manifest_resource_table (VerifyContext *ctx)
3495 {
3496         MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
3497         MonoCLIHeader *ch = &iinfo->cli_cli_header;
3498         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3499         guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3500         int i;
3501
3502         resources_size = ch->ch_resources.size;
3503
3504         for (i = 0; i < table->rows; ++i) {
3505                 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3506
3507                 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3508                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3509
3510                 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3511                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3512
3513                 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3514                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3515
3516                 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3517                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3518
3519                 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3520                 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3521
3522                 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3523                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token table %08x", i, get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION])));
3524
3525                 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3526                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3527
3528                 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3529                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3530         }
3531 }
3532
3533 static void
3534 verify_nested_class_table (VerifyContext *ctx)
3535 {
3536         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3537         guint32 data [MONO_NESTED_CLASS_SIZE];
3538         int i;
3539
3540         for (i = 0; i < table->rows; ++i) {
3541                 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3542
3543                 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3544                         ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3545                 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3546                         ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3547                 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3548                         ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass  and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3549         }
3550 }
3551
3552 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3553 static void
3554 verify_generic_param_table (VerifyContext *ctx)
3555 {
3556         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3557         guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3558         int i, param_number = 0;
3559
3560         for (i = 0; i < table->rows; ++i) {
3561                 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3562
3563                 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3564                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3565
3566                 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3567                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3568
3569                 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3570                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3571
3572                 token = data [MONO_GENERICPARAM_OWNER];
3573
3574                 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3575                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3576
3577                 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3578                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3579
3580                 if (token != last_token) {
3581                         param_number = 0;
3582                         last_token = token;
3583                 }
3584
3585                 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3586                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d Number is out of order %d expected %d", i, data [MONO_GENERICPARAM_NUMBER], param_number));
3587
3588                 ++param_number;
3589         }
3590 }
3591
3592 static void
3593 verify_method_spec_table (VerifyContext *ctx)
3594 {
3595         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3596         guint32 data [MONO_METHODSPEC_SIZE];
3597         int i;
3598
3599         for (i = 0; i < table->rows; ++i) {
3600                 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3601
3602                 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3603                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3604
3605                 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3606                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3607
3608                 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3609                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3610         }
3611 }
3612
3613 static void
3614 verify_method_spec_table_full (VerifyContext *ctx)
3615 {
3616         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3617         guint32 data [MONO_METHODSPEC_SIZE];
3618         int i;
3619
3620         for (i = 0; i < table->rows; ++i) {
3621                 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3622
3623                 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3624                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3625         }
3626 }
3627
3628 static void
3629 verify_generic_param_constraint_table (VerifyContext *ctx)
3630 {
3631         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3632         guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3633         int i;
3634         guint32 last_owner = 0, last_constraint = 0;
3635
3636         for (i = 0; i < table->rows; ++i) {
3637                 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3638
3639                 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3640                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3641
3642                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3643                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3644
3645                 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3646                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3647
3648                 if (last_owner > data [MONO_GENPARCONSTRAINT_GENERICPAR])
3649                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d is not properly sorted. Previous value of the owner column is 0x%08x current value is 0x%08x", i, last_owner, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3650
3651                 if (last_owner == data [MONO_GENPARCONSTRAINT_GENERICPAR]) {
3652                         if (last_constraint == data [MONO_GENPARCONSTRAINT_CONSTRAINT])
3653                                 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has duplicate constraint 0x%08x", i, last_constraint));
3654                 } else {
3655                         last_owner = data [MONO_GENPARCONSTRAINT_GENERICPAR];
3656                 }
3657                 last_constraint = data [MONO_GENPARCONSTRAINT_CONSTRAINT];
3658         }
3659 }
3660
3661
3662 typedef struct {
3663         const char *name;
3664         const char *name_space;
3665         guint32 resolution_scope;
3666 } TypeDefUniqueId;
3667
3668 static guint
3669 typedef_hash (gconstpointer _key)
3670 {
3671         const TypeDefUniqueId *key = (const TypeDefUniqueId *)_key;
3672         return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3673 }
3674
3675 static gboolean
3676 typedef_equals (gconstpointer _a, gconstpointer _b)
3677 {
3678         const TypeDefUniqueId *a = (const TypeDefUniqueId *)_a;
3679         const TypeDefUniqueId *b = (const TypeDefUniqueId *)_b;
3680         return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3681 }
3682
3683 static void
3684 verify_typedef_table_global_constraints (VerifyContext *ctx)
3685 {
3686         int i;
3687         guint32 data [MONO_TYPEDEF_SIZE];
3688         guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3689         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3690         MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3691         GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3692
3693         for (i = 0; i < table->rows; ++i) {
3694                 guint visibility;
3695                 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3696                 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3697
3698                 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3699                 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3700                 type->resolution_scope = 0;
3701
3702                 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3703                 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3704                         int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3705                         g_assert (res >= 0);
3706
3707                         mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3708                         type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3709                 }
3710
3711                 if (g_hash_table_lookup (unique_types, type)) {
3712                         ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("TypeDef table row %d has duplicate for tuple (%s,%s,%x)", i, type->name, type->name_space, type->resolution_scope));
3713                         g_hash_table_destroy (unique_types);
3714                         g_free (type);
3715                         return;
3716                 }
3717                 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3718         }
3719
3720         g_hash_table_destroy (unique_types);
3721 }
3722
3723 static void
3724 verify_typeref_table_global_constraints (VerifyContext *ctx)
3725 {
3726         int i;
3727         guint32 data [MONO_TYPEREF_SIZE];
3728         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3729         GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3730
3731         for (i = 0; i < table->rows; ++i) {
3732                 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3733                 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3734
3735                 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3736                 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3737                 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3738
3739                 if (g_hash_table_lookup (unique_types, type)) {
3740                         ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("TypeRef table row %d has duplicate for tuple (%s,%s,%x)", i, type->name, type->name_space, type->resolution_scope));
3741                         g_hash_table_destroy (unique_types);
3742                         g_free (type);
3743                         return;
3744                 }
3745                 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3746         }
3747
3748         g_hash_table_destroy (unique_types);
3749 }
3750
3751 static void
3752 verify_tables_data_global_constraints (VerifyContext *ctx)
3753 {
3754         verify_typedef_table_global_constraints (ctx);
3755 }
3756
3757 static void
3758 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3759 {
3760         verify_typeref_table (ctx);
3761         verify_typeref_table_global_constraints (ctx);
3762 }
3763
3764 static void
3765 verify_tables_data (VerifyContext *ctx)
3766 {
3767         OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3768         guint32 size = 0, tables_offset;
3769         int i;
3770
3771         for (i = 0; i < 0x2D; ++i) {
3772                 MonoTableInfo *table = &ctx->image->tables [i];
3773                 guint32 tmp_size;
3774                 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3775                 if (tmp_size < size) {
3776                         size = 0;
3777                         break;
3778                 }
3779                 size = tmp_size;                        
3780         }
3781
3782         if (size == 0)
3783                 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3784
3785         tables_offset = ctx->image->tables_base - ctx->data;
3786         if (!bounds_check_offset (&tables_area, tables_offset, size))
3787                 ADD_ERROR (ctx, g_strdup_printf ("Tables data require %d bytes but the only %d are available in the #~ stream", size, tables_area.size - (tables_offset - tables_area.offset)));
3788
3789         verify_module_table (ctx);
3790         CHECK_ERROR ();
3791         /*Obfuscators love to place broken stuff in the typeref table
3792         verify_typeref_table (ctx);
3793         CHECK_ERROR ();*/
3794         verify_typedef_table (ctx);
3795         CHECK_ERROR ();
3796         verify_field_table (ctx);
3797         CHECK_ERROR ();
3798         verify_method_table (ctx);
3799         CHECK_ERROR ();
3800         verify_param_table (ctx);
3801         CHECK_ERROR ();
3802         verify_interfaceimpl_table (ctx);
3803         CHECK_ERROR ();
3804         verify_memberref_table (ctx);
3805         CHECK_ERROR ();
3806         verify_constant_table (ctx);
3807         CHECK_ERROR ();
3808         verify_cattr_table (ctx);
3809         CHECK_ERROR ();
3810         verify_field_marshal_table (ctx);
3811         CHECK_ERROR ();
3812         verify_decl_security_table (ctx);
3813         CHECK_ERROR ();
3814         verify_class_layout_table (ctx);
3815         CHECK_ERROR ();
3816         verify_field_layout_table (ctx);
3817         CHECK_ERROR ();
3818         verify_standalonesig_table (ctx);
3819         CHECK_ERROR ();
3820         verify_eventmap_table (ctx);
3821         CHECK_ERROR ();
3822         verify_event_table (ctx);
3823         CHECK_ERROR ();
3824         verify_propertymap_table (ctx);
3825         CHECK_ERROR ();
3826         verify_property_table (ctx);
3827         CHECK_ERROR ();
3828         verify_methodimpl_table (ctx);
3829         CHECK_ERROR ();
3830         verify_moduleref_table (ctx);
3831         CHECK_ERROR ();
3832         verify_typespec_table (ctx);
3833         CHECK_ERROR ();
3834         verify_implmap_table (ctx);
3835         CHECK_ERROR ();
3836         verify_fieldrva_table (ctx);
3837         CHECK_ERROR ();
3838         verify_assembly_table (ctx);
3839         CHECK_ERROR ();
3840         verify_assemblyref_table (ctx);
3841         CHECK_ERROR ();
3842         verify_file_table (ctx);
3843         CHECK_ERROR ();
3844         verify_exportedtype_table (ctx);
3845         CHECK_ERROR ();
3846         verify_manifest_resource_table (ctx);
3847         CHECK_ERROR ();
3848         verify_nested_class_table (ctx);
3849         CHECK_ERROR ();
3850         verify_generic_param_table (ctx);
3851         CHECK_ERROR ();
3852         verify_method_spec_table (ctx);
3853         CHECK_ERROR ();
3854         verify_generic_param_constraint_table (ctx);
3855         CHECK_ERROR ();
3856         verify_tables_data_global_constraints (ctx);
3857 }
3858
3859 static void
3860 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3861 {
3862         memset (ctx, 0, sizeof (VerifyContext));
3863         ctx->image = image;
3864         ctx->report_error = report_error;
3865         ctx->report_warning = FALSE; //export this setting in the API
3866         ctx->valid = 1;
3867         ctx->size = image->raw_data_len;
3868         ctx->data = image->raw_data;
3869 }
3870
3871 static gboolean
3872 cleanup_context (VerifyContext *ctx, GSList **error_list)
3873 {
3874         g_free (ctx->sections);
3875         if (error_list)
3876                 *error_list = ctx->errors;
3877         else
3878                 mono_free_verify_list (ctx->errors);
3879         return ctx->valid;      
3880 }
3881
3882 static gboolean
3883 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3884 {
3885         g_free (ctx->sections);
3886         if (ctx->errors) {
3887                 MonoVerifyInfo *info = (MonoVerifyInfo *)ctx->errors->data;
3888                 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3889                 mono_free_verify_list (ctx->errors);
3890         }
3891         return ctx->valid;
3892 }
3893
3894 gboolean
3895 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3896 {
3897         VerifyContext ctx;
3898
3899         if (!mono_verifier_is_enabled_for_image (image))
3900                 return TRUE;
3901
3902         init_verify_context (&ctx, image, error_list != NULL);
3903         ctx.stage = STAGE_PE;
3904
3905         verify_msdos_header (&ctx);
3906         CHECK_STATE();
3907         verify_pe_header (&ctx);
3908         CHECK_STATE();
3909         verify_pe_optional_header (&ctx);
3910         CHECK_STATE();
3911         load_section_table (&ctx);
3912         CHECK_STATE();
3913         load_data_directories (&ctx);
3914         CHECK_STATE();
3915         verify_import_table (&ctx);
3916         CHECK_STATE();
3917         /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3918         verify_resources_table (&ctx);
3919
3920 cleanup:
3921         return cleanup_context (&ctx, error_list);
3922 }
3923
3924 gboolean
3925 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3926 {
3927         VerifyContext ctx;
3928
3929         if (!mono_verifier_is_enabled_for_image (image))
3930                 return TRUE;
3931
3932         init_verify_context (&ctx, image, error_list != NULL);
3933         ctx.stage = STAGE_CLI;
3934
3935         verify_cli_header (&ctx);
3936         CHECK_STATE();
3937         verify_metadata_header (&ctx);
3938         CHECK_STATE();
3939         verify_tables_schema (&ctx);
3940
3941 cleanup:
3942         return cleanup_context (&ctx, error_list);
3943 }
3944
3945
3946 /*
3947  * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3948  * Other verification checks are meant to be done lazily by the runtime. Those include:
3949  *      blob items (signatures, method headers, custom attributes, etc)
3950  *  type semantics related
3951  *  vtable related
3952  *  stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3953  * 
3954  * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3955  * operation still need more checking.
3956  */
3957 gboolean
3958 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3959 {
3960         VerifyContext ctx;
3961
3962         if (!mono_verifier_is_enabled_for_image (image))
3963                 return TRUE;
3964
3965         init_verify_context (&ctx, image, error_list != NULL);
3966         ctx.stage = STAGE_TABLES;
3967
3968         verify_tables_data (&ctx);
3969
3970         return cleanup_context (&ctx, error_list);
3971 }
3972
3973
3974 /*
3975  * Verifies all other constraints.
3976  */
3977 gboolean
3978 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3979 {
3980         VerifyContext ctx;
3981
3982         if (!mono_verifier_is_enabled_for_image (image))
3983                 return TRUE;
3984
3985         init_verify_context (&ctx, image, error_list != NULL);
3986         ctx.stage = STAGE_TABLES;
3987
3988         verify_typedef_table_full (&ctx);
3989         CHECK_STATE ();
3990         verify_field_table_full (&ctx);
3991         CHECK_STATE ();
3992         verify_method_table_full (&ctx);
3993         CHECK_STATE ();
3994         verify_memberref_table_full (&ctx);
3995         CHECK_STATE ();
3996         verify_cattr_table_full (&ctx);
3997         CHECK_STATE ();
3998         verify_field_marshal_table_full (&ctx);
3999         CHECK_STATE ();
4000         verify_decl_security_table_full (&ctx);
4001         CHECK_STATE ();
4002         verify_standalonesig_table_full (&ctx);
4003         CHECK_STATE ();
4004         verify_event_table_full (&ctx);
4005         CHECK_STATE ();
4006         verify_typespec_table_full (&ctx);
4007         CHECK_STATE ();
4008         verify_method_spec_table_full (&ctx);
4009         CHECK_STATE ();
4010         verify_tables_data_global_constraints_full (&ctx);
4011
4012 cleanup:
4013         return cleanup_context (&ctx, error_list);
4014 }
4015
4016 gboolean
4017 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4018 {
4019         VerifyContext ctx;
4020
4021         if (!mono_verifier_is_enabled_for_image (image))
4022                 return TRUE;
4023
4024         init_verify_context (&ctx, image, error_list != NULL);
4025         ctx.stage = STAGE_TABLES;
4026
4027         is_valid_field_signature (&ctx, offset);
4028         return cleanup_context (&ctx, error_list);
4029 }
4030
4031 gboolean
4032 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4033 {
4034         VerifyContext ctx;
4035         guint32 locals_token;
4036
4037         if (!mono_verifier_is_enabled_for_image (image))
4038                 return TRUE;
4039
4040         init_verify_context (&ctx, image, error_list != NULL);
4041         ctx.stage = STAGE_TABLES;
4042
4043         is_valid_method_header (&ctx, offset, &locals_token);
4044         if (locals_token) {
4045                 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
4046                 is_valid_standalonesig_blob (&ctx, sig_offset);
4047         }
4048
4049         return cleanup_context (&ctx, error_list);
4050 }
4051
4052 gboolean
4053 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4054 {
4055         VerifyContext ctx;
4056
4057         mono_error_init (error);
4058
4059         if (!mono_verifier_is_enabled_for_image (image))
4060                 return TRUE;
4061
4062         init_verify_context (&ctx, image, TRUE);
4063         ctx.stage = STAGE_TABLES;
4064
4065         is_valid_method_signature (&ctx, offset);
4066         /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4067         return cleanup_context_checked (&ctx, error);
4068 }
4069
4070 gboolean
4071 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4072 {
4073         VerifyContext ctx;
4074
4075         if (!mono_verifier_is_enabled_for_image (image))
4076                 return TRUE;
4077
4078         init_verify_context (&ctx, image, error_list != NULL);
4079         ctx.stage = STAGE_TABLES;
4080
4081         is_valid_memberref_method_signature (&ctx, offset);
4082         return cleanup_context (&ctx, error_list);
4083 }
4084
4085 gboolean
4086 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4087 {
4088         VerifyContext ctx;
4089
4090         if (!mono_verifier_is_enabled_for_image (image))
4091                 return TRUE;
4092
4093         init_verify_context (&ctx, image, error_list != NULL);
4094         ctx.stage = STAGE_TABLES;
4095
4096         is_valid_field_signature (&ctx, offset);
4097         return cleanup_context (&ctx, error_list);
4098 }
4099
4100 gboolean
4101 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4102 {
4103         VerifyContext ctx;
4104
4105         if (!mono_verifier_is_enabled_for_image (image))
4106                 return TRUE;
4107
4108         init_verify_context (&ctx, image, error_list != NULL);
4109         ctx.stage = STAGE_TABLES;
4110
4111         is_valid_standalonesig_blob (&ctx, offset);
4112         return cleanup_context (&ctx, error_list);
4113 }
4114
4115 gboolean
4116 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4117 {
4118         VerifyContext ctx;
4119
4120         if (!mono_verifier_is_enabled_for_image (image))
4121                 return TRUE;
4122
4123         init_verify_context (&ctx, image, error_list != NULL);
4124         ctx.stage = STAGE_TABLES;
4125         ctx.token = token;
4126
4127         is_valid_typespec_blob (&ctx, offset);
4128         return cleanup_context (&ctx, error_list);
4129 }
4130
4131 gboolean
4132 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4133 {
4134         VerifyContext ctx;
4135
4136         if (!mono_verifier_is_enabled_for_image (image))
4137                 return TRUE;
4138
4139         init_verify_context (&ctx, image, error_list != NULL);
4140         ctx.stage = STAGE_TABLES;
4141
4142         is_valid_methodspec_blob (&ctx, offset);
4143         return cleanup_context (&ctx, error_list);
4144 }
4145
4146 static void
4147 verify_user_string (VerifyContext *ctx, guint32 offset)
4148 {
4149         OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4150         guint32 entry_size, bytes;
4151
4152         if (heap_us.size < offset)
4153                 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4154
4155         if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4156                 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4157
4158         if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4159                 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4160
4161         entry_size += bytes;
4162
4163         if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4164                 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4165 }
4166
4167 gboolean
4168 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4169 {
4170         VerifyContext ctx;
4171
4172         if (!mono_verifier_is_enabled_for_image (image))
4173                 return TRUE;
4174
4175         init_verify_context (&ctx, image, error_list != NULL);
4176         ctx.stage = STAGE_TABLES;
4177
4178         verify_user_string (&ctx, offset);
4179
4180         return cleanup_context (&ctx, error_list);
4181 }
4182
4183 gboolean
4184 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4185 {
4186         VerifyContext ctx;
4187
4188         if (!mono_verifier_is_enabled_for_image (image))
4189                 return TRUE;
4190
4191         init_verify_context (&ctx, image, error_list != NULL);
4192         ctx.stage = STAGE_TABLES;
4193
4194         is_valid_cattr_blob (&ctx, offset);
4195
4196         return cleanup_context (&ctx, error_list);
4197 }
4198
4199 gboolean
4200 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4201 {
4202         VerifyContext ctx;
4203
4204         if (!mono_verifier_is_enabled_for_image (image))
4205                 return TRUE;
4206
4207         init_verify_context (&ctx, image, error_list != NULL);
4208         ctx.stage = STAGE_TABLES;
4209
4210         is_valid_cattr_content (&ctx, ctor, (const char*)data, size);
4211
4212         return cleanup_context (&ctx, error_list);
4213 }
4214
4215 gboolean
4216 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4217 {
4218         MonoMethodSignature *original_sig;
4219         if (!mono_verifier_is_enabled_for_image (image))
4220                 return TRUE;
4221
4222         original_sig = mono_method_signature (method);
4223         if (original_sig->call_convention == MONO_CALL_VARARG) {
4224                 if (original_sig->hasthis != signature->hasthis)
4225                         return FALSE;
4226                 if (original_sig->call_convention != signature->call_convention)
4227                         return FALSE;
4228                 if (original_sig->explicit_this != signature->explicit_this)
4229                         return FALSE;
4230                 if (original_sig->call_convention != signature->call_convention)
4231                         return FALSE;
4232                 if (original_sig->pinvoke != signature->pinvoke)
4233                         return FALSE;
4234                 if (original_sig->sentinelpos != signature->sentinelpos)
4235                         return FALSE;
4236         } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4237                 return FALSE;
4238         }
4239
4240         return TRUE;
4241 }
4242
4243 gboolean
4244 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4245 {
4246         MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
4247         guint32 data [MONO_TYPEREF_SIZE];
4248
4249         mono_error_init (error);
4250
4251         if (!mono_verifier_is_enabled_for_image (image))
4252                 return TRUE;
4253
4254         if (row >= table->rows) {
4255                 mono_error_set_bad_image (error, image, "Invalid typeref row %d - table has %d rows", row, table->rows);
4256                 return FALSE;
4257         }
4258
4259         mono_metadata_decode_row (table, row, data, MONO_TYPEREF_SIZE);
4260         if (!is_valid_coded_index_with_image (image, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4261                 mono_error_set_bad_image (error, image, "Invalid typeref row %d coded index 0x%08x", row, data [MONO_TYPEREF_SCOPE]);
4262                 return FALSE;
4263         }
4264
4265         if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4266                 mono_error_set_bad_image (error, image, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row);
4267                 return FALSE;
4268         }
4269
4270         if (!data [MONO_TYPEREF_NAME] || !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAME], FALSE)) {
4271                 mono_error_set_bad_image (error, image, "Invalid typeref row %d name token 0x%08x", row, data [MONO_TYPEREF_NAME]);
4272                 return FALSE;
4273         }
4274
4275         if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAMESPACE], FALSE)) {
4276                 mono_error_set_bad_image (error, image, "Invalid typeref row %d namespace token 0x%08x", row, data [MONO_TYPEREF_NAMESPACE]);
4277                 return FALSE;
4278         }
4279
4280         return TRUE;
4281 }
4282
4283 /*Perform additional verification including metadata ones*/
4284 gboolean
4285 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4286 {
4287         MonoMethod *declaration, *body;
4288         MonoMethodSignature *body_sig, *decl_sig;
4289         MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
4290         guint32 data [MONO_METHODIMPL_SIZE];
4291
4292         mono_error_init (error);
4293
4294         if (!mono_verifier_is_enabled_for_image (image))
4295                 return TRUE;
4296
4297         if (row >= table->rows) {
4298                 mono_error_set_bad_image (error, image, "Invalid methodimpl row %d - table has %d rows", row, table->rows);
4299                 return FALSE;
4300         }
4301
4302         mono_metadata_decode_row (table, row, data, MONO_METHODIMPL_SIZE);
4303
4304         body = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_BODY], NULL, error);
4305         if (!body)
4306                 return FALSE;
4307
4308         declaration = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_DECLARATION], NULL, error);
4309         if (!declaration)
4310                 return FALSE;
4311
4312         /* FIXME
4313         mono_class_setup_supertypes (class);
4314         if (!mono_class_has_parent (class, body->klass)) {
4315                 mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
4316                 return FALSE;
4317         }*/
4318
4319         if (!(body_sig = mono_method_signature_checked (body, error))) {
4320                 return FALSE;
4321         }
4322
4323         if (!(decl_sig = mono_method_signature_checked (declaration, error))) {
4324                 return FALSE;
4325         }
4326
4327         if (!mono_verifier_is_signature_compatible (decl_sig, body_sig)) {
4328                 mono_error_set_bad_image (error, image, "Invalid methodimpl body signature not compatible with declaration row %x", row);
4329                 return FALSE;
4330         }
4331
4332         return TRUE;
4333 }
4334
4335 #else
4336 gboolean
4337 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4338 {
4339         return TRUE;
4340 }
4341
4342 gboolean
4343 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4344 {
4345         return TRUE;
4346 }
4347
4348 gboolean
4349 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4350 {
4351         return TRUE;
4352 }
4353
4354 gboolean
4355 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4356 {
4357         return TRUE;
4358 }
4359
4360 gboolean
4361 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4362 {
4363         return TRUE;
4364 }
4365
4366 gboolean
4367 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4368 {
4369         return TRUE;
4370 }
4371
4372 gboolean
4373 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4374 {
4375         mono_error_init (error);
4376         return TRUE;
4377 }
4378
4379 gboolean
4380 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4381 {
4382         return TRUE;
4383 }
4384
4385 gboolean
4386 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4387 {
4388         return TRUE;
4389 }
4390
4391 gboolean
4392 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4393 {
4394         return TRUE;
4395 }
4396
4397 gboolean
4398 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4399 {
4400         return TRUE;
4401 }
4402
4403 gboolean
4404 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4405 {
4406         return TRUE;
4407 }
4408
4409 gboolean
4410 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4411 {
4412         return TRUE;
4413 }
4414
4415 gboolean
4416 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4417 {
4418         return TRUE;
4419 }
4420
4421
4422 gboolean
4423 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4424 {
4425         mono_error_init (error);
4426         return TRUE;
4427 }
4428
4429 gboolean
4430 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4431 {
4432         mono_error_init (error);
4433         return TRUE;
4434 }
4435
4436 gboolean
4437 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4438 {
4439         return TRUE;
4440 }
4441
4442 gboolean
4443 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4444 {
4445         return TRUE;
4446 }
4447
4448 #endif /* DISABLE_VERIFIER */