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