2 * metadata-verify.c: Metadata verfication support
5 * Mono Project (http://www.mono-project.com)
7 * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
9 #include <mono/metadata/object-internals.h>
10 #include <mono/metadata/verify.h>
11 #include <mono/metadata/verify-internals.h>
12 #include <mono/metadata/opcodes.h>
13 #include <mono/metadata/tabledefs.h>
14 #include <mono/metadata/reflection.h>
15 #include <mono/metadata/debug-helpers.h>
16 #include <mono/metadata/mono-endian.h>
17 #include <mono/metadata/metadata.h>
18 #include <mono/metadata/metadata-internals.h>
19 #include <mono/metadata/class-internals.h>
20 #include <mono/metadata/tokentype.h>
21 #include <mono/metadata/security-manager.h>
22 #include <mono/metadata/security-core-clr.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/attrdefs.h>
25 #include <mono/utils/strenc.h>
30 #ifndef DISABLE_VERIFIER
32 TODO add fail fast mode
33 TODO add PE32+ support
34 TODO verify the entry point RVA and content.
35 TODO load_section_table and load_data_directories must take PE32+ into account
36 TODO add section relocation support
37 TODO verify the relocation table, since we really don't use, no need so far.
38 TODO do full PECOFF resources verification
39 TODO verify in the CLI header entry point and resources
40 TODO implement null token typeref validation
41 TODO verify table wide invariants for typedef (sorting and uniqueness)
42 TODO implement proper authenticode data directory validation
43 TODO verify properties that require multiple tables to be valid
44 FIXME use subtraction based bounds checking to avoid overflows
45 FIXME get rid of metadata_streams and other fields from VerifyContext
48 #ifdef MONO_VERIFIER_DEBUG
49 #define VERIFIER_DEBUG(code) do { code; } while (0)
51 #define VERIFIER_DEBUG(code)
54 #define INVALID_OFFSET ((guint32)-1)
55 #define INVALID_ADDRESS 0xffffffff
65 RESOURCE_TABLE_IDX = 2,
66 CERTIFICATE_TABLE_IDX = 4,
67 RELOCATION_TABLE_IDX = 5,
81 #define INVALID_TABLE (0xFF)
82 /*format: number of bits, number of tables, tables{n. tables} */
83 const static unsigned char coded_index_desc[] = {
84 #define TYPEDEF_OR_REF_DESC (0)
91 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
98 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
106 MONO_TABLE_INTERFACEIMPL,
107 MONO_TABLE_MEMBERREF,
109 MONO_TABLE_DECLSECURITY,
112 MONO_TABLE_STANDALONESIG,
113 MONO_TABLE_MODULEREF,
116 MONO_TABLE_ASSEMBLYREF,
118 MONO_TABLE_EXPORTEDTYPE,
119 MONO_TABLE_MANIFESTRESOURCE,
120 MONO_TABLE_GENERICPARAM,
122 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
128 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
135 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
144 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
150 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
154 MONO_TABLE_MEMBERREF,
156 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
162 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
166 MONO_TABLE_ASSEMBLYREF,
167 MONO_TABLE_EXPORTEDTYPE,
169 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
175 MONO_TABLE_MEMBERREF,
178 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
182 MONO_TABLE_MODULEREF,
183 MONO_TABLE_ASSEMBLYREF,
186 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
196 guint32 translated_offset;
208 guint32 rellocationsRVA;
209 guint16 numberOfRelocations;
224 gboolean report_error;
225 gboolean report_warning;
228 DataDirectory data_directories [16];
229 guint32 section_count;
230 SectionHeader *sections;
232 OffsetAndSize metadata_streams [5]; //offset from begin of the image
235 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
237 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
238 vinfo->info.status = __status; \
239 vinfo->info.message = ( __msg); \
240 vinfo->exception_type = (__exception); \
241 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
244 #define ADD_WARNING(__ctx, __msg) \
246 if ((__ctx)->report_warning) \
247 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
248 (__ctx)->valid = 0; \
252 #define ADD_ERROR(__ctx, __msg) \
254 if ((__ctx)->report_error) \
255 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
256 (__ctx)->valid = 0; \
260 #define FAIL(__ctx, __msg) \
262 if ((__ctx)->report_error) \
263 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
264 (__ctx)->valid = 0; \
268 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
270 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
272 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
273 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
275 #if SIZEOF_VOID_P == 4
276 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
278 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
281 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
282 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
285 dword_align (const char *ptr)
287 #if SIZEOF_VOID_P == 8
288 return (const char *) (((guint64) (ptr + 3)) & ~3);
290 return (const char *) (((guint32) (ptr + 3)) & ~3);
295 pe_signature_offset (VerifyContext *ctx)
297 return read32 (ctx->data + 0x3c);
301 pe_header_offset (VerifyContext *ctx)
303 return read32 (ctx->data + 0x3c) + 4;
307 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
311 if (rva + size < rva) //overflow
314 if (ctx->stage > STAGE_PE) {
315 MonoCLIImageInfo *iinfo = ctx->image->image_info;
316 const int top = iinfo->cli_section_count;
317 MonoSectionTable *tables = iinfo->cli_section_tables;
320 for (i = 0; i < top; i++) {
321 guint32 base = tables->st_virtual_address;
322 guint32 end = base + tables->st_raw_data_size;
324 if (rva >= base && rva + size <= end)
327 /*if ((addr >= tables->st_virtual_address) &&
328 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
330 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
340 for (i = 0; i < ctx->section_count; ++i) {
341 guint32 base = ctx->sections [i].baseRVA;
342 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
343 if (rva >= base && rva + size <= end)
350 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
352 if (dir->translated_offset > offset)
354 if (dir->size < size)
356 return offset + size <= dir->translated_offset + dir->size;
360 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
362 if (off->offset > offset)
365 if (off->size < size)
368 return offset + size <= off->offset + off->size;
372 translate_rva (VerifyContext *ctx, guint32 rva)
376 if (ctx->stage > STAGE_PE)
377 return mono_cli_rva_image_map (ctx->image, rva);
382 for (i = 0; i < ctx->section_count; ++i) {
383 guint32 base = ctx->sections [i].baseRVA;
384 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
385 if (rva >= base && rva <= end) {
386 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
388 return res >= ctx->size ? INVALID_OFFSET : res;
392 return INVALID_OFFSET;
396 verify_msdos_header (VerifyContext *ctx)
400 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
401 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
402 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
403 lfanew = pe_signature_offset (ctx);
404 if (lfanew > ctx->size - 4)
405 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
409 verify_pe_header (VerifyContext *ctx)
411 guint32 offset = pe_signature_offset (ctx);
412 const char *pe_header = ctx->data + offset;
413 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
414 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
418 if (offset > ctx->size - 20)
419 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
420 if (read16 (pe_header) != 0x14c)
421 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
425 verify_pe_optional_header (VerifyContext *ctx)
427 guint32 offset = pe_header_offset (ctx);
428 guint32 header_size, file_alignment;
429 const char *pe_header = ctx->data + offset;
430 const char *pe_optional_header = pe_header + 20;
432 header_size = read16 (pe_header + 16);
435 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
436 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
438 if (offset > ctx->size - header_size || header_size > ctx->size)
439 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
441 if (read16 (pe_optional_header) == 0x10b) {
442 if (header_size != 224)
443 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
445 /* LAMESPEC MS plays around this value and ignore it during validation
446 if (read32 (pe_optional_header + 28) != 0x400000)
447 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
448 if (read32 (pe_optional_header + 32) != 0x2000)
449 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
450 file_alignment = read32 (pe_optional_header + 36);
451 if (file_alignment != 0x200 && file_alignment != 0x1000)
452 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
453 /* All the junk in the middle is irrelevant, specially for mono. */
454 if (read32 (pe_optional_header + 92) > 0x10)
455 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
457 if (read16 (pe_optional_header) == 0x20B)
458 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
460 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
465 load_section_table (VerifyContext *ctx)
468 SectionHeader *sections;
469 guint32 offset = pe_header_offset (ctx);
470 const char *ptr = ctx->data + offset;
471 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
473 offset += 244;/*FIXME, this constant is different under PE32+*/
476 if (num_sections * 40 > ctx->size - offset)
477 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
479 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
480 for (i = 0; i < num_sections; ++i) {
481 sections [i].size = read32 (ptr + 8);
482 sections [i].baseRVA = read32 (ptr + 12);
483 sections [i].baseOffset = read32 (ptr + 20);
484 sections [i].rellocationsRVA = read32 (ptr + 24);
485 sections [i].numberOfRelocations = read16 (ptr + 32);
489 ptr = ctx->data + offset; /*reset it to the beggining*/
490 for (i = 0; i < num_sections; ++i) {
491 guint32 raw_size, flags;
492 if (sections [i].baseOffset == 0)
493 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
494 if (sections [i].baseOffset >= ctx->size)
495 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
496 if (sections [i].size > ctx->size - sections [i].baseOffset)
497 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
499 raw_size = read32 (ptr + 16);
500 if (raw_size < sections [i].size)
501 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
503 if (raw_size > ctx->size - sections [i].baseOffset)
504 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
506 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
507 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
509 flags = read32 (ptr + 36);
510 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
511 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
512 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
519 is_valid_data_directory (int i)
521 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
522 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
526 load_data_directories (VerifyContext *ctx)
528 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
529 const char *ptr = ctx->data + offset;
532 for (i = 0; i < 16; ++i) {
533 guint32 rva = read32 (ptr);
534 guint32 size = read32 (ptr + 4);
536 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
537 if (i == CERTIFICATE_TABLE_IDX) {
541 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
542 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
544 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
545 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
547 ctx->data_directories [i].rva = rva;
548 ctx->data_directories [i].size = size;
549 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
555 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
557 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
560 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
563 guint32 hint_table_rva;
565 import_rva = translate_rva (ctx, import_rva);
566 g_assert (import_rva != INVALID_OFFSET);
568 hint_table_rva = read32 (ctx->data + import_rva);
569 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
570 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
572 hint_table_rva = translate_rva (ctx, hint_table_rva);
573 g_assert (hint_table_rva != INVALID_OFFSET);
574 ptr = ctx->data + hint_table_rva + 2;
576 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
577 char name[SIZE_OF_CORMAIN];
578 memcpy (name, ptr, SIZE_OF_CORMAIN);
579 name [SIZE_OF_CORMAIN - 1] = 0;
580 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
585 verify_import_table (VerifyContext *ctx)
587 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
588 guint32 offset = it.translated_offset;
589 const char *ptr = ctx->data + offset;
590 guint32 name_rva, ilt_rva, iat_rva;
592 g_assert (offset != INVALID_OFFSET);
595 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
597 ilt_rva = read32 (ptr);
598 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
599 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
601 name_rva = read32 (ptr + 12);
602 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
603 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
605 iat_rva = read32 (ptr + 16);
607 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
608 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
610 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
611 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));
615 name_rva = translate_rva (ctx, name_rva);
616 g_assert (name_rva != INVALID_OFFSET);
617 ptr = ctx->data + name_rva;
619 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
620 char name[SIZE_OF_MSCOREE];
621 memcpy (name, ptr, SIZE_OF_MSCOREE);
622 name [SIZE_OF_MSCOREE - 1] = 0;
623 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
628 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
633 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
637 verify_resources_table (VerifyContext *ctx)
639 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
641 guint16 named_entries, id_entries;
642 const char *ptr, *root, *end;
648 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));
650 offset = it.translated_offset;
651 root = ptr = ctx->data + offset;
652 end = root + it.size;
654 g_assert (offset != INVALID_OFFSET);
656 named_entries = read16 (ptr + 12);
657 id_entries = read16 (ptr + 14);
659 if ((named_entries + id_entries) * 8 + 16 > it.size)
660 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));
662 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
663 if (named_entries || id_entries)
664 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
668 /*----------nothing from here on can use data_directory---*/
671 get_data_dir (VerifyContext *ctx, int idx)
673 MonoCLIImageInfo *iinfo = ctx->image->image_info;
674 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
678 res.rva = entry->rva;
679 res.size = entry->size;
680 res.translated_offset = translate_rva (ctx, res.rva);
685 verify_cli_header (VerifyContext *ctx)
687 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
693 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
696 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
698 offset = it.translated_offset;
699 ptr = ctx->data + offset;
701 g_assert (offset != INVALID_OFFSET);
703 if (read16 (ptr) != 72)
704 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
706 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
707 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
710 if (!read32 (ptr + 8) || !read32 (ptr + 12))
711 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
713 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
714 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
717 for (i = 0; i < 6; ++i) {
718 guint32 rva = read32 (ptr);
719 guint32 size = read32 (ptr + 4);
721 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
722 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
727 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
732 pad4 (guint32 offset)
734 if (offset & 0x3) //pad to the next 4 byte boundary
735 offset = (offset & ~0x3) + 4;
740 verify_metadata_header (VerifyContext *ctx)
743 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
747 offset = it.translated_offset;
748 ptr = ctx->data + offset;
749 g_assert (offset != INVALID_OFFSET);
751 //build a directory entry for the metadata root
753 it.rva = read32 (ptr);
755 it.size = read32 (ptr);
756 it.translated_offset = offset = translate_rva (ctx, it.rva);
758 ptr = ctx->data + offset;
759 g_assert (offset != INVALID_OFFSET);
762 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
764 if (read32 (ptr) != 0x424A5342)
765 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
767 offset = pad4 (offset + 16 + read32 (ptr + 12));
769 if (!bounds_check_datadir (&it, offset, 4))
770 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));
772 ptr = ctx->data + offset; //move to streams header
774 if (read16 (ptr + 2) < 3)
775 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 3 streams (#~, #GUID and #Blob"));
780 for (i = 0; i < 5; ++i) {
781 guint32 stream_off, stream_size;
782 int string_size, stream_idx;
784 if (!bounds_check_datadir (&it, offset, 8))
785 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));
787 stream_off = it.translated_offset + read32 (ptr);
788 stream_size = read32 (ptr + 4);
790 if (!bounds_check_datadir (&it, stream_off, stream_size))
791 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
796 for (string_size = 0; string_size < 32; ++string_size) {
797 if (!bounds_check_datadir (&it, offset++, 1))
798 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
799 if (!ptr [string_size])
803 if (ptr [string_size])
804 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
806 if (!strncmp ("#Strings", ptr, 9))
807 stream_idx = STRINGS_STREAM;
808 else if (!strncmp ("#US", ptr, 4))
809 stream_idx = USER_STRINGS_STREAM;
810 else if (!strncmp ("#Blob", ptr, 6))
811 stream_idx = BLOB_STREAM;
812 else if (!strncmp ("#GUID", ptr, 6))
813 stream_idx = GUID_STREAM;
814 else if (!strncmp ("#~", ptr, 3))
815 stream_idx = TILDE_STREAM;
817 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
819 if (ctx->metadata_streams [stream_idx].offset != 0)
820 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
822 ctx->metadata_streams [stream_idx].offset = stream_off;
823 ctx->metadata_streams [stream_idx].size = stream_size;
825 offset = pad4 (offset);
826 ptr = ctx->data + offset;
829 if (!ctx->metadata_streams [TILDE_STREAM].size)
830 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
831 if (!ctx->metadata_streams [GUID_STREAM].size)
832 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
833 if (!ctx->metadata_streams [BLOB_STREAM].size)
834 ADD_ERROR (ctx, g_strdup_printf ("Metadata blob stream missing"));
839 verify_tables_schema (VerifyContext *ctx)
841 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
842 unsigned offset = tables_area.offset;
843 const char *ptr = ctx->data + offset;
844 guint64 valid_tables;
848 //printf ("tables_area size %d offset %x %s\n", tables_area.size, tables_area.offset, ctx->image->name);
849 if (tables_area.size < 24)
850 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
852 //printf ("ptr %x %x\n", ptr[4], ptr[5]);
853 if (ptr [4] != 2 && ptr [4] != 1)
854 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
856 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
858 if ((ptr [6] & ~0x7) != 0)
859 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]));
861 valid_tables = read64 (ptr + 8);
863 for (i = 0; i < 64; ++i) {
864 if (!(valid_tables & ((guint64)1 << i)))
867 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
868 Unused: 0x1E 0x1F 0x2D-0x3F
869 We don't care about the MS extensions.*/
870 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
871 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifies doesn't support MS specific table %x", i));
872 if (i == 0x1E || i == 0x1F || i >= 0x2D)
873 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
877 if (tables_area.size < 24 + count * 4)
878 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));
881 for (i = 0; i < 64; ++i) {
882 if (valid_tables & ((guint64)1 << i)) {
883 guint32 row_count = read32 (ptr);
884 if (row_count > (1 << 24) - 1)
885 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
891 /*----------nothing from here on can use data_directory or metadata_streams ---*/
894 get_col_offset (VerifyContext *ctx, int table, int column)
896 guint32 bitfield = ctx->image->tables [table].size_bitfield;
900 offset += mono_metadata_table_size (bitfield, column);
906 get_col_size (VerifyContext *ctx, int table, int column)
908 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
912 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
915 res.offset = header->data - ctx->data;
916 res.size = header->size;
922 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
924 OffsetAndSize strings = get_metadata_stream (ctx, &ctx->image->heap_strings);
926 const char *data = ctx->data + strings.offset;
928 if (offset >= strings.size)
930 if (data + offset < data) //FIXME, use a generalized and smart unsigned add with overflow check and fix the whole thing
933 if (!mono_utf8_validate_and_len_with_bounds (data + offset, strings.size - offset, &length, NULL))
935 return allow_empty || length > 0;
939 is_valid_string (VerifyContext *ctx, guint32 offset)
941 return is_valid_string_full (ctx, offset, TRUE);
945 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
947 return is_valid_string_full (ctx, offset, FALSE);
951 is_valid_guid (VerifyContext *ctx, guint32 offset)
953 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
954 return guids.size >= 8 && guids.size - 8 >= offset;
958 get_coded_index_token (int token_kind, guint32 coded_token)
960 guint32 bits = coded_index_desc [token_kind];
961 return coded_token >> bits;
965 get_coded_index_table (int kind, guint32 coded_token)
967 guint32 idx, bits = coded_index_desc [kind];
969 idx = coded_token & ((1 << bits) - 1);
970 return coded_index_desc [kind + idx];
974 make_coded_token (int kind, guint32 table, guint32 table_idx)
976 guint32 bits = coded_index_desc [kind++];
977 guint32 tables = coded_index_desc [kind++];
979 for (i = 0; i < tables; ++i) {
980 if (coded_index_desc [kind++] == table)
981 return ((table_idx + 1) << bits) | i;
983 g_assert_not_reached ();
988 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
990 guint32 bits = coded_index_desc [token_kind++];
991 guint32 table_count = coded_index_desc [token_kind++];
992 guint32 table = coded_token & ((1 << bits) - 1);
993 guint32 token = coded_token >> bits;
995 if (table >= table_count)
998 /*token_kind points to the first table idx*/
999 table = coded_index_desc [token_kind + table];
1001 if (table == INVALID_TABLE)
1003 return token <= ctx->image->tables [table].rows;
1010 MonoTableInfo *table;
1014 token_locator (const void *a, const void *b)
1016 RowLocator *loc = (RowLocator *)a;
1017 unsigned const char *row = (unsigned const char *)b;
1018 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1020 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1021 return (int)loc->token - (int)token;
1025 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1027 MonoTableInfo *tinfo = &ctx->image->tables [table];
1029 const char *res, *base;
1030 locator.token = coded_token;
1031 locator.col_offset = get_col_offset (ctx, table, column);
1032 locator.col_size = get_col_size (ctx, table, column);
1033 locator.table = tinfo;
1037 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) );
1038 res = bsearch (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1042 return (res - base) / tinfo->row_size;
1045 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1047 get_string_ptr (VerifyContext *ctx, guint offset)
1049 return ctx->image->heap_strings.data + offset;
1052 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1054 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1057 return strcmp (str, "");
1059 return strcmp (str, get_string_ptr (ctx, offset));
1063 mono_verifier_is_corlib (MonoImage *image)
1065 gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
1066 TRUE : mono_security_core_clr_is_platform_image (image);
1068 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1072 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1074 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1078 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1081 const unsigned char *ptr = (const unsigned char *)_ptr;
1089 if ((b & 0x80) == 0) {
1092 } else if ((b & 0x40) == 0) {
1096 *value = ((b & 0x3f) << 8 | ptr [1]);
1101 *value = ((b & 0x1f) << 24) |
1111 decode_signature_header (VerifyContext *ctx, guint32 offset, int *size, const char **first_byte)
1113 MonoStreamHeader blob = ctx->image->heap_blob;
1114 guint32 value, enc_size;
1116 if (offset >= blob.size)
1119 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1122 if (offset + enc_size + value < offset)
1125 if (offset + enc_size + value > blob.size)
1129 *first_byte = blob.data + offset + enc_size;
1134 safe_read (const char **_ptr, const char *limit, unsigned *dest, int size)
1136 const char *ptr = *_ptr;
1137 if (ptr + size > limit)
1141 *dest = *((guint8*)ptr);
1145 *dest = read16 (ptr);
1149 *dest = read32 (ptr);
1158 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1161 const char *ptr = *_ptr;
1162 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1167 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1168 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1169 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1170 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1173 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1176 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1179 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1181 const char *ptr = *_ptr;
1186 if (!safe_read8 (type, ptr, end))
1187 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1189 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1194 if (!safe_read_cint (token, ptr, end))
1195 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1197 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1198 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1206 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1208 const char *ptr = *_ptr;
1210 unsigned size, num, i;
1212 if (!safe_read8 (val, ptr, end))
1213 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1216 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1218 if (!safe_read_cint (size, ptr, end))
1219 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1221 for (i = 0; i < size; ++i) {
1222 if (!safe_read_cint (num, ptr, end))
1223 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1226 if (!safe_read_cint (size, ptr, end))
1227 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1229 for (i = 0; i < size; ++i) {
1230 if (!safe_read_cint (num, ptr, end))
1231 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1239 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1241 const char *ptr = *_ptr;
1243 unsigned count, token, i;
1245 if (!safe_read8 (type, ptr, end))
1246 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1248 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1249 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1251 if (!safe_read_cint (token, ptr, end))
1252 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1254 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1255 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1257 if (!safe_read_cint (count, ptr, end))
1258 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1261 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1263 for (i = 0; i < count; ++i) {
1264 if (!parse_type (ctx, &ptr, end))
1265 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1272 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1274 const char *ptr = *_ptr;
1278 if (!safe_read8 (type, ptr, end))
1279 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1281 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1282 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1283 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1284 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1285 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1289 if (!parse_custom_mods (ctx, &ptr, end))
1290 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1292 if (!safe_read8 (type, ptr, end))
1293 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1295 if (type != MONO_TYPE_VOID) {
1297 if (!parse_type (ctx, &ptr, end))
1298 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1302 case MONO_TYPE_VALUETYPE:
1303 case MONO_TYPE_CLASS:
1304 if (!safe_read_cint (token, ptr, end))
1305 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1307 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1308 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1312 case MONO_TYPE_MVAR:
1313 if (!safe_read_cint (token, ptr, end))
1314 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1317 case MONO_TYPE_ARRAY:
1318 if (!parse_type (ctx, &ptr, end))
1319 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1320 if (!parse_array_shape (ctx, &ptr, end))
1321 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1324 case MONO_TYPE_GENERICINST:
1325 if (!parse_generic_inst (ctx, &ptr, end))
1326 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1329 case MONO_TYPE_FNPTR:
1330 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1331 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1334 case MONO_TYPE_SZARRAY:
1335 if (!parse_custom_mods (ctx, &ptr, end))
1336 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1337 if (!parse_type (ctx, &ptr, end))
1338 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1346 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1351 if (!parse_custom_mods (ctx, _ptr, end))
1355 if (!safe_read8 (type, ptr, end))
1356 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1358 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1363 //it's a byref, update the cursor ptr
1364 if (type == MONO_TYPE_BYREF)
1367 return parse_type (ctx, _ptr, end);
1371 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1376 if (!parse_custom_mods (ctx, _ptr, end))
1380 if (!safe_read8 (type, ptr, end))
1381 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1383 if (type == MONO_TYPE_TYPEDBYREF) {
1388 //it's a byref, update the cursor ptr
1389 if (type == MONO_TYPE_BYREF)
1392 return parse_type (ctx, _ptr, end);
1396 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1399 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1400 const char *ptr = *_ptr;
1401 gboolean saw_sentinel = FALSE;
1403 if (!safe_read8 (cconv, ptr, end))
1404 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1407 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1409 if (allow_unmanaged) {
1410 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1411 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1412 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1413 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1415 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1416 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1418 if ((cconv & 0x10) && gparam_count == 0)
1419 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1421 if (allow_unmanaged && (cconv & 0x10))
1422 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1424 if (!safe_read_cint (param_count, ptr, end))
1425 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1427 if (!parse_return_type (ctx, &ptr, end))
1428 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1430 for (i = 0; i < param_count; ++i) {
1431 if (allow_sentinel) {
1432 if (!safe_read8 (type, ptr, end))
1433 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1435 if (type == MONO_TYPE_SENTINEL) {
1436 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1437 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1440 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1442 saw_sentinel = TRUE;
1448 if (!parse_param (ctx, &ptr, end))
1449 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1457 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1460 unsigned param_count = 0, i;
1461 const char *ptr = *_ptr;
1463 if (!safe_read8 (sig, ptr, end))
1464 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1466 if (sig != 0x08 && sig != 0x28)
1467 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1469 if (!safe_read_cint (param_count, ptr, end))
1470 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1472 if (!parse_custom_mods (ctx, &ptr, end))
1475 if (!parse_type (ctx, &ptr, end))
1476 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1478 for (i = 0; i < param_count; ++i) {
1479 if (!parse_type (ctx, &ptr, end))
1480 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1488 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1490 const char *ptr = *_ptr;
1491 unsigned signature = 0;
1493 if (!safe_read8 (signature, ptr, end))
1494 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1496 if (signature != 0x06)
1497 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1499 if (!parse_custom_mods (ctx, &ptr, end))
1502 if (safe_read8 (signature, ptr, end)) {
1503 if (signature != MONO_TYPE_BYREF)
1508 return parse_type (ctx, _ptr, end);
1512 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1515 unsigned locals_count = 0, i;
1516 const char *ptr = *_ptr;
1518 if (!safe_read8 (sig, ptr, end))
1519 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1522 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1524 if (!safe_read_cint (locals_count, ptr, end))
1525 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1527 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1528 if (locals_count == 0)
1529 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1532 for (i = 0; i < locals_count; ++i) {
1533 if (!safe_read8 (sig, ptr, end))
1534 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1536 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1537 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1538 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1539 if (!safe_read8 (sig, ptr, end))
1540 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1543 if (sig == MONO_TYPE_BYREF) {
1544 if (!safe_read8 (sig, ptr, end))
1545 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1546 if (sig == MONO_TYPE_TYPEDBYREF)
1547 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1550 if (sig == MONO_TYPE_TYPEDBYREF)
1555 if (!parse_type (ctx, &ptr, end))
1556 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1564 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1567 unsigned signature = 0;
1568 const char *ptr = NULL, *end;
1570 if (!decode_signature_header (ctx, offset, &size, &ptr))
1571 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1574 if (!safe_read8 (signature, ptr, end))
1575 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1578 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1581 return parse_field (ctx, &ptr, end);
1585 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1588 const char *ptr = NULL, *end;
1590 if (!decode_signature_header (ctx, offset, &size, &ptr))
1591 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1594 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1598 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1601 unsigned signature = 0;
1602 const char *ptr = NULL, *end;
1604 if (!decode_signature_header (ctx, offset, &size, &ptr))
1605 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1608 if (!safe_read8 (signature, ptr, end))
1609 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1612 if (signature == 0x06)
1613 return parse_field (ctx, &ptr, end);
1615 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1619 is_vald_cattr_blob (VerifyContext *ctx, guint32 offset)
1622 unsigned prolog = 0;
1623 const char *ptr = NULL, *end;
1628 if (!decode_signature_header (ctx, offset, &size, &ptr))
1629 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1632 if (!safe_read16 (prolog, ptr, end))
1633 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1636 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1642 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
1644 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1645 //TODO do proper verification
1646 return blob.size >= 1 && blob.size - 1 >= offset;
1650 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
1652 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1653 //TODO do proper verification
1654 return blob.size >= 1 && blob.size - 1 >= offset;
1658 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
1661 unsigned signature = 0;
1662 const char *ptr = NULL, *end;
1664 if (!decode_signature_header (ctx, offset, &size, &ptr))
1665 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
1668 if (!safe_read8 (signature, ptr, end))
1669 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
1672 if (signature == 0x07)
1673 return parse_locals_signature (ctx, &ptr, end);
1674 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
1678 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
1681 const char *ptr = NULL, *end;
1683 if (!decode_signature_header (ctx, offset, &size, &ptr))
1684 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
1687 return parse_property_signature (ctx, &ptr, end);
1691 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
1694 const char *ptr = NULL, *end;
1698 if (!decode_signature_header (ctx, offset, &size, &ptr))
1699 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
1702 if (!parse_custom_mods (ctx, &ptr, end))
1705 if (!safe_read8 (type, ptr, end))
1706 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
1708 if (type == MONO_TYPE_BYREF) {
1709 if (!safe_read8 (type, ptr, end))
1710 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
1711 if (type == MONO_TYPE_TYPEDBYREF)
1712 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
1715 if (type == MONO_TYPE_TYPEDBYREF)
1719 return parse_type (ctx, &ptr, end);
1723 is_valid_methodspec_blog (VerifyContext *ctx, guint32 offset)
1726 const char *ptr = NULL, *end;
1728 unsigned count = 0, i;
1730 if (!decode_signature_header (ctx, offset, &size, &ptr))
1731 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
1734 if (!safe_read8 (type, ptr, end))
1735 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
1738 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
1740 if (!safe_read_cint (count, ptr, end))
1741 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
1744 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
1746 for (i = 0; i < count; ++i) {
1747 if (!parse_type (ctx, &ptr, end))
1748 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
1754 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
1756 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1757 guint32 entry_size, bytes;
1759 if (blob.size < offset)
1762 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1765 if (entry_size < minsize)
1768 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
1770 entry_size += bytes;
1772 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
1776 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
1778 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1779 guint32 size, entry_size, bytes;
1781 if (blob.size < offset)
1782 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
1784 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1785 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
1787 if (type == MONO_TYPE_STRING) {
1788 //String is encoded as: compressed_int:len len *bytes
1791 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
1792 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
1798 case MONO_TYPE_BOOLEAN:
1803 case MONO_TYPE_CHAR:
1811 case MONO_TYPE_CLASS:
1821 g_assert_not_reached ();
1824 if (size != entry_size)
1825 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
1829 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
1830 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
1832 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
1833 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
1837 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
1838 //only 0x01, 0x40 and 0x80 are allowed
1839 #define SECTION_HEADER_INVALID_FLAGS 0x3E
1842 is_valid_method_header (VerifyContext *ctx, guint32 rva)
1844 unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
1845 unsigned header = 0;
1846 unsigned fat_header = 0, size = 0, max_stack;
1847 const char *ptr = NULL, *end;
1849 if (offset == INVALID_ADDRESS)
1850 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
1852 ptr = ctx->data + offset;
1853 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
1855 if (!safe_read8 (header, ptr, end))
1856 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
1858 switch (header & 0x3) {
1861 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
1864 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
1865 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
1870 if (!safe_read16 (fat_header, ptr, end))
1871 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
1873 size = (fat_header >> 12) & 0xF;
1875 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
1877 if (!safe_read16 (max_stack, ptr, end))
1878 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
1880 if (!safe_read32 (code_size, ptr, end))
1881 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
1883 if (!safe_read32 (local_vars_tok, ptr, end))
1884 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
1886 if (local_vars_tok) {
1887 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
1888 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
1889 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
1890 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
1893 if (fat_header & FAT_HEADER_INVALID_FLAGS)
1894 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
1896 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
1897 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
1899 if (!(fat_header & 0x08))
1905 unsigned section_header = 0, section_size = 0;
1908 ptr = dword_align (ptr);
1909 if (!safe_read32 (section_header, ptr, end))
1910 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
1912 if (section_header & SECTION_HEADER_INVALID_FLAGS)
1913 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
1915 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
1916 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
1918 if (section_size < 4)
1919 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
1921 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
1922 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
1924 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
1925 guint32 i, clauses = (section_size - 4) / (is_fat ? 24 : 12);
1926 if (clauses * (is_fat ? 24 : 12) + 4 != section_size)
1927 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the proper size", section_size));
1929 /* only verify the class token is verified as the rest is done by the IL verifier*/
1930 for (i = 0; i < clauses; ++i) {
1931 unsigned flags = *(unsigned char*)ptr;
1932 unsigned class_token = 0;
1933 ptr += (is_fat ? 20 : 8);
1934 if (!safe_read32 (class_token, ptr, end))
1935 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
1936 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
1937 guint table = mono_metadata_token_table (class_token);
1938 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
1939 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
1940 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
1941 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
1946 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
1953 verify_module_table (VerifyContext *ctx)
1955 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
1956 guint32 data [MONO_MODULE_SIZE];
1958 if (table->rows != 1)
1959 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
1961 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
1963 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
1964 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
1966 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
1967 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
1969 if (data [MONO_MODULE_ENC] != 0)
1970 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
1972 if (data [MONO_MODULE_ENCBASE] != 0)
1973 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
1977 verify_typeref_table (VerifyContext *ctx)
1979 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
1980 guint32 data [MONO_TYPEREF_SIZE];
1983 for (i = 0; i < table->rows; ++i) {
1984 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
1985 if (!is_valid_coded_index (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1986 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i, data [MONO_TYPEREF_SCOPE]));
1988 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1989 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i));
1991 if (!data [MONO_TYPEREF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAME]))
1992 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d name token 0x%08x", i, data [MONO_TYPEREF_NAME]));
1994 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
1995 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d namespace token 0x%08x", i, data [MONO_TYPEREF_NAMESPACE]));
1999 /*bits 9,11,14,15,19,21,24-31 */
2000 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2002 verify_typedef_table (VerifyContext *ctx)
2004 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2005 guint32 data [MONO_TYPEDEF_SIZE];
2006 guint32 fieldlist = 1, methodlist = 1;
2009 if (table->rows == 0)
2010 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2012 for (i = 0; i < table->rows; ++i) {
2013 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2014 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2015 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2017 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2018 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2020 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2021 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2023 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2024 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2026 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2027 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2029 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2030 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2032 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2033 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2035 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2036 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2038 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2039 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2041 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2042 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2044 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2045 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));
2047 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2048 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2050 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2051 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2053 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2054 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));
2056 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2057 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2062 verify_typedef_table_full (VerifyContext *ctx)
2064 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2065 guint32 data [MONO_TYPEDEF_SIZE];
2068 if (table->rows == 0)
2069 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2071 for (i = 0; i < table->rows; ++i) {
2072 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2075 if (data [MONO_TYPEDEF_EXTENDS] != 0)
2076 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2080 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2081 if (data [MONO_TYPEDEF_EXTENDS])
2082 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2084 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2085 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2089 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2092 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2100 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2102 verify_field_table (VerifyContext *ctx)
2104 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2105 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2108 module_field_list = (guint32)-1;
2109 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2110 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2111 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2114 for (i = 0; i < table->rows; ++i) {
2115 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2116 flags = data [MONO_FIELD_FLAGS];
2118 if (flags & INVALID_FIELD_FLAG_BITS)
2119 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2121 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2122 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2124 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2125 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2127 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2128 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2130 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2131 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2133 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2134 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2135 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2137 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2138 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2139 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2141 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2142 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2143 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2145 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2146 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2147 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2149 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2150 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2152 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2153 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2155 //TODO verify contant flag
2157 if (i + 1 < module_field_list) {
2158 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2159 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2160 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2161 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2162 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2168 verify_field_table_full (VerifyContext *ctx)
2170 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2171 guint32 data [MONO_FIELD_SIZE];
2174 for (i = 0; i < table->rows; ++i) {
2175 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2177 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2178 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2182 /*bits 6,8,9,10,11,13,14,15*/
2183 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2185 verify_method_table (VerifyContext *ctx)
2187 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2188 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2189 guint32 paramlist = 1;
2190 gboolean is_ctor, is_cctor;
2194 module_method_list = (guint32)-1;
2195 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2196 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2197 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2200 for (i = 0; i < table->rows; ++i) {
2201 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2202 rva = data [MONO_METHOD_RVA];
2203 implflags = data [MONO_METHOD_IMPLFLAGS];
2204 flags = data [MONO_METHOD_FLAGS];
2205 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2206 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2209 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2210 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2213 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2215 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2216 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2218 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2219 is_ctor = !strcmp (".ctor", name);
2220 is_cctor = !strcmp (".cctor", name);
2222 if ((is_ctor || is_cctor) &&
2223 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2224 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2226 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2227 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2229 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2230 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2231 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2232 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2233 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2236 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2237 ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2239 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2240 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2242 //XXX no checks against cas stuff 10,11,12,13)
2244 //TODO check iface with .ctor (15,16)
2246 if (i + 1 < module_method_list) {
2247 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2248 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2249 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2250 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2251 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2252 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2255 //TODO check valuetype for synchronized
2257 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2258 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2260 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (flags & METHOD_ATTRIBUTE_VIRTUAL))
2261 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2263 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2264 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2265 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2267 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2268 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2270 //TODO check signature contents
2273 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2274 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2275 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2276 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2278 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2279 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2282 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2284 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2285 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2286 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2288 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2289 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2291 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2292 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2294 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2295 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2297 if (data [MONO_METHOD_PARAMLIST] == 0)
2298 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2300 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2301 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));
2303 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2304 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2306 paramlist = data [MONO_METHOD_PARAMLIST];
2312 verify_method_table_full (VerifyContext *ctx)
2314 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2315 guint32 data [MONO_METHOD_SIZE], rva;
2318 for (i = 0; i < table->rows; ++i) {
2319 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2320 rva = data [MONO_METHOD_RVA];
2322 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2323 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2325 if (rva && !is_valid_method_header (ctx, rva))
2326 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2331 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2333 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2334 guint32 row = *current_method;
2335 guint32 paramlist, tmp;
2338 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2339 while (row < table->rows) {
2340 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2341 if (tmp > paramlist) {
2342 *current_method = row;
2343 return tmp - paramlist;
2348 /*no more methods, all params apply to the last one*/
2349 *current_method = table->rows;
2354 #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))
2356 verify_param_table (VerifyContext *ctx)
2358 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2359 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2360 gboolean first_param = TRUE;
2363 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2364 if (table->rows > 0)
2365 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2369 remaining_params = get_next_param_count (ctx, ¤t_method);
2371 for (i = 0; i < table->rows; ++i) {
2372 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2373 flags = data [MONO_PARAM_FLAGS];
2375 if (flags & INVALID_PARAM_FLAGS_BITS)
2376 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2378 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2379 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2380 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2382 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2383 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2386 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)
2387 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2389 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2390 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2392 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2393 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2395 first_param = FALSE;
2396 sequence = data [MONO_PARAM_SEQUENCE];
2397 if (--remaining_params == 0) {
2398 remaining_params = get_next_param_count (ctx, ¤t_method);
2405 verify_interfaceimpl_table (VerifyContext *ctx)
2407 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2408 guint32 data [MONO_INTERFACEIMPL_SIZE];
2411 for (i = 0; i < table->rows; ++i) {
2412 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2413 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2414 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2416 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2417 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2419 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2420 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2425 verify_memberref_table (VerifyContext *ctx)
2427 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2428 guint32 data [MONO_MEMBERREF_SIZE];
2431 for (i = 0; i < table->rows; ++i) {
2432 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2434 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2435 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2437 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2438 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2440 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2441 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2443 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2444 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2450 verify_memberref_table_full (VerifyContext *ctx)
2452 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2453 guint32 data [MONO_MEMBERREF_SIZE];
2456 for (i = 0; i < table->rows; ++i) {
2457 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2459 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2460 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2465 verify_constant_table (VerifyContext *ctx)
2467 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2468 guint32 data [MONO_CONSTANT_SIZE], type;
2471 for (i = 0; i < table->rows; ++i) {
2472 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2473 type = data [MONO_CONSTANT_TYPE];
2475 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2476 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2478 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2479 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2481 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2482 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2484 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2485 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2490 verify_cattr_table (VerifyContext *ctx)
2492 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2493 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2496 for (i = 0; i < table->rows; ++i) {
2497 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2499 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2500 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2502 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2503 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2505 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2506 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2511 verify_cattr_table_full (VerifyContext *ctx)
2513 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2514 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2517 for (i = 0; i < table->rows; ++i) {
2518 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2520 if (!is_vald_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2521 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2526 verify_field_marshal_table (VerifyContext *ctx)
2528 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2529 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2532 for (i = 0; i < table->rows; ++i) {
2533 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2535 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2536 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2538 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2539 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2541 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2542 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2544 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2545 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2550 verify_field_marshal_table_full (VerifyContext *ctx)
2552 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2553 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2556 for (i = 0; i < table->rows; ++i) {
2557 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2559 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2560 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2565 verify_decl_security_table (VerifyContext *ctx)
2567 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2568 guint32 data [MONO_DECL_SECURITY_SIZE];
2571 for (i = 0; i < table->rows; ++i) {
2572 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2574 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2575 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2577 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2578 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
2580 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
2581 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
2586 verify_decl_security_table_full (VerifyContext *ctx)
2588 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2589 guint32 data [MONO_DECL_SECURITY_SIZE];
2592 for (i = 0; i < table->rows; ++i) {
2593 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2595 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
2596 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
2601 verify_class_layout_table (VerifyContext *ctx)
2603 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
2604 guint32 data [MONO_CLASS_LAYOUT_SIZE];
2607 for (i = 0; i < table->rows; ++i) {
2608 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
2610 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2611 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2613 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
2625 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
2631 verify_field_layout_table (VerifyContext *ctx)
2633 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
2634 guint32 data [MONO_FIELD_LAYOUT_SIZE];
2637 for (i = 0; i < table->rows; ++i) {
2638 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
2640 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2641 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
2646 verify_standalonesig_table (VerifyContext *ctx)
2648 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2649 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2652 for (i = 0; i < table->rows; ++i) {
2653 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2655 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
2656 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2661 verify_standalonesig_table_full (VerifyContext *ctx)
2663 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2664 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2667 for (i = 0; i < table->rows; ++i) {
2668 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2670 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
2671 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2676 verify_eventmap_table (VerifyContext *ctx)
2678 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
2679 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
2682 for (i = 0; i < table->rows; ++i) {
2683 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
2685 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2686 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
2688 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
2689 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
2691 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
2695 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
2697 verify_event_table (VerifyContext *ctx)
2699 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2700 guint32 data [MONO_EVENT_SIZE];
2703 for (i = 0; i < table->rows; ++i) {
2704 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2706 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
2707 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
2709 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
2710 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
2712 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
2713 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
2718 verify_event_table_full (VerifyContext *ctx)
2720 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2721 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
2722 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
2723 gboolean found_add, found_remove;
2726 for (i = 0; i < table->rows; ++i) {
2727 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2729 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
2730 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
2732 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
2734 //first we move to the first row for this event
2736 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
2740 //now move forward looking for AddOn and RemoveOn rows
2741 found_add = found_remove = FALSE;
2742 while (idx < sema_table->rows) {
2743 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
2744 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
2746 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
2748 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
2749 found_remove = TRUE;
2750 if (found_add && found_remove)
2756 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2758 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2763 verify_propertymap_table (VerifyContext *ctx)
2765 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
2766 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
2769 for (i = 0; i < table->rows; ++i) {
2770 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
2772 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2773 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
2775 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
2776 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
2778 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
2782 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
2784 verify_property_table (VerifyContext *ctx)
2786 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
2787 guint32 data [MONO_PROPERTY_SIZE];
2790 for (i = 0; i < table->rows; ++i) {
2791 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
2793 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
2794 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
2796 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
2797 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
2799 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
2800 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
2802 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
2803 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
2804 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
2810 verify_methodimpl_table (VerifyContext *ctx)
2812 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
2813 guint32 data [MONO_METHODIMPL_SIZE];
2816 for (i = 0; i < table->rows; ++i) {
2817 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
2819 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2820 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2822 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2823 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2825 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2826 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2828 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2829 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2831 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2832 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2837 verify_moduleref_table (VerifyContext *ctx)
2839 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
2840 guint32 data [MONO_MODULEREF_SIZE];
2843 for (i = 0; i < table->rows; ++i) {
2844 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
2846 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
2847 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2852 verify_typespec_table (VerifyContext *ctx)
2854 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2855 guint32 data [MONO_TYPESPEC_SIZE];
2858 for (i = 0; i < table->rows; ++i) {
2859 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2861 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
2862 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2867 verify_typespec_table_full (VerifyContext *ctx)
2869 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2870 guint32 data [MONO_TYPESPEC_SIZE];
2873 for (i = 0; i < table->rows; ++i) {
2874 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2876 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
2877 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2881 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10))
2883 verify_implmap_table (VerifyContext *ctx)
2885 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
2886 guint32 data [MONO_IMPLMAP_SIZE], cconv;
2889 for (i = 0; i < table->rows; ++i) {
2890 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
2892 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
2893 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
2895 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
2896 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
2897 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
2899 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2900 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
2902 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
2903 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
2905 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2906 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
2908 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
2909 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
2911 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows + 1)
2912 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
2917 verify_fieldrva_table (VerifyContext *ctx)
2919 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
2920 guint32 data [MONO_FIELD_RVA_SIZE];
2923 for (i = 0; i < table->rows; ++i) {
2924 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
2926 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
2927 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
2929 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2930 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
2934 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
2936 verify_assembly_table (VerifyContext *ctx)
2938 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
2939 guint32 data [MONO_ASSEMBLY_SIZE], hash;
2942 if (table->rows > 1)
2943 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
2945 for (i = 0; i < table->rows; ++i) {
2946 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
2948 hash = data [MONO_ASSEMBLY_HASH_ALG];
2949 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
2950 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
2952 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
2953 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2955 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
2956 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2958 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
2959 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
2961 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
2962 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
2966 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
2968 verify_assemblyref_table (VerifyContext *ctx)
2970 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
2971 guint32 data [MONO_ASSEMBLYREF_SIZE];
2974 for (i = 0; i < table->rows; ++i) {
2975 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
2977 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
2978 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
2980 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
2981 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
2983 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
2984 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
2986 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
2987 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
2989 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
2990 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
2994 #define INVALID_FILE_FLAGS_BITS ~(1)
2996 verify_file_table (VerifyContext *ctx)
2998 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
2999 guint32 data [MONO_FILE_SIZE];
3002 for (i = 0; i < table->rows; ++i) {
3003 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3005 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3006 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3008 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3009 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3011 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3012 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3016 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3018 verify_exportedtype_table (VerifyContext *ctx)
3020 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3021 guint32 data [MONO_EXP_TYPE_SIZE];
3024 for (i = 0; i < table->rows; ++i) {
3025 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3027 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3028 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3030 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3031 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3033 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3034 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3036 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3037 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3039 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3040 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3042 /*nested type can't have a namespace*/
3043 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3044 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3048 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3050 verify_manifest_resource_table (VerifyContext *ctx)
3052 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3053 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3054 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3055 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3058 resources_size = ch->ch_resources.size;
3060 for (i = 0; i < table->rows; ++i) {
3061 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3063 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3064 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3066 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3067 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3069 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3070 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3072 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3073 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3075 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3076 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3078 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3079 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])));
3081 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3082 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3084 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3085 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3090 verify_nested_class_table (VerifyContext *ctx)
3092 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3093 guint32 data [MONO_NESTED_CLASS_SIZE];
3096 for (i = 0; i < table->rows; ++i) {
3097 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3099 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3100 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3101 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3102 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3103 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3104 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3108 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3110 verify_generic_param_table (VerifyContext *ctx)
3112 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3113 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3114 int i, param_number = 0;
3116 for (i = 0; i < table->rows; ++i) {
3117 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3119 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3120 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3122 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3123 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3125 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3126 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3128 token = data [MONO_GENERICPARAM_OWNER];
3130 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3131 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3133 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3134 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3136 if (token != last_token) {
3141 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3142 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));
3149 verify_method_spec_table (VerifyContext *ctx)
3151 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3152 guint32 data [MONO_METHODSPEC_SIZE];
3155 for (i = 0; i < table->rows; ++i) {
3156 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3158 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3159 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3161 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3162 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3164 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3165 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3170 verify_method_spec_table_full (VerifyContext *ctx)
3172 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3173 guint32 data [MONO_METHODSPEC_SIZE];
3176 for (i = 0; i < table->rows; ++i) {
3177 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3179 if (!is_valid_methodspec_blog (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3180 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3185 verify_generic_param_constraint_table (VerifyContext *ctx)
3187 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3188 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3191 for (i = 0; i < table->rows; ++i) {
3192 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3194 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3195 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_TABLE_GENERICPARAM]));
3197 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3198 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3200 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3201 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3206 verify_tables_data (VerifyContext *ctx)
3208 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3209 guint32 size = 0, tables_offset;
3212 for (i = 0; i < 0x2D; ++i) {
3213 MonoTableInfo *table = &ctx->image->tables [i];
3215 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3216 if (tmp_size < size) {
3224 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3226 tables_offset = ctx->image->tables_base - ctx->data;
3227 if (!bounds_check_offset (&tables_area, tables_offset, size))
3228 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)));
3230 verify_module_table (ctx);
3232 verify_typeref_table (ctx);
3234 verify_typedef_table (ctx);
3236 verify_field_table (ctx);
3238 verify_method_table (ctx);
3240 verify_param_table (ctx);
3242 verify_interfaceimpl_table (ctx);
3244 verify_memberref_table (ctx);
3246 verify_constant_table (ctx);
3248 verify_cattr_table (ctx);
3250 verify_field_marshal_table (ctx);
3252 verify_decl_security_table (ctx);
3254 verify_class_layout_table (ctx);
3256 verify_field_layout_table (ctx);
3258 verify_standalonesig_table (ctx);
3260 verify_eventmap_table (ctx);
3262 verify_event_table (ctx);
3264 verify_propertymap_table (ctx);
3266 verify_property_table (ctx);
3268 verify_methodimpl_table (ctx);
3270 verify_moduleref_table (ctx);
3272 verify_typespec_table (ctx);
3274 verify_implmap_table (ctx);
3276 verify_fieldrva_table (ctx);
3278 verify_assembly_table (ctx);
3280 verify_assemblyref_table (ctx);
3282 verify_file_table (ctx);
3284 verify_exportedtype_table (ctx);
3286 verify_manifest_resource_table (ctx);
3288 verify_nested_class_table (ctx);
3290 verify_generic_param_table (ctx);
3292 verify_method_spec_table (ctx);
3294 verify_generic_param_constraint_table (ctx);
3298 init_verify_context (VerifyContext *ctx, MonoImage *image, GSList **error_list)
3300 memset (ctx, 0, sizeof (VerifyContext));
3302 ctx->report_error = error_list != NULL;
3303 ctx->report_warning = FALSE; //export this setting in the API
3305 ctx->size = image->raw_data_len;
3306 ctx->data = image->raw_data;
3310 cleanup_context (VerifyContext *ctx, GSList **error_list)
3312 g_free (ctx->sections);
3314 *error_list = ctx->errors;
3316 mono_free_verify_list (ctx->errors);
3321 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3325 if (!mono_verifier_is_enabled_for_image (image))
3328 init_verify_context (&ctx, image, error_list);
3329 ctx.stage = STAGE_PE;
3331 verify_msdos_header (&ctx);
3333 verify_pe_header (&ctx);
3335 verify_pe_optional_header (&ctx);
3337 load_section_table (&ctx);
3339 load_data_directories (&ctx);
3341 verify_import_table (&ctx);
3343 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3344 verify_resources_table (&ctx);
3347 return cleanup_context (&ctx, error_list);
3351 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3355 if (!mono_verifier_is_enabled_for_image (image))
3358 init_verify_context (&ctx, image, error_list);
3359 ctx.stage = STAGE_CLI;
3361 verify_cli_header (&ctx);
3363 verify_metadata_header (&ctx);
3365 verify_tables_schema (&ctx);
3368 return cleanup_context (&ctx, error_list);
3373 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3374 * Other verification checks are meant to be done lazily by the runtime. Those include:
3375 * blob items (signatures, method headers, custom attributes, etc)
3376 * type semantics related
3378 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3380 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3381 * operation still need more checking.
3384 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3388 if (!mono_verifier_is_enabled_for_image (image))
3391 init_verify_context (&ctx, image, error_list);
3392 ctx.stage = STAGE_TABLES;
3394 verify_tables_data (&ctx);
3396 return cleanup_context (&ctx, error_list);
3401 * Verifies all other constraints.
3404 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3408 if (!mono_verifier_is_enabled_for_image (image))
3411 init_verify_context (&ctx, image, error_list);
3412 ctx.stage = STAGE_TABLES;
3414 verify_typedef_table_full (&ctx);
3416 verify_field_table_full (&ctx);
3418 verify_method_table_full (&ctx);
3420 verify_memberref_table_full (&ctx);
3422 verify_cattr_table_full (&ctx);
3424 verify_field_marshal_table_full (&ctx);
3426 verify_decl_security_table_full (&ctx);
3428 verify_standalonesig_table_full (&ctx);
3430 verify_event_table_full (&ctx);
3432 verify_typespec_table_full (&ctx);
3434 verify_method_spec_table_full (&ctx);
3437 return cleanup_context (&ctx, error_list);
3441 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3445 if (!mono_verifier_is_enabled_for_image (image))
3448 init_verify_context (&ctx, image, error_list);
3449 ctx.stage = STAGE_TABLES;
3451 is_valid_field_signature (&ctx, offset);
3452 return cleanup_context (&ctx, error_list);
3456 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3460 if (!mono_verifier_is_enabled_for_image (image))
3463 init_verify_context (&ctx, image, error_list);
3464 ctx.stage = STAGE_TABLES;
3466 is_valid_method_header (&ctx, offset);
3467 return cleanup_context (&ctx, error_list);
3471 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3475 if (!mono_verifier_is_enabled_for_image (image))
3478 init_verify_context (&ctx, image, error_list);
3479 ctx.stage = STAGE_TABLES;
3481 is_valid_method_signature (&ctx, offset);
3482 return cleanup_context (&ctx, error_list);
3486 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3490 if (!mono_verifier_is_enabled_for_image (image))
3493 init_verify_context (&ctx, image, error_list);
3494 ctx.stage = STAGE_TABLES;
3496 is_valid_method_or_field_signature (&ctx, offset);
3497 return cleanup_context (&ctx, error_list);
3501 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3505 if (!mono_verifier_is_enabled_for_image (image))
3508 init_verify_context (&ctx, image, error_list);
3509 ctx.stage = STAGE_TABLES;
3511 is_valid_standalonesig_blob (&ctx, offset);
3512 return cleanup_context (&ctx, error_list);
3516 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3520 if (!mono_verifier_is_enabled_for_image (image))
3523 init_verify_context (&ctx, image, error_list);
3524 ctx.stage = STAGE_TABLES;
3526 is_valid_typespec_blob (&ctx, offset);
3527 return cleanup_context (&ctx, error_list);
3531 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3535 if (!mono_verifier_is_enabled_for_image (image))
3538 init_verify_context (&ctx, image, error_list);
3539 ctx.stage = STAGE_TABLES;
3541 is_valid_methodspec_blog (&ctx, offset);
3542 return cleanup_context (&ctx, error_list);
3547 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3553 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3559 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3565 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3571 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3577 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3583 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3589 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3595 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3601 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3607 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3612 #endif /* DISABLE_VERIFIER */