[verifier] Check methodimpl table for duplicated. Fixes #11696
[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 sig = 0;
1518         unsigned param_count = 0, i;
1519         const char *ptr = *_ptr;
1520
1521         if (!safe_read8 (sig, ptr, end))
1522                 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1523
1524         if (sig != 0x08 && sig != 0x28)
1525                 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1526
1527         if (!safe_read_cint (param_count, ptr, end))
1528                 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1529
1530         if (!parse_custom_mods (ctx, &ptr, end))
1531                 return FALSE;
1532
1533         if (!parse_type (ctx, &ptr, end))
1534                 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1535
1536         for (i = 0; i < param_count; ++i) {
1537                 if (!parse_custom_mods (ctx, &ptr, end))
1538                         FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1539                 if (!parse_type (ctx, &ptr, end))
1540                         FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1541         }
1542
1543         *_ptr = ptr;
1544         return TRUE;
1545 }
1546
1547 static gboolean
1548 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1549 {
1550         const char *ptr = *_ptr;
1551         unsigned signature = 0;
1552
1553         if (!safe_read8 (signature, ptr, end))
1554                 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1555
1556         if (signature != 0x06)
1557                 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1558
1559         if (!parse_custom_mods (ctx, &ptr, end))
1560                 return FALSE;
1561
1562         if (safe_read8 (signature, ptr, end)) {
1563                 if (signature != MONO_TYPE_BYREF)
1564                         --ptr;
1565         }
1566         *_ptr = ptr;
1567
1568         return parse_type (ctx, _ptr, end);
1569 }
1570
1571 static gboolean
1572 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1573 {
1574         unsigned sig = 0;
1575         unsigned locals_count = 0, i;
1576         const char *ptr = *_ptr;        
1577
1578         if (!safe_read8 (sig, ptr, end))
1579                 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1580
1581         if (sig != 0x07)
1582                 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1583
1584         if (!safe_read_cint (locals_count, ptr, end))
1585                 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1586
1587         /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1588         if (locals_count == 0)
1589                 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1590         */
1591
1592         for (i = 0; i < locals_count; ++i) {
1593                 if (!safe_read8 (sig, ptr, end))
1594                         FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1595
1596                 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1597                         if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1598                                 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1599                         if (!safe_read8 (sig, ptr, end))
1600                                 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1601                 }
1602
1603                 if (sig == MONO_TYPE_BYREF) {
1604                         if (!safe_read8 (sig, ptr, end))
1605                                 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1606                         if (sig == MONO_TYPE_TYPEDBYREF)
1607                                 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1608                 }
1609
1610                 if (sig == MONO_TYPE_TYPEDBYREF)
1611                         continue;
1612
1613                 --ptr;
1614
1615                 if (!parse_type (ctx, &ptr, end))
1616                         FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1617         }
1618
1619         *_ptr = ptr;
1620         return TRUE;
1621 }
1622
1623 static gboolean
1624 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1625 {
1626         guint32 size = 0;
1627         unsigned signature = 0;
1628         const char *ptr = NULL, *end;
1629
1630         if (!decode_signature_header (ctx, offset, &size, &ptr))
1631                 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1632         end = ptr + size;
1633
1634         if (!safe_read8 (signature, ptr, end))
1635                 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1636
1637         if (signature != 6)
1638                 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1639         --ptr;
1640
1641         return parse_field (ctx, &ptr, end);
1642 }
1643
1644 static gboolean
1645 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1646 {
1647         guint32 size = 0;
1648         const char *ptr = NULL, *end;
1649
1650         if (!decode_signature_header (ctx, offset, &size, &ptr))
1651                 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1652         end = ptr + size;
1653
1654         return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1655 }
1656
1657 static gboolean
1658 is_valid_memberref_method_signature (VerifyContext *ctx, guint32 offset)
1659 {
1660         guint32 size = 0;
1661         const char *ptr = NULL, *end;
1662
1663         if (!decode_signature_header (ctx, offset, &size, &ptr))
1664                 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1665         end = ptr + size;
1666
1667         return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1668 }
1669
1670
1671 static gboolean
1672 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1673 {
1674         guint32 size = 0;
1675         unsigned signature = 0;
1676         const char *ptr = NULL, *end;
1677
1678         if (!decode_signature_header (ctx, offset, &size, &ptr))
1679                 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1680         end = ptr + size;
1681
1682         if (!safe_read8 (signature, ptr, end))
1683                 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1684         --ptr;
1685
1686         if (signature == 0x06)
1687                 return parse_field (ctx, &ptr, end);
1688
1689         return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1690 }
1691
1692 static gboolean
1693 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1694 {
1695         guint32 size = 0;
1696         unsigned prolog = 0;
1697         const char *ptr = NULL, *end;
1698
1699         if (!offset)
1700                 return TRUE;
1701
1702         if (!decode_signature_header (ctx, offset, &size, &ptr))
1703                 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1704         end = ptr + size;
1705
1706         if (!safe_read16 (prolog, ptr, end))
1707                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1708
1709         if (prolog != 1)
1710                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1711
1712         return TRUE;
1713 }
1714
1715 static gboolean
1716 is_valid_cattr_type (MonoType *type)
1717 {
1718         MonoClass *klass;
1719
1720         if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1721                 return TRUE;
1722
1723         if (type->type == MONO_TYPE_VALUETYPE) {
1724                 klass = mono_class_from_mono_type (type);
1725                 return klass && klass->enumtype;
1726         }
1727
1728         if (type->type == MONO_TYPE_CLASS)
1729                 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1730
1731         return FALSE;
1732 }
1733
1734 static gboolean
1735 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1736 {
1737         guint32 size = 0;
1738         const char *ptr = *_ptr;
1739
1740         *str_start = NULL;
1741         *str_len = 0;
1742
1743         if (ptr >= end)
1744                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1745
1746         /*NULL string*/
1747         if (*ptr == (char)0xFF) {
1748                 *_ptr = ptr + 1;
1749                 return TRUE;
1750         }
1751
1752         if (!safe_read_cint (size, ptr, end))
1753                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1754
1755         if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1756                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1757
1758         *str_start = ptr;
1759         *str_len = size;
1760
1761         *_ptr = ptr + size;
1762         return TRUE;
1763 }
1764
1765 static gboolean
1766 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1767 {
1768         const char *dummy_str;
1769         guint32 dummy_int;
1770         return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1771 }
1772
1773 static MonoClass*
1774 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1775 {
1776         MonoType *type;
1777         MonoClass *klass;
1778         const char *str_start = NULL;
1779         const char *ptr = *_ptr;
1780         char *enum_name;
1781         guint32 str_len = 0;
1782
1783         if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1784                 return NULL;
1785
1786         /*NULL or empty string*/
1787         if (str_start == NULL || str_len == 0) {
1788                 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1789                 return NULL;
1790         }
1791
1792         enum_name = (char *)g_memdup (str_start, str_len + 1);
1793         enum_name [str_len] = 0;
1794         type = mono_reflection_type_from_name (enum_name, ctx->image);
1795         if (!type) {
1796                 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1797                 g_free (enum_name);
1798                 return NULL;
1799         }
1800         g_free (enum_name);
1801
1802         klass = mono_class_from_mono_type (type);
1803         if (!klass || !klass->enumtype) {
1804                 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1805                 return NULL;
1806         }
1807
1808         *_ptr = ptr;
1809         return klass;
1810 }
1811
1812 static gboolean
1813 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1814 {
1815         MonoClass *klass;
1816         const char *ptr = *_ptr;
1817         int elem_size = 0;
1818         guint32 element_count, i;
1819         int type;
1820
1821         klass = mono_type->data.klass;
1822         type = mono_type->type;
1823
1824 handle_enum:
1825         switch (type) {
1826         case MONO_TYPE_BOOLEAN:
1827         case MONO_TYPE_I1:
1828         case MONO_TYPE_U1:
1829                 elem_size = 1;
1830                 break;
1831         case MONO_TYPE_I2:
1832         case MONO_TYPE_U2:
1833         case MONO_TYPE_CHAR:
1834                 elem_size = 2;
1835                 break;
1836         case MONO_TYPE_I4:
1837         case MONO_TYPE_U4:
1838         case MONO_TYPE_R4:
1839                 elem_size = 4;
1840                 break;
1841         case MONO_TYPE_I8:
1842         case MONO_TYPE_U8:
1843         case MONO_TYPE_R8:
1844                 elem_size = 8;
1845                 break;
1846
1847         case MONO_TYPE_STRING:
1848                 *_ptr = ptr;
1849                 return is_valid_ser_string (ctx, _ptr, end);
1850
1851         case MONO_TYPE_OBJECT: {
1852                 unsigned sub_type = 0;
1853                 if (!safe_read8 (sub_type, ptr, end))
1854                         FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1855
1856                 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1857                         type = sub_type;
1858                         goto handle_enum;
1859                 }
1860                 if (sub_type == MONO_TYPE_ENUM) {
1861                         klass = get_enum_by_encoded_name (ctx, &ptr, end);
1862                         if (!klass)
1863                                 return FALSE;
1864
1865                         klass = klass->element_class;
1866                         type = klass->byval_arg.type;
1867                         goto handle_enum;
1868                 }
1869                 if (sub_type == 0x50) { /*Type*/
1870                         *_ptr = ptr;
1871                         return is_valid_ser_string (ctx, _ptr, end);
1872                 }
1873                 if (sub_type == MONO_TYPE_SZARRAY) {
1874                         MonoType simple_type = {{0}};
1875                         unsigned etype = 0;
1876                         if (!safe_read8 (etype, ptr, end))
1877                                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1878
1879                         if (etype == MONO_TYPE_ENUM) {
1880                                 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1881                                 if (!klass)
1882                                         return FALSE;
1883                         } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
1884                                 klass = mono_defaults.systemtype_class;
1885                         } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1886                                 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : (MonoTypeEnum)etype;
1887                                 klass = mono_class_from_mono_type (&simple_type);
1888                         } else
1889                                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1890
1891                         type = MONO_TYPE_SZARRAY;
1892                         goto handle_enum;
1893                 }
1894                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1895         }
1896
1897
1898         case MONO_TYPE_CLASS:
1899                 if (klass != mono_defaults.systemtype_class)
1900                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1901                 *_ptr = ptr;
1902                 return is_valid_ser_string (ctx, _ptr, end);
1903
1904         case MONO_TYPE_VALUETYPE:
1905                 if (!klass || !klass->enumtype)
1906                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1907
1908                 klass = klass->element_class;
1909                 type = klass->byval_arg.type;
1910                 goto handle_enum;
1911
1912         case MONO_TYPE_SZARRAY:
1913                 mono_type = &klass->byval_arg;
1914                 if (!is_valid_cattr_type (mono_type))
1915                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1916                 if (!safe_read32 (element_count, ptr, end))
1917                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1918                 if (element_count == 0xFFFFFFFFu) {
1919                         *_ptr = ptr;
1920                         return TRUE;
1921                 }
1922                 for (i = 0; i < element_count; ++i) {
1923                         if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1924                                 return FALSE;
1925                 }
1926                 *_ptr = ptr;
1927                 return TRUE;
1928         default:
1929                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1930         }
1931
1932         if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1933                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1934         *_ptr = ptr + elem_size;
1935         return TRUE;
1936 }
1937
1938 static gboolean
1939 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1940 {
1941         MonoError error;
1942         unsigned prolog = 0;
1943         const char *end;
1944         MonoMethodSignature *sig;
1945         int args, i;
1946         unsigned num_named;
1947
1948         if (!ctor)
1949                 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1950
1951         sig = mono_method_signature_checked (ctor, &error);
1952         if (!mono_error_ok (&error)) {
1953                 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1954                 mono_error_cleanup (&error);
1955                 return FALSE;
1956         }
1957
1958         if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1959                 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1960
1961         end = ptr + size;
1962
1963         if (!safe_read16 (prolog, ptr, end))
1964                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1965
1966         if (prolog != 1)
1967                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1968
1969         args = sig->param_count;
1970         for (i = 0; i < args; ++i) {
1971                 MonoType *arg_type = sig->params [i];
1972                 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1973                         return FALSE;
1974         }
1975
1976         if (!safe_read16 (num_named, ptr, end))
1977                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1978
1979         for (i = 0; i < num_named; ++i) {
1980                 MonoType *type, simple_type = {{0}};
1981                 unsigned kind;
1982
1983                 if (!safe_read8 (kind, ptr, end))
1984                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1985                 if (kind != 0x53 && kind != 0x54)
1986                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1987                 if (!safe_read8 (kind, ptr, end))
1988                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1989
1990                 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1991                         simple_type.type = (MonoTypeEnum)kind;
1992                         type = &simple_type;
1993                 } else if (kind == MONO_TYPE_ENUM) {
1994                         MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1995                         if (!klass)
1996                                 return FALSE;
1997                         type = &klass->byval_arg;
1998                 } else if (kind == 0x50) {
1999                         type = &mono_defaults.systemtype_class->byval_arg;
2000                 } else if (kind == 0x51) {
2001                         type = &mono_defaults.object_class->byval_arg;
2002                 } else if (kind == MONO_TYPE_SZARRAY) {
2003                         MonoClass *klass;
2004                         unsigned etype = 0;
2005                         if (!safe_read8 (etype, ptr, end))
2006                                 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
2007
2008                         if (etype == MONO_TYPE_ENUM) {
2009                                 klass = get_enum_by_encoded_name (ctx, &ptr, end);
2010                                 if (!klass)
2011                                         return FALSE;
2012                         } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
2013                                 klass = mono_defaults.systemtype_class;
2014                         } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
2015                                 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : (MonoTypeEnum)etype;
2016                                 klass = mono_class_from_mono_type (&simple_type);
2017                         } else
2018                                 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
2019
2020                         type = &mono_array_class_get (klass, 1)->byval_arg;
2021                 } else {
2022                         FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
2023                 }
2024
2025                 if (!is_valid_ser_string (ctx, &ptr, end))
2026                         return FALSE;
2027
2028                 if (!is_valid_fixed_param (ctx, type, &ptr, end))
2029                         return FALSE;
2030
2031         }
2032
2033         return TRUE;
2034 }
2035
2036 static gboolean
2037 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
2038 {
2039         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2040         //TODO do proper verification
2041         return blob.size >= 1 && blob.size - 1 >= offset;
2042 }
2043
2044 static gboolean
2045 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
2046 {
2047         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2048         //TODO do proper verification
2049         return blob.size >= 1 && blob.size - 1 >= offset;
2050 }
2051
2052 static gboolean
2053 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2054 {
2055         guint32 size = 0;
2056         unsigned signature = 0;
2057         const char *ptr = NULL, *end;
2058
2059         if (!decode_signature_header (ctx, offset, &size, &ptr))
2060                 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2061         end = ptr + size;
2062
2063         if (!safe_read8 (signature, ptr, end))
2064                 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2065
2066         --ptr;
2067         if (signature == 0x07)
2068                 return parse_locals_signature (ctx, &ptr, end);
2069
2070         /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2071         if (signature == 0x06)
2072                 return parse_field (ctx, &ptr, end);
2073
2074         return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2075 }
2076
2077 static gboolean
2078 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2079 {
2080         guint32 size = 0;
2081         const char *ptr = NULL, *end;
2082
2083         if (!decode_signature_header (ctx, offset, &size, &ptr))
2084                 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2085         end = ptr + size;
2086
2087         return parse_property_signature (ctx, &ptr, end);
2088 }
2089
2090 static gboolean
2091 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2092 {
2093         guint32 size = 0;
2094         const char *ptr = NULL, *end;
2095         unsigned type = 0;
2096         
2097         if (!decode_signature_header (ctx, offset, &size, &ptr))
2098                 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2099         end = ptr + size;
2100
2101         if (!parse_custom_mods (ctx, &ptr, end))
2102                 return FALSE;
2103
2104         if (!safe_read8 (type, ptr, end))
2105                 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2106
2107         if (type == MONO_TYPE_BYREF) {
2108                 if (!safe_read8 (type, ptr, end)) 
2109                         FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2110                 if (type == MONO_TYPE_TYPEDBYREF)
2111                         FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2112         }
2113         
2114         if (type == MONO_TYPE_TYPEDBYREF)
2115                 return TRUE;
2116
2117         --ptr;
2118         return parse_type (ctx, &ptr, end);
2119 }
2120
2121 static gboolean
2122 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2123 {
2124         guint32 size = 0;
2125         const char *ptr = NULL, *end;
2126         unsigned type = 0;
2127         unsigned count = 0, i;
2128
2129         if (!decode_signature_header (ctx, offset, &size, &ptr))
2130                 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2131         end = ptr + size;
2132
2133         if (!safe_read8 (type, ptr, end))
2134                 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2135
2136         if (type != 0x0A)
2137                 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2138
2139         if (!safe_read_cint (count, ptr, end))
2140                 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2141
2142         if (!count)
2143                 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2144
2145         for (i = 0; i < count; ++i) {
2146                 if (!parse_custom_mods (ctx, &ptr, end))
2147                         return FALSE;
2148                 if (!parse_type (ctx, &ptr, end))
2149                         FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2150         }
2151         return TRUE;
2152 }
2153
2154 static gboolean
2155 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2156 {
2157         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2158         guint32 entry_size, bytes;
2159
2160         if (blob.size < offset)
2161                 return FALSE;
2162
2163         if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2164                 return FALSE;
2165
2166         if (entry_size < minsize)
2167                 return FALSE;
2168
2169         if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2170                 return FALSE;
2171         entry_size += bytes;
2172
2173         return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2174 }
2175
2176 static gboolean
2177 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2178 {
2179         OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2180         guint32 size, entry_size, bytes;
2181
2182         if (blob.size < offset)
2183                 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2184         
2185         if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2186                 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2187
2188         if (type == MONO_TYPE_STRING) {
2189                 //String is encoded as: compressed_int:len len *bytes
2190                 offset += bytes;
2191
2192                 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2193                         FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));  
2194
2195                 return TRUE;
2196         }
2197
2198         switch (type) {
2199         case MONO_TYPE_BOOLEAN:
2200         case MONO_TYPE_I1:
2201         case MONO_TYPE_U1:
2202                 size = 1;
2203                 break;
2204         case MONO_TYPE_CHAR:
2205         case MONO_TYPE_I2:
2206         case MONO_TYPE_U2:
2207                 size = 2;
2208                 break;
2209         case MONO_TYPE_I4:
2210         case MONO_TYPE_U4:
2211         case MONO_TYPE_R4:
2212         case MONO_TYPE_CLASS:
2213                 size = 4;
2214                 break;
2215
2216         case MONO_TYPE_I8:
2217         case MONO_TYPE_U8:
2218         case MONO_TYPE_R8:
2219                 size = 8;
2220                 break;
2221         default:
2222                 g_assert_not_reached ();
2223         }
2224
2225         if (size != entry_size)
2226                 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2227
2228         offset += bytes;
2229
2230         if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2231                 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2232
2233         if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2234                 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2235         return TRUE;
2236 }
2237
2238 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2239 //only 0x01, 0x40 and 0x80 are allowed
2240 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2241
2242 static gboolean
2243 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2244 {
2245         unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2246         unsigned header = 0;
2247         unsigned fat_header = 0, size = 0, max_stack;
2248         const char *ptr = NULL, *end;
2249
2250         *locals_token = 0;
2251
2252         if (offset == INVALID_ADDRESS)
2253                 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2254
2255         ptr = ctx->data + offset;
2256         end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2257
2258         if (!safe_read8 (header, ptr, end))
2259                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2260
2261         switch (header & 0x3) {
2262         case 0:
2263         case 1:
2264                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2265         case 2:
2266                 header >>= 2;
2267                 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end)) 
2268                         FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2269                 return TRUE;
2270         }
2271         //FAT HEADER
2272         --ptr;
2273         if (!safe_read16 (fat_header, ptr, end))
2274                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2275
2276         size = (fat_header >> 12) & 0xF;
2277         if (size != 3)
2278                 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2279
2280         if (!safe_read16 (max_stack, ptr, end))
2281                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2282
2283         if (!safe_read32 (code_size, ptr, end))
2284                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2285
2286         if (!safe_read32 (local_vars_tok, ptr, end))
2287                 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2288
2289         if (local_vars_tok) {
2290                 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2291                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2292                 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)   
2293                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2294                 if (!(local_vars_tok & 0xFFFFFF))
2295                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature with zero index"));
2296                 *locals_token = local_vars_tok & 0xFFFFFF;
2297         }
2298
2299         if (fat_header & FAT_HEADER_INVALID_FLAGS)
2300                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2301
2302         if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2303                 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2304
2305         if (!(fat_header & 0x08))
2306                 return TRUE;
2307
2308         ptr += code_size;
2309
2310         do {
2311                 unsigned section_header = 0, section_size = 0;
2312                 gboolean is_fat;
2313
2314                 ptr = dword_align (ptr);
2315                 if (!safe_read32 (section_header, ptr, end))
2316                         FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2317
2318                 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2319                         FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2320                         
2321                 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2322                 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2323
2324                 if (section_size < 4)
2325                         FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2326
2327                 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2328                         FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2329
2330                 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2331                         guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2332                         /*
2333                                 LAMEIMPL: MS emits section_size without accounting for header size.
2334                                 Mono does as the spec says. section_size is header + section
2335                                 MS's peverify happily accepts both. 
2336                         */
2337                         if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2338                                 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)));
2339
2340                         /* only verify the class token is verified as the rest is done by the IL verifier*/
2341                         for (i = 0; i < clauses; ++i) {
2342                                 unsigned flags = *(unsigned char*)ptr;
2343                                 unsigned class_token = 0;
2344                                 ptr += (is_fat ? 20 : 8);
2345                                 if (!safe_read32 (class_token, ptr, end))
2346                                         FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2347                                 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2348                                         guint table = mono_metadata_token_table (class_token);
2349                                         if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2350                                                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2351                                         if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2352                                                 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2353                                 }
2354                         }
2355                 }
2356
2357                 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2358                         break;
2359         } while (1);
2360         return TRUE;
2361 }
2362
2363 static void
2364 verify_module_table (VerifyContext *ctx)
2365 {
2366         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2367         guint32 data [MONO_MODULE_SIZE];
2368
2369         if (table->rows != 1)
2370                 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2371
2372         mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2373
2374         if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2375                 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2376
2377         if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2378                 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2379
2380         if (data [MONO_MODULE_ENC] != 0)
2381                 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2382
2383         if (data [MONO_MODULE_ENCBASE] != 0)
2384                 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2385 }
2386
2387 static void
2388 verify_typeref_table (VerifyContext *ctx)
2389 {
2390         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2391         MonoError error;
2392         guint32 i;
2393
2394         for (i = 0; i < table->rows; ++i) {
2395                 mono_verifier_verify_typeref_row (ctx->image, i, &error);
2396                 add_from_mono_error (ctx, &error);
2397         }
2398 }
2399
2400 /*bits 9,11,14,15,19,21,24-31 */
2401 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2402 static void
2403 verify_typedef_table (VerifyContext *ctx)
2404 {
2405         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2406         guint32 data [MONO_TYPEDEF_SIZE];
2407         guint32 fieldlist = 1, methodlist = 1, visibility;
2408         int i;
2409
2410         if (table->rows == 0)
2411                 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2412
2413         for (i = 0; i < table->rows; ++i) {
2414                 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2415                 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2416                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2417
2418                 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2419                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2420
2421                 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2422                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2423
2424                 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2425                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2426
2427                 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2428                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2429
2430                 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2431                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2432
2433                 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2434                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2435
2436                 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2437                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2438
2439                 if (data [MONO_TYPEDEF_EXTENDS] && !get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2440                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d zero coded extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2441
2442                 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2443                 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2444                         search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2445                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2446
2447                 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2448                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2449
2450                 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2451                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2452
2453                 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2454                         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));
2455
2456                 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2457                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2458
2459                 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2460                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2461
2462                 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2463                         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));
2464
2465                 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2466                 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2467         }
2468 }
2469
2470 static void
2471 verify_typedef_table_full (VerifyContext *ctx)
2472 {
2473         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2474         guint32 data [MONO_TYPEDEF_SIZE];
2475         int i;
2476
2477         if (table->rows == 0)
2478                 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2479
2480         for (i = 0; i < table->rows; ++i) {
2481                 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2482
2483                 if (i == 0) {
2484                         /*XXX it's ok if <module> extends object, or anything at all, actually. */
2485                         /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2486                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2487                         */
2488                         continue;
2489                 }
2490
2491                 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2492                         if (data [MONO_TYPEDEF_EXTENDS])
2493                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2494                 } else {
2495                         gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2496                         gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2497
2498                         if (is_sys_obj) {
2499                                 if (has_parent)
2500                                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2501                         } else {
2502                                 if (!has_parent) {
2503                                         ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2504                                 }
2505                         }
2506                 }
2507         }
2508 }
2509
2510 /*bits 3,11,14 */
2511 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2512 static void
2513 verify_field_table (VerifyContext *ctx)
2514 {
2515         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2516         guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2517         int i;
2518
2519         module_field_list = (guint32)-1;
2520         if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2521                 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2522                 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2523         }
2524         
2525         for (i = 0; i < table->rows; ++i) {
2526                 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2527                 flags = data [MONO_FIELD_FLAGS];
2528
2529                 if (flags & INVALID_FIELD_FLAG_BITS)
2530                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2531
2532                 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)         
2533                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2534
2535                 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2536                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2537
2538                 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2539                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2540
2541                 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2542                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2543
2544                 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2545                                 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2546                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2547
2548                 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2549                                 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2550                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2551
2552                 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2553                                 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2554                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2555
2556                 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2557                                 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2558                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2559
2560                 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2561                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2562
2563                 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2564                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2565
2566                 //TODO verify contant flag
2567
2568                 if (i + 1 < module_field_list) {
2569                         guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2570                         if (!(flags & FIELD_ATTRIBUTE_STATIC))
2571                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2572                         if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2573                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2574                 }
2575         }
2576 }
2577
2578 static void
2579 verify_field_table_full (VerifyContext *ctx)
2580 {
2581         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2582         guint32 data [MONO_FIELD_SIZE];
2583         int i;
2584         
2585         for (i = 0; i < table->rows; ++i) {
2586                 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2587
2588                 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2589                         ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2590         }
2591 }
2592
2593 /*bits 8,9,10,11,13,14,15*/
2594 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2595 static void
2596 verify_method_table (VerifyContext *ctx)
2597 {
2598         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2599         guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2600         guint32 paramlist = 1;
2601         gboolean is_ctor, is_cctor;
2602         const char *name;
2603         int i;
2604
2605         module_method_list = (guint32)-1;
2606         if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2607                 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2608                 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2609         }
2610
2611         for (i = 0; i < table->rows; ++i) {
2612                 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2613                 rva = data [MONO_METHOD_RVA];
2614                 implflags = data [MONO_METHOD_IMPLFLAGS];
2615                 flags = data [MONO_METHOD_FLAGS];
2616                 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2617                 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2618                 
2619
2620                 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2621                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2622
2623                 if (access == 0x7)
2624                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2625
2626                 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2627                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2628
2629                 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2630                 is_ctor = !strcmp (".ctor", name);
2631                 is_cctor = !strcmp (".cctor", name);
2632
2633                 if ((is_ctor || is_cctor) &&
2634                         search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2635                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2636
2637                 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2638                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2639                 
2640                 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2641                         if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2642                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2643                         if (flags & METHOD_ATTRIBUTE_FINAL)
2644                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2645                         if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2646                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2647                 }
2648
2649                 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2650                         ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2651
2652                 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2653                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2654
2655                 //XXX no checks against cas stuff 10,11,12,13)
2656
2657                 //TODO check iface with .ctor (15,16)
2658
2659                 if (i + 1 < module_method_list) {
2660                         if (!(flags & METHOD_ATTRIBUTE_STATIC))
2661                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2662                         if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2663                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2664                         if (access == METHOD_ATTRIBUTE_FAMILY || access == METHOD_ATTRIBUTE_FAM_AND_ASSEM || access == METHOD_ATTRIBUTE_FAM_OR_ASSEM)
2665                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public, Private or Assembly", i));
2666                 }
2667
2668                 //TODO check valuetype for synchronized
2669
2670                 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2671                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2672
2673                 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2674                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2675                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2676                         if (!(flags & METHOD_ATTRIBUTE_STATIC))
2677                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2678                 }
2679
2680                 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && 
2681                                 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2682                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2683
2684                 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2685                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2686
2687                 //TODO check signature contents
2688
2689                 if (rva) {
2690                         if ((flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) || (implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2691                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is either Abstract, InternalCall or PinvokeImpl", i));
2692                         if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2693                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2694                 } else {
2695                         if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2696                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2697                 }
2698
2699                 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2700                         if (rva)
2701                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2702                         if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2703                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2704                 }
2705                 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2706                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2707
2708                 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2709                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2710
2711                 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2712                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2713
2714                 if (data [MONO_METHOD_PARAMLIST] == 0)
2715                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2716
2717                 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2718                         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));
2719
2720                 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2721                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2722
2723                 paramlist = data [MONO_METHOD_PARAMLIST];
2724
2725         }
2726 }
2727
2728 static void
2729 verify_method_table_full (VerifyContext *ctx)
2730 {
2731         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2732         guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2733         int i;
2734
2735         for (i = 0; i < table->rows; ++i) {
2736                 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2737                 rva = data [MONO_METHOD_RVA];
2738
2739                 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2740                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2741
2742                 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2743                         ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2744         }
2745 }
2746
2747 static guint32
2748 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2749 {
2750         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2751         guint32 row = *current_method;
2752         guint32 paramlist, tmp;
2753
2754
2755         paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2756         while (row < table->rows) {
2757                 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2758                 if (tmp > paramlist) {
2759                         *current_method = row;
2760                         return tmp - paramlist;
2761                 }
2762                 ++row;
2763         }
2764
2765         /*no more methods, all params apply to the last one*/
2766         *current_method = table->rows;
2767         return (guint32)-1;
2768 }
2769
2770
2771 #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))
2772 static void
2773 verify_param_table (VerifyContext *ctx)
2774 {
2775         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2776         guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2777         gboolean first_param = TRUE;
2778         int i;
2779
2780         if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2781                 if (table->rows > 0)
2782                         ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2783                 return;
2784         }
2785         
2786         remaining_params = get_next_param_count (ctx, &current_method);
2787
2788         for (i = 0; i < table->rows; ++i) {
2789                 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2790                 flags = data [MONO_PARAM_FLAGS];
2791
2792                 if (flags & INVALID_PARAM_FLAGS_BITS)
2793                         ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2794
2795                 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2796                         if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2797                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2798                 } else {
2799                         if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2800                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2801                 }
2802
2803                 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)
2804                         ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2805
2806                 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2807                         ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2808
2809                 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2810                                 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2811
2812                 first_param = FALSE;
2813                 sequence = data [MONO_PARAM_SEQUENCE];
2814                 if (--remaining_params == 0) {
2815                         remaining_params = get_next_param_count (ctx, &current_method);
2816                         first_param = TRUE;
2817                 }
2818         }
2819 }
2820
2821 static void
2822 verify_interfaceimpl_table (VerifyContext *ctx)
2823 {
2824         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2825         guint32 data [MONO_INTERFACEIMPL_SIZE];
2826         int i;
2827
2828         for (i = 0; i < table->rows; ++i) {
2829                 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2830                 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2831                         ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_INTERFACEIMPL_CLASS]));
2832
2833                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2834                         ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2835
2836                 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2837                         ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2838         }
2839 }
2840
2841 static void
2842 verify_memberref_table (VerifyContext *ctx)
2843 {
2844         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2845         guint32 data [MONO_MEMBERREF_SIZE];
2846         int i;
2847
2848         for (i = 0; i < table->rows; ++i) {
2849                 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2850
2851                 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2852                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2853
2854                 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2855                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2856
2857                 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2858                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2859
2860                 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2861                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2862         }
2863 }
2864
2865
2866 static void
2867 verify_memberref_table_full (VerifyContext *ctx)
2868 {
2869         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2870         guint32 data [MONO_MEMBERREF_SIZE];
2871         int i;
2872
2873         for (i = 0; i < table->rows; ++i) {
2874                 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2875
2876                 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2877                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field  0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2878         }
2879 }
2880
2881 static void
2882 verify_constant_table (VerifyContext *ctx)
2883 {
2884         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2885         guint32 data [MONO_CONSTANT_SIZE], type;
2886         int i;
2887
2888         for (i = 0; i < table->rows; ++i) {
2889                 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2890                 type = data [MONO_CONSTANT_TYPE];
2891
2892                 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2893                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2894
2895                 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2896                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2897
2898                 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2899                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2900
2901                 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2902                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2903         }
2904 }
2905
2906 static void
2907 verify_cattr_table (VerifyContext *ctx)
2908 {
2909         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2910         guint32 data [MONO_CUSTOM_ATTR_SIZE];
2911         int i;
2912
2913         for (i = 0; i < table->rows; ++i) {
2914                 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2915
2916                 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2917                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2918
2919                 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]))
2920                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Type field 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2921
2922                 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2923                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2924         }
2925 }
2926
2927 static void
2928 verify_cattr_table_full (VerifyContext *ctx)
2929 {
2930         MonoError error;
2931         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2932         MonoMethod *ctor;
2933         const char *ptr;
2934         guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2935         int i;
2936
2937         for (i = 0; i < table->rows; ++i) {
2938                 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2939
2940                 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2941                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2942
2943                 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2944                 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2945                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2946                         mtoken |= MONO_TOKEN_METHOD_DEF;
2947                         break;
2948                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2949                         mtoken |= MONO_TOKEN_MEMBER_REF;
2950                         break;
2951                 default:
2952                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2953                 }
2954
2955                 ctor = mono_get_method_checked (ctx->image, mtoken, NULL, NULL, &error);
2956
2957                 if (!ctor) {
2958                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Could not load ctor due to %s", i, mono_error_get_message (&error)));
2959                         mono_error_cleanup (&error);
2960                 }
2961
2962                 /*This can't fail since this is checked in is_valid_cattr_blob*/
2963                 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2964
2965                 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2966                         ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2967         }
2968 }
2969
2970 static void
2971 verify_field_marshal_table (VerifyContext *ctx)
2972 {
2973         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2974         guint32 data [MONO_FIELD_MARSHAL_SIZE];
2975         int i;
2976
2977         for (i = 0; i < table->rows; ++i) {
2978                 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2979
2980                 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2981                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2982
2983                 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2984                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2985
2986                 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2987                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2988
2989                 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2990                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2991         }
2992 }
2993
2994 static void
2995 verify_field_marshal_table_full (VerifyContext *ctx)
2996 {
2997         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2998         guint32 data [MONO_FIELD_MARSHAL_SIZE];
2999         int i;
3000
3001         for (i = 0; i < table->rows; ++i) {
3002                 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
3003
3004                 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
3005                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
3006         }
3007 }
3008
3009 static void
3010 verify_decl_security_table (VerifyContext *ctx)
3011 {
3012         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3013         guint32 data [MONO_DECL_SECURITY_SIZE];
3014         int i;
3015
3016         for (i = 0; i < table->rows; ++i) {
3017                 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3018
3019                 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3020                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
3021
3022                 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3023                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
3024
3025                 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
3026                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
3027         }
3028 }
3029
3030 static void
3031 verify_decl_security_table_full (VerifyContext *ctx)
3032 {
3033         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3034         guint32 data [MONO_DECL_SECURITY_SIZE];
3035         int i;
3036
3037         for (i = 0; i < table->rows; ++i) {
3038                 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3039
3040                 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
3041                         ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
3042         }
3043 }
3044
3045 static void
3046 verify_class_layout_table (VerifyContext *ctx)
3047 {
3048         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
3049         guint32 data [MONO_CLASS_LAYOUT_SIZE];
3050         int i;
3051
3052         for (i = 0; i < table->rows; ++i) {
3053                 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
3054
3055                 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3056                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
3057
3058                 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3059                 case 0:
3060                 case 1:
3061                 case 2:
3062                 case 4:
3063                 case 8:
3064                 case 16:
3065                 case 32:
3066                 case 64:
3067                 case 128:
3068                         break;
3069                 default:
3070                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3071                 }
3072         }
3073 }
3074
3075 static void
3076 verify_field_layout_table (VerifyContext *ctx)
3077 {
3078         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3079         guint32 data [MONO_FIELD_LAYOUT_SIZE];
3080         int i;
3081
3082         for (i = 0; i < table->rows; ++i) {
3083                 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3084
3085                 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3086                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3087         }
3088 }
3089
3090 static void
3091 verify_standalonesig_table (VerifyContext *ctx)
3092 {
3093         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3094         guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3095         int i;
3096
3097         for (i = 0; i < table->rows; ++i) {
3098                 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3099
3100                 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3101                         ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3102         }
3103 }
3104
3105 static void
3106 verify_standalonesig_table_full (VerifyContext *ctx)
3107 {
3108         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3109         guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3110         int i;
3111
3112         for (i = 0; i < table->rows; ++i) {
3113                 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3114
3115                 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3116                         ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3117         }
3118 }
3119
3120 static void
3121 verify_eventmap_table (VerifyContext *ctx)
3122 {
3123         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3124         guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3125         int i;
3126
3127         for (i = 0; i < table->rows; ++i) {
3128                 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3129
3130                 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3131                         ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3132
3133                 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3134                         ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3135
3136                 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3137         }
3138 }
3139
3140 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3141 static void
3142 verify_event_table (VerifyContext *ctx)
3143 {
3144         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3145         guint32 data [MONO_EVENT_SIZE];
3146         int i;
3147
3148         for (i = 0; i < table->rows; ++i) {
3149                 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3150
3151                 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3152                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3153
3154                 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3155                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3156
3157                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3158                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3159         }
3160 }
3161
3162 static void
3163 verify_event_table_full (VerifyContext *ctx)
3164 {
3165         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3166         MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3167         guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3168         gboolean found_add, found_remove;
3169         int i, idx;
3170
3171         for (i = 0; i < table->rows; ++i) {
3172                 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3173
3174                 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3175                 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3176                 if (idx == -1)
3177                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3178
3179                 //first we move to the first row for this event
3180                 while (idx > 0) {
3181                         if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3182                                 break;
3183                         --idx;
3184                 }
3185                 //now move forward looking for AddOn and RemoveOn rows
3186                 found_add = found_remove = FALSE;
3187                 while (idx < sema_table->rows) {
3188                         mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3189                         if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3190                                 break;
3191                         if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3192                                 found_add = TRUE;
3193                         if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3194                                 found_remove = TRUE;
3195                         if (found_add && found_remove)
3196                                 break;
3197                         ++idx;
3198                 }
3199
3200                 if (!found_add)
3201                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3202                 if (!found_remove)
3203                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no RemoveOn associated method", i));
3204         }
3205 }
3206
3207 static void
3208 verify_propertymap_table (VerifyContext *ctx)
3209 {
3210         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3211         guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3212         int i;
3213
3214         for (i = 0; i < table->rows; ++i) {
3215                 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3216
3217                 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3218                         ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3219
3220                 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3221                         ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3222
3223                 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3224         }
3225 }
3226
3227 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3228 static void
3229 verify_property_table (VerifyContext *ctx)
3230 {
3231         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3232         guint32 data [MONO_PROPERTY_SIZE];
3233         int i;
3234
3235         for (i = 0; i < table->rows; ++i) {
3236                 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3237
3238                 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3239                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3240
3241                 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3242                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3243
3244                 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3245                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3246
3247                 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3248                                 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3249                         ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3250
3251         }
3252 }
3253
3254 static void
3255 verify_methodimpl_table (VerifyContext *ctx)
3256 {
3257         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3258         guint32 data [MONO_METHODIMPL_SIZE];
3259         int i;
3260
3261         for (i = 0; i < table->rows; ++i) {
3262                 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3263
3264                 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3265                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3266                         
3267                 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3268                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3269                 
3270                 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3271                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3272
3273                 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3274                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3275                 
3276                 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3277                         ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3278         }
3279 }
3280
3281 static void
3282 verify_moduleref_table (VerifyContext *ctx)
3283 {
3284         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3285         guint32 data [MONO_MODULEREF_SIZE];
3286         int i;
3287
3288         for (i = 0; i < table->rows; ++i) {
3289                 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3290
3291                 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3292                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ModuleRef row %d name field %08x", i, data [MONO_MODULEREF_NAME]));
3293         }
3294 }
3295
3296 static void
3297 verify_typespec_table (VerifyContext *ctx)
3298 {
3299         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3300         guint32 data [MONO_TYPESPEC_SIZE];
3301         int i;
3302
3303         for (i = 0; i < table->rows; ++i) {
3304                 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3305
3306                 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3307                         ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3308         }
3309 }
3310
3311 static void
3312 verify_typespec_table_full (VerifyContext *ctx)
3313 {
3314         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3315         guint32 data [MONO_TYPESPEC_SIZE];
3316         int i;
3317
3318         for (i = 0; i < table->rows; ++i) {
3319                 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3320                 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3321                 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3322                         ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3323         }
3324         ctx->token = 0;
3325 }
3326
3327 #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))
3328 static void
3329 verify_implmap_table (VerifyContext *ctx)
3330 {
3331         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3332         guint32 data [MONO_IMPLMAP_SIZE], cconv;
3333         int i;
3334
3335         for (i = 0; i < table->rows; ++i) {
3336                 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3337
3338                 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3339                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3340
3341                 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3342                 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3343                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3344
3345                 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3346                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3347
3348                 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3349                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3350
3351                 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3352                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3353
3354                 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3355                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3356
3357                 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows)
3358                         ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3359         }
3360 }
3361
3362 static void
3363 verify_fieldrva_table (VerifyContext *ctx)
3364 {
3365         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3366         guint32 data [MONO_FIELD_RVA_SIZE];
3367         int i;
3368
3369         for (i = 0; i < table->rows; ++i) {
3370                 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3371
3372                 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3373                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3374
3375                 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3376                         ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3377         }
3378 }
3379
3380 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 14) | (1 << 15))
3381 static void
3382 verify_assembly_table (VerifyContext *ctx)
3383 {
3384         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3385         guint32 data [MONO_ASSEMBLY_SIZE], hash;
3386         int i;
3387
3388         if (table->rows > 1)
3389                 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3390
3391         for (i = 0; i < table->rows; ++i) {
3392                 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3393
3394                 hash = data [MONO_ASSEMBLY_HASH_ALG];
3395                 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3396                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3397
3398                 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3399                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3400
3401                 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3402                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3403
3404                 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3405                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3406
3407                 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3408                         ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3409         }
3410 }
3411
3412 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
3413 static void
3414 verify_assemblyref_table (VerifyContext *ctx)
3415 {
3416         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3417         guint32 data [MONO_ASSEMBLYREF_SIZE];
3418         int i;
3419
3420         for (i = 0; i < table->rows; ++i) {
3421                 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3422
3423                 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3424                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3425
3426                 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3427                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3428
3429                 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3430                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3431
3432                 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3433                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3434
3435                 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3436                         ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3437         }
3438 }
3439
3440 #define INVALID_FILE_FLAGS_BITS ~(1)
3441 static void
3442 verify_file_table (VerifyContext *ctx)
3443 {
3444         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3445         guint32 data [MONO_FILE_SIZE];
3446         int i;
3447
3448         for (i = 0; i < table->rows; ++i) {
3449                 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3450                 
3451                 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3452                         ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3453
3454                 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3455                         ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3456
3457                 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3458                         ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3459         }
3460 }
3461
3462 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3463 static void
3464 verify_exportedtype_table (VerifyContext *ctx)
3465 {
3466         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3467         guint32 data [MONO_EXP_TYPE_SIZE];
3468         int i;
3469
3470         for (i = 0; i < table->rows; ++i) {
3471                 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3472                 
3473                 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3474                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3475
3476                 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3477                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3478
3479                 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3480                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3481
3482                 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3483                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3484
3485                 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3486                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3487
3488                 /*nested type can't have a namespace*/
3489                 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3490                         ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3491         }
3492 }
3493
3494 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3495 static void
3496 verify_manifest_resource_table (VerifyContext *ctx)
3497 {
3498         MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
3499         MonoCLIHeader *ch = &iinfo->cli_cli_header;
3500         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3501         guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3502         int i;
3503
3504         resources_size = ch->ch_resources.size;
3505
3506         for (i = 0; i < table->rows; ++i) {
3507                 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3508
3509                 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3510                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3511
3512                 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3513                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3514
3515                 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3516                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3517
3518                 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3519                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3520
3521                 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3522                 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3523
3524                 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3525                         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])));
3526
3527                 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3528                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3529
3530                 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3531                         ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3532         }
3533 }
3534
3535 static void
3536 verify_nested_class_table (VerifyContext *ctx)
3537 {
3538         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3539         guint32 data [MONO_NESTED_CLASS_SIZE];
3540         int i;
3541
3542         for (i = 0; i < table->rows; ++i) {
3543                 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3544
3545                 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3546                         ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3547                 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3548                         ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3549                 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3550                         ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass  and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3551         }
3552 }
3553
3554 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3555 static void
3556 verify_generic_param_table (VerifyContext *ctx)
3557 {
3558         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3559         guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3560         int i, param_number = 0;
3561
3562         for (i = 0; i < table->rows; ++i) {
3563                 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3564
3565                 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3566                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3567
3568                 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3569                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3570
3571                 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3572                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3573
3574                 token = data [MONO_GENERICPARAM_OWNER];
3575
3576                 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3577                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3578
3579                 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3580                         ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3581
3582                 if (token != last_token) {
3583                         param_number = 0;
3584                         last_token = token;
3585                 }
3586
3587                 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3588                         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));
3589
3590                 ++param_number;
3591         }
3592 }
3593
3594 static void
3595 verify_method_spec_table (VerifyContext *ctx)
3596 {
3597         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3598         guint32 data [MONO_METHODSPEC_SIZE];
3599         int i;
3600
3601         for (i = 0; i < table->rows; ++i) {
3602                 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3603
3604                 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3605                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3606
3607                 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3608                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3609
3610                 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3611                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3612         }
3613 }
3614
3615 static void
3616 verify_method_spec_table_full (VerifyContext *ctx)
3617 {
3618         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3619         guint32 data [MONO_METHODSPEC_SIZE];
3620         int i;
3621
3622         for (i = 0; i < table->rows; ++i) {
3623                 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3624
3625                 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3626                         ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3627         }
3628 }
3629
3630 static void
3631 verify_generic_param_constraint_table (VerifyContext *ctx)
3632 {
3633         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3634         guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3635         int i;
3636         guint32 last_owner = 0, last_constraint = 0;
3637
3638         for (i = 0; i < table->rows; ++i) {
3639                 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3640
3641                 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3642                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3643
3644                 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3645                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3646
3647                 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3648                         ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3649
3650                 if (last_owner > data [MONO_GENPARCONSTRAINT_GENERICPAR])
3651                         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]));
3652
3653                 if (last_owner == data [MONO_GENPARCONSTRAINT_GENERICPAR]) {
3654                         if (last_constraint == data [MONO_GENPARCONSTRAINT_CONSTRAINT])
3655                                 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has duplicate constraint 0x%08x", i, last_constraint));
3656                 } else {
3657                         last_owner = data [MONO_GENPARCONSTRAINT_GENERICPAR];
3658                 }
3659                 last_constraint = data [MONO_GENPARCONSTRAINT_CONSTRAINT];
3660         }
3661 }
3662
3663
3664 typedef struct {
3665         const char *name;
3666         const char *name_space;
3667         guint32 resolution_scope;
3668 } TypeDefUniqueId;
3669
3670 static guint
3671 typedef_hash (gconstpointer _key)
3672 {
3673         const TypeDefUniqueId *key = (const TypeDefUniqueId *)_key;
3674         return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3675 }
3676
3677 static gboolean
3678 typedef_equals (gconstpointer _a, gconstpointer _b)
3679 {
3680         const TypeDefUniqueId *a = (const TypeDefUniqueId *)_a;
3681         const TypeDefUniqueId *b = (const TypeDefUniqueId *)_b;
3682         return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3683 }
3684
3685 static void
3686 verify_typedef_table_global_constraints (VerifyContext *ctx)
3687 {
3688         int i;
3689         guint32 data [MONO_TYPEDEF_SIZE];
3690         guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3691         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3692         MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3693         GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3694
3695         for (i = 0; i < table->rows; ++i) {
3696                 guint visibility;
3697                 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3698                 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3699
3700                 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3701                 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3702                 type->resolution_scope = 0;
3703
3704                 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3705                 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3706                         int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3707                         g_assert (res >= 0);
3708
3709                         mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3710                         type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3711                 }
3712
3713                 if (g_hash_table_lookup (unique_types, type)) {
3714                         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));
3715                         g_hash_table_destroy (unique_types);
3716                         g_free (type);
3717                         return;
3718                 }
3719                 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3720         }
3721
3722         g_hash_table_destroy (unique_types);
3723 }
3724
3725 static void
3726 verify_typeref_table_global_constraints (VerifyContext *ctx)
3727 {
3728         int i;
3729         guint32 data [MONO_TYPEREF_SIZE];
3730         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3731         GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3732
3733         for (i = 0; i < table->rows; ++i) {
3734                 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3735                 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3736
3737                 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3738                 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3739                 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3740
3741                 if (g_hash_table_lookup (unique_types, type)) {
3742                         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));
3743                         g_hash_table_destroy (unique_types);
3744                         g_free (type);
3745                         return;
3746                 }
3747                 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3748         }
3749
3750         g_hash_table_destroy (unique_types);
3751 }
3752
3753 typedef struct {
3754         guint32 klass;
3755         guint32 method_declaration;
3756 } MethodImplUniqueId;
3757
3758 static guint
3759 methodimpl_hash (gconstpointer _key)
3760 {
3761         const MethodImplUniqueId *key = (const MethodImplUniqueId *)_key;
3762         return key->klass ^ key->method_declaration;
3763 }
3764
3765 static gboolean
3766 methodimpl_equals (gconstpointer _a, gconstpointer _b)
3767 {
3768         const MethodImplUniqueId *a = (const MethodImplUniqueId *)_a;
3769         const MethodImplUniqueId *b = (const MethodImplUniqueId *)_b;
3770         return a->klass == b->klass && a->method_declaration == b->method_declaration;
3771 }
3772
3773 static void
3774 verify_methodimpl_table_global_constraints (VerifyContext *ctx)
3775 {
3776         int i;
3777         guint32 data [MONO_METHODIMPL_SIZE];
3778         MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3779         GHashTable *unique_impls = g_hash_table_new_full (&methodimpl_hash, &methodimpl_equals, g_free, NULL);
3780
3781         for (i = 0; i < table->rows; ++i) {
3782                 MethodImplUniqueId *impl = g_new (MethodImplUniqueId, 1);
3783                 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3784
3785                 impl->klass = data [MONO_METHODIMPL_CLASS];
3786                 impl->method_declaration = data [MONO_METHODIMPL_DECLARATION];
3787
3788                 if (g_hash_table_lookup (unique_impls, impl)) {
3789                         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));
3790                         g_hash_table_destroy (unique_impls);
3791                         g_free (impl);
3792                         return;
3793                 }
3794                 g_hash_table_insert (unique_impls, impl, GUINT_TO_POINTER (1));
3795         }
3796
3797         g_hash_table_destroy (unique_impls);
3798 }
3799
3800
3801 static void
3802 verify_tables_data_global_constraints (VerifyContext *ctx)
3803 {
3804         verify_typedef_table_global_constraints (ctx);
3805 }
3806
3807 static void
3808 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3809 {
3810         verify_typeref_table (ctx);
3811         verify_typeref_table_global_constraints (ctx);
3812         verify_methodimpl_table_global_constraints (ctx);
3813 }
3814
3815 static void
3816 verify_tables_data (VerifyContext *ctx)
3817 {
3818         OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3819         guint32 size = 0, tables_offset;
3820         int i;
3821
3822         for (i = 0; i < 0x2D; ++i) {
3823                 MonoTableInfo *table = &ctx->image->tables [i];
3824                 guint32 tmp_size;
3825                 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3826                 if (tmp_size < size) {
3827                         size = 0;
3828                         break;
3829                 }
3830                 size = tmp_size;                        
3831         }
3832
3833         if (size == 0)
3834                 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3835
3836         tables_offset = ctx->image->tables_base - ctx->data;
3837         if (!bounds_check_offset (&tables_area, tables_offset, size))
3838                 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)));
3839
3840         verify_module_table (ctx);
3841         CHECK_ERROR ();
3842         /*Obfuscators love to place broken stuff in the typeref table
3843         verify_typeref_table (ctx);
3844         CHECK_ERROR ();*/
3845         verify_typedef_table (ctx);
3846         CHECK_ERROR ();
3847         verify_field_table (ctx);
3848         CHECK_ERROR ();
3849         verify_method_table (ctx);
3850         CHECK_ERROR ();
3851         verify_param_table (ctx);
3852         CHECK_ERROR ();
3853         verify_interfaceimpl_table (ctx);
3854         CHECK_ERROR ();
3855         verify_memberref_table (ctx);
3856         CHECK_ERROR ();
3857         verify_constant_table (ctx);
3858         CHECK_ERROR ();
3859         verify_cattr_table (ctx);
3860         CHECK_ERROR ();
3861         verify_field_marshal_table (ctx);
3862         CHECK_ERROR ();
3863         verify_decl_security_table (ctx);
3864         CHECK_ERROR ();
3865         verify_class_layout_table (ctx);
3866         CHECK_ERROR ();
3867         verify_field_layout_table (ctx);
3868         CHECK_ERROR ();
3869         verify_standalonesig_table (ctx);
3870         CHECK_ERROR ();
3871         verify_eventmap_table (ctx);
3872         CHECK_ERROR ();
3873         verify_event_table (ctx);
3874         CHECK_ERROR ();
3875         verify_propertymap_table (ctx);
3876         CHECK_ERROR ();
3877         verify_property_table (ctx);
3878         CHECK_ERROR ();
3879         verify_methodimpl_table (ctx);
3880         CHECK_ERROR ();
3881         verify_moduleref_table (ctx);
3882         CHECK_ERROR ();
3883         verify_typespec_table (ctx);
3884         CHECK_ERROR ();
3885         verify_implmap_table (ctx);
3886         CHECK_ERROR ();
3887         verify_fieldrva_table (ctx);
3888         CHECK_ERROR ();
3889         verify_assembly_table (ctx);
3890         CHECK_ERROR ();
3891         verify_assemblyref_table (ctx);
3892         CHECK_ERROR ();
3893         verify_file_table (ctx);
3894         CHECK_ERROR ();
3895         verify_exportedtype_table (ctx);
3896         CHECK_ERROR ();
3897         verify_manifest_resource_table (ctx);
3898         CHECK_ERROR ();
3899         verify_nested_class_table (ctx);
3900         CHECK_ERROR ();
3901         verify_generic_param_table (ctx);
3902         CHECK_ERROR ();
3903         verify_method_spec_table (ctx);
3904         CHECK_ERROR ();
3905         verify_generic_param_constraint_table (ctx);
3906         CHECK_ERROR ();
3907         verify_tables_data_global_constraints (ctx);
3908 }
3909
3910 static void
3911 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3912 {
3913         memset (ctx, 0, sizeof (VerifyContext));
3914         ctx->image = image;
3915         ctx->report_error = report_error;
3916         ctx->report_warning = FALSE; //export this setting in the API
3917         ctx->valid = 1;
3918         ctx->size = image->raw_data_len;
3919         ctx->data = image->raw_data;
3920 }
3921
3922 static gboolean
3923 cleanup_context (VerifyContext *ctx, GSList **error_list)
3924 {
3925         g_free (ctx->sections);
3926         if (error_list)
3927                 *error_list = ctx->errors;
3928         else
3929                 mono_free_verify_list (ctx->errors);
3930         return ctx->valid;      
3931 }
3932
3933 static gboolean
3934 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3935 {
3936         g_free (ctx->sections);
3937         if (ctx->errors) {
3938                 MonoVerifyInfo *info = (MonoVerifyInfo *)ctx->errors->data;
3939                 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3940                 mono_free_verify_list (ctx->errors);
3941         }
3942         return ctx->valid;
3943 }
3944
3945 gboolean
3946 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3947 {
3948         VerifyContext ctx;
3949
3950         if (!mono_verifier_is_enabled_for_image (image))
3951                 return TRUE;
3952
3953         init_verify_context (&ctx, image, error_list != NULL);
3954         ctx.stage = STAGE_PE;
3955
3956         verify_msdos_header (&ctx);
3957         CHECK_STATE();
3958         verify_pe_header (&ctx);
3959         CHECK_STATE();
3960         verify_pe_optional_header (&ctx);
3961         CHECK_STATE();
3962         load_section_table (&ctx);
3963         CHECK_STATE();
3964         load_data_directories (&ctx);
3965         CHECK_STATE();
3966         verify_import_table (&ctx);
3967         CHECK_STATE();
3968         /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3969         verify_resources_table (&ctx);
3970
3971 cleanup:
3972         return cleanup_context (&ctx, error_list);
3973 }
3974
3975 gboolean
3976 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3977 {
3978         VerifyContext ctx;
3979
3980         if (!mono_verifier_is_enabled_for_image (image))
3981                 return TRUE;
3982
3983         init_verify_context (&ctx, image, error_list != NULL);
3984         ctx.stage = STAGE_CLI;
3985
3986         verify_cli_header (&ctx);
3987         CHECK_STATE();
3988         verify_metadata_header (&ctx);
3989         CHECK_STATE();
3990         verify_tables_schema (&ctx);
3991
3992 cleanup:
3993         return cleanup_context (&ctx, error_list);
3994 }
3995
3996
3997 /*
3998  * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3999  * Other verification checks are meant to be done lazily by the runtime. Those include:
4000  *      blob items (signatures, method headers, custom attributes, etc)
4001  *  type semantics related
4002  *  vtable related
4003  *  stuff that should not block other pieces from running such as bad types/methods/fields/etc.
4004  * 
4005  * The whole idea is that if this succeed the runtime is free to play around safely but any complex
4006  * operation still need more checking.
4007  */
4008 gboolean
4009 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4010 {
4011         VerifyContext ctx;
4012
4013         if (!mono_verifier_is_enabled_for_image (image))
4014                 return TRUE;
4015
4016         init_verify_context (&ctx, image, error_list != NULL);
4017         ctx.stage = STAGE_TABLES;
4018
4019         verify_tables_data (&ctx);
4020
4021         return cleanup_context (&ctx, error_list);
4022 }
4023
4024
4025 /*
4026  * Verifies all other constraints.
4027  */
4028 gboolean
4029 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4030 {
4031         VerifyContext ctx;
4032
4033         if (!mono_verifier_is_enabled_for_image (image))
4034                 return TRUE;
4035
4036         init_verify_context (&ctx, image, error_list != NULL);
4037         ctx.stage = STAGE_TABLES;
4038
4039         verify_typedef_table_full (&ctx);
4040         CHECK_STATE ();
4041         verify_field_table_full (&ctx);
4042         CHECK_STATE ();
4043         verify_method_table_full (&ctx);
4044         CHECK_STATE ();
4045         verify_memberref_table_full (&ctx);
4046         CHECK_STATE ();
4047         verify_cattr_table_full (&ctx);
4048         CHECK_STATE ();
4049         verify_field_marshal_table_full (&ctx);
4050         CHECK_STATE ();
4051         verify_decl_security_table_full (&ctx);
4052         CHECK_STATE ();
4053         verify_standalonesig_table_full (&ctx);
4054         CHECK_STATE ();
4055         verify_event_table_full (&ctx);
4056         CHECK_STATE ();
4057         verify_typespec_table_full (&ctx);
4058         CHECK_STATE ();
4059         verify_method_spec_table_full (&ctx);
4060         CHECK_STATE ();
4061         verify_tables_data_global_constraints_full (&ctx);
4062
4063 cleanup:
4064         return cleanup_context (&ctx, error_list);
4065 }
4066
4067 gboolean
4068 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4069 {
4070         VerifyContext ctx;
4071
4072         if (!mono_verifier_is_enabled_for_image (image))
4073                 return TRUE;
4074
4075         init_verify_context (&ctx, image, error_list != NULL);
4076         ctx.stage = STAGE_TABLES;
4077
4078         is_valid_field_signature (&ctx, offset);
4079         return cleanup_context (&ctx, error_list);
4080 }
4081
4082 gboolean
4083 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4084 {
4085         VerifyContext ctx;
4086         guint32 locals_token;
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_method_header (&ctx, offset, &locals_token);
4095         if (locals_token) {
4096                 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
4097                 is_valid_standalonesig_blob (&ctx, sig_offset);
4098         }
4099
4100         return cleanup_context (&ctx, error_list);
4101 }
4102
4103 gboolean
4104 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4105 {
4106         VerifyContext ctx;
4107
4108         error_init (error);
4109
4110         if (!mono_verifier_is_enabled_for_image (image))
4111                 return TRUE;
4112
4113         init_verify_context (&ctx, image, TRUE);
4114         ctx.stage = STAGE_TABLES;
4115
4116         is_valid_method_signature (&ctx, offset);
4117         /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4118         return cleanup_context_checked (&ctx, error);
4119 }
4120
4121 gboolean
4122 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4123 {
4124         VerifyContext ctx;
4125
4126         if (!mono_verifier_is_enabled_for_image (image))
4127                 return TRUE;
4128
4129         init_verify_context (&ctx, image, error_list != NULL);
4130         ctx.stage = STAGE_TABLES;
4131
4132         is_valid_memberref_method_signature (&ctx, offset);
4133         return cleanup_context (&ctx, error_list);
4134 }
4135
4136 gboolean
4137 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4138 {
4139         VerifyContext ctx;
4140
4141         if (!mono_verifier_is_enabled_for_image (image))
4142                 return TRUE;
4143
4144         init_verify_context (&ctx, image, error_list != NULL);
4145         ctx.stage = STAGE_TABLES;
4146
4147         is_valid_field_signature (&ctx, offset);
4148         return cleanup_context (&ctx, error_list);
4149 }
4150
4151 gboolean
4152 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4153 {
4154         VerifyContext ctx;
4155
4156         if (!mono_verifier_is_enabled_for_image (image))
4157                 return TRUE;
4158
4159         init_verify_context (&ctx, image, error_list != NULL);
4160         ctx.stage = STAGE_TABLES;
4161
4162         is_valid_standalonesig_blob (&ctx, offset);
4163         return cleanup_context (&ctx, error_list);
4164 }
4165
4166 gboolean
4167 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4168 {
4169         VerifyContext ctx;
4170
4171         if (!mono_verifier_is_enabled_for_image (image))
4172                 return TRUE;
4173
4174         init_verify_context (&ctx, image, error_list != NULL);
4175         ctx.stage = STAGE_TABLES;
4176         ctx.token = token;
4177
4178         is_valid_typespec_blob (&ctx, offset);
4179         return cleanup_context (&ctx, error_list);
4180 }
4181
4182 gboolean
4183 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, 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
4193         is_valid_methodspec_blob (&ctx, offset);
4194         return cleanup_context (&ctx, error_list);
4195 }
4196
4197 static void
4198 verify_user_string (VerifyContext *ctx, guint32 offset)
4199 {
4200         OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4201         guint32 entry_size, bytes;
4202
4203         if (heap_us.size < offset)
4204                 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4205
4206         if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4207                 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4208
4209         if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4210                 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4211
4212         entry_size += bytes;
4213
4214         if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4215                 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4216 }
4217
4218 gboolean
4219 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4220 {
4221         VerifyContext ctx;
4222
4223         if (!mono_verifier_is_enabled_for_image (image))
4224                 return TRUE;
4225
4226         init_verify_context (&ctx, image, error_list != NULL);
4227         ctx.stage = STAGE_TABLES;
4228
4229         verify_user_string (&ctx, offset);
4230
4231         return cleanup_context (&ctx, error_list);
4232 }
4233
4234 gboolean
4235 mono_verifier_verify_cattr_blob (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         is_valid_cattr_blob (&ctx, offset);
4246
4247         return cleanup_context (&ctx, error_list);
4248 }
4249
4250 gboolean
4251 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, 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_content (&ctx, ctor, (const char*)data, size);
4262
4263         return cleanup_context (&ctx, error_list);
4264 }
4265
4266 gboolean
4267 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4268 {
4269         MonoMethodSignature *original_sig;
4270         if (!mono_verifier_is_enabled_for_image (image))
4271                 return TRUE;
4272
4273         original_sig = mono_method_signature (method);
4274         if (original_sig->call_convention == MONO_CALL_VARARG) {
4275                 if (original_sig->hasthis != signature->hasthis)
4276                         return FALSE;
4277                 if (original_sig->call_convention != signature->call_convention)
4278                         return FALSE;
4279                 if (original_sig->explicit_this != signature->explicit_this)
4280                         return FALSE;
4281                 if (original_sig->pinvoke != signature->pinvoke)
4282                         return FALSE;
4283                 if (original_sig->sentinelpos != signature->sentinelpos)
4284                         return FALSE;
4285         } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4286                 return FALSE;
4287         }
4288
4289         return TRUE;
4290 }
4291
4292 gboolean
4293 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4294 {
4295         MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
4296         guint32 data [MONO_TYPEREF_SIZE];
4297
4298         error_init (error);
4299
4300         if (!mono_verifier_is_enabled_for_image (image))
4301                 return TRUE;
4302
4303         if (row >= table->rows) {
4304                 mono_error_set_bad_image (error, image, "Invalid typeref row %d - table has %d rows", row, table->rows);
4305                 return FALSE;
4306         }
4307
4308         mono_metadata_decode_row (table, row, data, MONO_TYPEREF_SIZE);
4309         if (!is_valid_coded_index_with_image (image, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4310                 mono_error_set_bad_image (error, image, "Invalid typeref row %d coded index 0x%08x", row, data [MONO_TYPEREF_SCOPE]);
4311                 return FALSE;
4312         }
4313
4314         if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4315                 mono_error_set_bad_image (error, image, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row);
4316                 return FALSE;
4317         }
4318
4319         if (!data [MONO_TYPEREF_NAME] || !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAME], FALSE)) {
4320                 mono_error_set_bad_image (error, image, "Invalid typeref row %d name token 0x%08x", row, data [MONO_TYPEREF_NAME]);
4321                 return FALSE;
4322         }
4323
4324         if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAMESPACE], FALSE)) {
4325                 mono_error_set_bad_image (error, image, "Invalid typeref row %d namespace token 0x%08x", row, data [MONO_TYPEREF_NAMESPACE]);
4326                 return FALSE;
4327         }
4328
4329         return TRUE;
4330 }
4331
4332 /*Perform additional verification including metadata ones*/
4333 gboolean
4334 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4335 {
4336         MonoMethod *declaration, *body;
4337         MonoMethodSignature *body_sig, *decl_sig;
4338         MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
4339         guint32 data [MONO_METHODIMPL_SIZE];
4340
4341         error_init (error);
4342
4343         if (!mono_verifier_is_enabled_for_image (image))
4344                 return TRUE;
4345
4346         if (row >= table->rows) {
4347                 mono_error_set_bad_image (error, image, "Invalid methodimpl row %d - table has %d rows", row, table->rows);
4348                 return FALSE;
4349         }
4350
4351         mono_metadata_decode_row (table, row, data, MONO_METHODIMPL_SIZE);
4352
4353         body = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_BODY], NULL, error);
4354         if (!body)
4355                 return FALSE;
4356
4357         declaration = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_DECLARATION], NULL, error);
4358         if (!declaration)
4359                 return FALSE;
4360
4361         /* FIXME
4362         mono_class_setup_supertypes (class);
4363         if (!mono_class_has_parent (class, body->klass)) {
4364                 mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
4365                 return FALSE;
4366         }*/
4367
4368         if (!(body_sig = mono_method_signature_checked (body, error))) {
4369                 return FALSE;
4370         }
4371
4372         if (!(decl_sig = mono_method_signature_checked (declaration, error))) {
4373                 return FALSE;
4374         }
4375
4376         if (!mono_verifier_is_signature_compatible (decl_sig, body_sig)) {
4377                 mono_error_set_bad_image (error, image, "Invalid methodimpl body signature not compatible with declaration row %x", row);
4378                 return FALSE;
4379         }
4380
4381         return TRUE;
4382 }
4383
4384 #else
4385 gboolean
4386 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4387 {
4388         return TRUE;
4389 }
4390
4391 gboolean
4392 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4393 {
4394         return TRUE;
4395 }
4396
4397 gboolean
4398 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4399 {
4400         return TRUE;
4401 }
4402
4403 gboolean
4404 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4405 {
4406         return TRUE;
4407 }
4408
4409 gboolean
4410 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4411 {
4412         return TRUE;
4413 }
4414
4415 gboolean
4416 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4417 {
4418         return TRUE;
4419 }
4420
4421 gboolean
4422 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4423 {
4424         error_init (error);
4425         return TRUE;
4426 }
4427
4428 gboolean
4429 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4430 {
4431         return TRUE;
4432 }
4433
4434 gboolean
4435 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4436 {
4437         return TRUE;
4438 }
4439
4440 gboolean
4441 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4442 {
4443         return TRUE;
4444 }
4445
4446 gboolean
4447 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4448 {
4449         return TRUE;
4450 }
4451
4452 gboolean
4453 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4454 {
4455         return TRUE;
4456 }
4457
4458 gboolean
4459 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4460 {
4461         return TRUE;
4462 }
4463
4464 gboolean
4465 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4466 {
4467         return TRUE;
4468 }
4469
4470
4471 gboolean
4472 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4473 {
4474         error_init (error);
4475         return TRUE;
4476 }
4477
4478 gboolean
4479 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4480 {
4481         error_init (error);
4482         return TRUE;
4483 }
4484
4485 gboolean
4486 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4487 {
4488         return TRUE;
4489 }
4490
4491 gboolean
4492 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4493 {
4494         return TRUE;
4495 }
4496
4497 #endif /* DISABLE_VERIFIER */