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