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