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