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;
227 DataDirectory data_directories [16];
228 guint32 section_count;
229 SectionHeader *sections;
231 OffsetAndSize metadata_streams [5]; //offset from begin of the image
234 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
236 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
237 vinfo->info.status = __status; \
238 vinfo->info.message = ( __msg); \
239 vinfo->exception_type = (__exception); \
240 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
244 #define ADD_ERROR(__ctx, __msg) \
246 if ((__ctx)->report_error) \
247 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
248 (__ctx)->valid = 0; \
252 #define FAIL(__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 CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
262 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
264 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
265 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
267 #if SIZEOF_VOID_P == 4
268 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
270 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
273 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
274 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
277 dword_align (const char *ptr)
279 #if SIZEOF_VOID_P == 8
280 return (const char *) (((guint64) (ptr + 3)) & ~3);
282 return (const char *) (((guint32) (ptr + 3)) & ~3);
287 pe_signature_offset (VerifyContext *ctx)
289 return read32 (ctx->data + 0x3c);
293 pe_header_offset (VerifyContext *ctx)
295 return read32 (ctx->data + 0x3c) + 4;
299 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
303 if (rva + size < rva) //overflow
306 if (ctx->stage > STAGE_PE) {
307 MonoCLIImageInfo *iinfo = ctx->image->image_info;
308 const int top = iinfo->cli_section_count;
309 MonoSectionTable *tables = iinfo->cli_section_tables;
312 for (i = 0; i < top; i++) {
313 guint32 base = tables->st_virtual_address;
314 guint32 end = base + tables->st_raw_data_size;
316 if (rva >= base && rva + size <= end)
319 /*if ((addr >= tables->st_virtual_address) &&
320 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
322 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
332 for (i = 0; i < ctx->section_count; ++i) {
333 guint32 base = ctx->sections [i].baseRVA;
334 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
335 if (rva >= base && rva + size <= end)
342 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
344 if (dir->translated_offset > offset)
346 if (dir->size < size)
348 return offset + size <= dir->translated_offset + dir->size;
352 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
354 if (off->offset > offset)
357 if (off->size < size)
360 return offset + size <= off->offset + off->size;
364 translate_rva (VerifyContext *ctx, guint32 rva)
368 if (ctx->stage > STAGE_PE)
369 return mono_cli_rva_image_map (ctx->image, rva);
374 for (i = 0; i < ctx->section_count; ++i) {
375 guint32 base = ctx->sections [i].baseRVA;
376 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
377 if (rva >= base && rva <= end) {
378 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
380 return res >= ctx->size ? INVALID_OFFSET : res;
384 return INVALID_OFFSET;
388 verify_msdos_header (VerifyContext *ctx)
392 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
393 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
394 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
395 lfanew = pe_signature_offset (ctx);
396 if (lfanew > ctx->size - 4)
397 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
401 verify_pe_header (VerifyContext *ctx)
403 guint32 offset = pe_signature_offset (ctx);
404 const char *pe_header = ctx->data + offset;
405 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
406 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
410 if (offset > ctx->size - 20)
411 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
412 if (read16 (pe_header) != 0x14c)
413 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
417 verify_pe_optional_header (VerifyContext *ctx)
419 guint32 offset = pe_header_offset (ctx);
420 guint32 header_size, file_alignment;
421 const char *pe_header = ctx->data + offset;
422 const char *pe_optional_header = pe_header + 20;
424 header_size = read16 (pe_header + 16);
427 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
428 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
430 if (offset > ctx->size - header_size || header_size > ctx->size)
431 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
433 if (read16 (pe_optional_header) == 0x10b) {
434 if (header_size != 224)
435 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
437 /* LAMESPEC MS plays around this value and ignore it during validation
438 if (read32 (pe_optional_header + 28) != 0x400000)
439 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
440 if (read32 (pe_optional_header + 32) != 0x2000)
441 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
442 file_alignment = read32 (pe_optional_header + 36);
443 if (file_alignment != 0x200 && file_alignment != 0x1000)
444 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
445 /* All the junk in the middle is irrelevant, specially for mono. */
446 if (read32 (pe_optional_header + 92) > 0x10)
447 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
449 if (read16 (pe_optional_header) == 0x20B)
450 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
452 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
457 load_section_table (VerifyContext *ctx)
460 SectionHeader *sections;
461 guint32 offset = pe_header_offset (ctx);
462 const char *ptr = ctx->data + offset;
463 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
465 offset += 244;/*FIXME, this constant is different under PE32+*/
468 if (num_sections * 40 > ctx->size - offset)
469 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
471 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
472 for (i = 0; i < num_sections; ++i) {
473 sections [i].size = read32 (ptr + 8);
474 sections [i].baseRVA = read32 (ptr + 12);
475 sections [i].baseOffset = read32 (ptr + 20);
476 sections [i].rellocationsRVA = read32 (ptr + 24);
477 sections [i].numberOfRelocations = read16 (ptr + 32);
481 ptr = ctx->data + offset; /*reset it to the beggining*/
482 for (i = 0; i < num_sections; ++i) {
483 guint32 raw_size, flags;
484 if (sections [i].baseOffset == 0)
485 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
486 if (sections [i].baseOffset >= ctx->size)
487 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
488 if (sections [i].size > ctx->size - sections [i].baseOffset)
489 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
491 raw_size = read32 (ptr + 16);
492 if (raw_size < sections [i].size)
493 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
495 if (raw_size > ctx->size - sections [i].baseOffset)
496 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
498 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
499 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
501 flags = read32 (ptr + 36);
502 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
503 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
504 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
511 is_valid_data_directory (int i)
513 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
514 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
518 load_data_directories (VerifyContext *ctx)
520 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
521 const char *ptr = ctx->data + offset;
524 for (i = 0; i < 16; ++i) {
525 guint32 rva = read32 (ptr);
526 guint32 size = read32 (ptr + 4);
528 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
529 if (i == CERTIFICATE_TABLE_IDX) {
533 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
534 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
536 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
537 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
539 ctx->data_directories [i].rva = rva;
540 ctx->data_directories [i].size = size;
541 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
547 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
549 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
552 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
555 guint32 hint_table_rva;
557 import_rva = translate_rva (ctx, import_rva);
558 g_assert (import_rva != INVALID_OFFSET);
560 hint_table_rva = read32 (ctx->data + import_rva);
561 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
562 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
564 hint_table_rva = translate_rva (ctx, hint_table_rva);
565 g_assert (hint_table_rva != INVALID_OFFSET);
566 ptr = ctx->data + hint_table_rva + 2;
568 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
569 char name[SIZE_OF_CORMAIN];
570 memcpy (name, ptr, SIZE_OF_CORMAIN);
571 name [SIZE_OF_CORMAIN - 1] = 0;
572 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
577 verify_import_table (VerifyContext *ctx)
579 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
580 guint32 offset = it.translated_offset;
581 const char *ptr = ctx->data + offset;
582 guint32 name_rva, ilt_rva, iat_rva;
584 g_assert (offset != INVALID_OFFSET);
587 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
589 ilt_rva = read32 (ptr);
590 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
591 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
593 name_rva = read32 (ptr + 12);
594 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
595 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
597 iat_rva = read32 (ptr + 16);
599 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
600 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
602 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
603 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));
607 name_rva = translate_rva (ctx, name_rva);
608 g_assert (name_rva != INVALID_OFFSET);
609 ptr = ctx->data + name_rva;
611 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
612 char name[SIZE_OF_MSCOREE];
613 memcpy (name, ptr, SIZE_OF_MSCOREE);
614 name [SIZE_OF_MSCOREE - 1] = 0;
615 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
620 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
625 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
629 verify_resources_table (VerifyContext *ctx)
631 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
633 guint16 named_entries, id_entries;
634 const char *ptr, *root, *end;
640 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));
642 offset = it.translated_offset;
643 root = ptr = ctx->data + offset;
644 end = root + it.size;
646 g_assert (offset != INVALID_OFFSET);
648 named_entries = read16 (ptr + 12);
649 id_entries = read16 (ptr + 14);
651 if ((named_entries + id_entries) * 8 + 16 > it.size)
652 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));
654 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
655 if (named_entries || id_entries)
656 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
660 /*----------nothing from here on can use data_directory---*/
663 get_data_dir (VerifyContext *ctx, int idx)
665 MonoCLIImageInfo *iinfo = ctx->image->image_info;
666 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
670 res.rva = entry->rva;
671 res.size = entry->size;
672 res.translated_offset = translate_rva (ctx, res.rva);
677 verify_cli_header (VerifyContext *ctx)
679 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
685 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
688 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
690 offset = it.translated_offset;
691 ptr = ctx->data + offset;
693 g_assert (offset != INVALID_OFFSET);
695 if (read16 (ptr) != 72)
696 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
698 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
699 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
702 if (!read32 (ptr + 8) || !read32 (ptr + 12))
703 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
705 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
706 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
709 for (i = 0; i < 6; ++i) {
710 guint32 rva = read32 (ptr);
711 guint32 size = read32 (ptr + 4);
713 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
714 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
719 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
724 pad4 (guint32 offset)
726 if (offset & 0x3) //pad to the next 4 byte boundary
727 offset = (offset & ~0x3) + 4;
732 verify_metadata_header (VerifyContext *ctx)
735 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
739 offset = it.translated_offset;
740 ptr = ctx->data + offset;
741 g_assert (offset != INVALID_OFFSET);
743 //build a directory entry for the metadata root
745 it.rva = read32 (ptr);
747 it.size = read32 (ptr);
748 it.translated_offset = offset = translate_rva (ctx, it.rva);
750 ptr = ctx->data + offset;
751 g_assert (offset != INVALID_OFFSET);
754 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
756 if (read32 (ptr) != 0x424A5342)
757 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
759 offset = pad4 (offset + 16 + read32 (ptr + 12));
761 if (!bounds_check_datadir (&it, offset, 4))
762 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));
764 ptr = ctx->data + offset; //move to streams header
766 if (read16 (ptr + 2) < 3)
767 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 3 streams (#~, #GUID and #Blob"));
772 for (i = 0; i < 5; ++i) {
773 guint32 stream_off, stream_size;
774 int string_size, stream_idx;
776 if (!bounds_check_datadir (&it, offset, 8))
777 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));
779 stream_off = it.translated_offset + read32 (ptr);
780 stream_size = read32 (ptr + 4);
782 if (!bounds_check_datadir (&it, stream_off, stream_size))
783 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
788 for (string_size = 0; string_size < 32; ++string_size) {
789 if (!bounds_check_datadir (&it, offset++, 1))
790 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
791 if (!ptr [string_size])
795 if (ptr [string_size])
796 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
798 if (!strncmp ("#Strings", ptr, 9))
799 stream_idx = STRINGS_STREAM;
800 else if (!strncmp ("#US", ptr, 4))
801 stream_idx = USER_STRINGS_STREAM;
802 else if (!strncmp ("#Blob", ptr, 6))
803 stream_idx = BLOB_STREAM;
804 else if (!strncmp ("#GUID", ptr, 6))
805 stream_idx = GUID_STREAM;
806 else if (!strncmp ("#~", ptr, 3))
807 stream_idx = TILDE_STREAM;
809 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
811 if (ctx->metadata_streams [stream_idx].offset != 0)
812 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
814 ctx->metadata_streams [stream_idx].offset = stream_off;
815 ctx->metadata_streams [stream_idx].size = stream_size;
817 offset = pad4 (offset);
818 ptr = ctx->data + offset;
821 if (!ctx->metadata_streams [TILDE_STREAM].size)
822 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
823 if (!ctx->metadata_streams [GUID_STREAM].size)
824 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
825 if (!ctx->metadata_streams [BLOB_STREAM].size)
826 ADD_ERROR (ctx, g_strdup_printf ("Metadata blob stream missing"));
831 verify_tables_schema (VerifyContext *ctx)
833 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
834 unsigned offset = tables_area.offset;
835 const char *ptr = ctx->data + offset;
836 guint64 valid_tables;
840 //printf ("tables_area size %d offset %x %s\n", tables_area.size, tables_area.offset, ctx->image->name);
841 if (tables_area.size < 24)
842 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
844 //printf ("ptr %x %x\n", ptr[4], ptr[5]);
845 if (ptr [4] != 2 && ptr [4] != 1)
846 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
848 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
850 if ((ptr [6] & ~0x7) != 0)
851 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]));
853 valid_tables = read64 (ptr + 8);
855 for (i = 0; i < 64; ++i) {
856 if (!(valid_tables & ((guint64)1 << i)))
859 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
860 Unused: 0x1E 0x1F 0x2D-0x3F
861 We don't care about the MS extensions.*/
862 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
863 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifies doesn't support MS specific table %x", i));
864 if (i == 0x1E || i == 0x1F || i >= 0x2D)
865 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
869 if (tables_area.size < 24 + count * 4)
870 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));
873 for (i = 0; i < 64; ++i) {
874 if (valid_tables & ((guint64)1 << i)) {
875 guint32 row_count = read32 (ptr);
876 if (row_count > (1 << 24) - 1)
877 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
883 /*----------nothing from here on can use data_directory or metadata_streams ---*/
886 get_col_offset (VerifyContext *ctx, int table, int column)
888 guint32 bitfield = ctx->image->tables [table].size_bitfield;
892 offset += mono_metadata_table_size (bitfield, column);
898 get_col_size (VerifyContext *ctx, int table, int column)
900 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
904 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
907 res.offset = header->data - ctx->data;
908 res.size = header->size;
914 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
916 OffsetAndSize strings = get_metadata_stream (ctx, &ctx->image->heap_strings);
918 const char *data = ctx->data + strings.offset;
920 if (offset >= strings.size)
922 if (data + offset < data) //FIXME, use a generalized and smart unsigned add with overflow check and fix the whole thing
925 if (!mono_utf8_validate_and_len_with_bounds (data + offset, strings.size - offset, &length, NULL))
927 return allow_empty || length > 0;
931 is_valid_string (VerifyContext *ctx, guint32 offset)
933 return is_valid_string_full (ctx, offset, TRUE);
937 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
939 return is_valid_string_full (ctx, offset, FALSE);
943 is_valid_guid (VerifyContext *ctx, guint32 offset)
945 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
946 return guids.size >= 8 && guids.size - 8 >= offset;
950 get_coded_index_token (int token_kind, guint32 coded_token)
952 guint32 bits = coded_index_desc [token_kind];
953 return coded_token >> bits;
957 get_coded_index_table (int kind, guint32 coded_token)
959 guint32 idx, bits = coded_index_desc [kind];
961 idx = coded_token & ((1 << bits) - 1);
962 return coded_index_desc [kind + idx];
966 make_coded_token (int kind, guint32 table, guint32 table_idx)
968 guint32 bits = coded_index_desc [kind++];
969 guint32 tables = coded_index_desc [kind++];
971 for (i = 0; i < tables; ++i) {
972 if (coded_index_desc [kind++] == table)
973 return ((table_idx + 1) << bits) | i;
975 g_assert_not_reached ();
980 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
982 guint32 bits = coded_index_desc [token_kind++];
983 guint32 table_count = coded_index_desc [token_kind++];
984 guint32 table = coded_token & ((1 << bits) - 1);
985 guint32 token = coded_token >> bits;
987 if (table >= table_count)
990 /*token_kind points to the first table idx*/
991 table = coded_index_desc [token_kind + table];
993 if (table == INVALID_TABLE)
995 return token <= ctx->image->tables [table].rows;
1002 MonoTableInfo *table;
1006 token_locator (const void *a, const void *b)
1008 RowLocator *loc = (RowLocator *)a;
1009 unsigned const char *row = (unsigned const char *)b;
1010 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1012 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1013 return (int)loc->token - (int)token;
1017 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1019 MonoTableInfo *tinfo = &ctx->image->tables [table];
1021 const char *res, *base;
1022 locator.token = coded_token;
1023 locator.col_offset = get_col_offset (ctx, table, column);
1024 locator.col_size = get_col_size (ctx, table, column);
1025 locator.table = tinfo;
1029 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) );
1030 res = bsearch (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1034 return (res - base) / tinfo->row_size;
1037 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1039 get_string_ptr (VerifyContext *ctx, guint offset)
1041 return ctx->image->heap_strings.data + offset;
1044 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1046 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1049 return strcmp (str, "");
1051 return strcmp (str, get_string_ptr (ctx, offset));
1055 mono_verifier_is_corlib (MonoImage *image)
1057 gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
1058 TRUE : mono_security_core_clr_is_platform_image (image);
1060 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1064 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1066 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1070 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1073 const unsigned char *ptr = (const unsigned char *)_ptr;
1081 if ((b & 0x80) == 0) {
1084 } else if ((b & 0x40) == 0) {
1088 *value = ((b & 0x3f) << 8 | ptr [1]);
1093 *value = ((b & 0x1f) << 24) |
1103 decode_signature_header (VerifyContext *ctx, guint32 offset, int *size, const char **first_byte)
1105 MonoStreamHeader blob = ctx->image->heap_blob;
1106 guint32 value, enc_size;
1108 if (offset >= blob.size)
1111 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1114 if (offset + enc_size + value < offset)
1117 if (offset + enc_size + value > blob.size)
1121 *first_byte = blob.data + offset + enc_size;
1126 safe_read (const char **_ptr, const char *limit, void *dest, int size)
1128 const char *ptr = *_ptr;
1129 if (ptr + size > limit)
1133 *((guint8*)dest) = *((guint8*)ptr);
1137 *((guint16*)dest) = read16 (ptr);
1141 *((guint32*)dest) = read32 (ptr);
1150 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1153 const char *ptr = *_ptr;
1154 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1159 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1160 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1161 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1162 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1165 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1168 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1171 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1173 const char *ptr = *_ptr;
1178 if (!safe_read8 (type, ptr, end))
1179 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1181 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1186 if (!safe_read_cint (token, ptr, end))
1187 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1189 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1190 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1198 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1200 const char *ptr = *_ptr;
1202 guint32 size, num, i;
1204 if (!safe_read8 (val, ptr, end))
1205 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1208 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1210 if (!safe_read_cint (size, ptr, end))
1211 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1213 for (i = 0; i < size; ++i) {
1214 if (!safe_read_cint (num, ptr, end))
1215 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1218 if (!safe_read_cint (size, ptr, end))
1219 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
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 LoBound of rank %d", i + 1));
1231 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1233 const char *ptr = *_ptr;
1235 guint32 count, token, i;
1237 if (!safe_read8 (type, ptr, end))
1238 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1240 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1241 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1243 if (!safe_read_cint (token, ptr, end))
1244 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1246 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1247 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1249 if (!safe_read_cint (count, ptr, end))
1250 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1253 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1255 for (i = 0; i < count; ++i) {
1256 if (!parse_type (ctx, &ptr, end))
1257 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1264 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1266 const char *ptr = *_ptr;
1270 if (!safe_read8 (type, ptr, end))
1271 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1273 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1274 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1275 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1276 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1277 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1281 if (!parse_custom_mods (ctx, &ptr, end))
1282 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1284 if (!safe_read8 (type, ptr, end))
1285 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1287 if (type != MONO_TYPE_VOID) {
1289 if (!parse_type (ctx, &ptr, end))
1290 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1294 case MONO_TYPE_VALUETYPE:
1295 case MONO_TYPE_CLASS:
1296 if (!safe_read_cint (token, ptr, end))
1297 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1299 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1300 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1304 case MONO_TYPE_MVAR:
1305 if (!safe_read_cint (token, ptr, end))
1306 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1309 case MONO_TYPE_ARRAY:
1310 if (!parse_type (ctx, &ptr, end))
1311 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1312 if (!parse_array_shape (ctx, &ptr, end))
1313 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1316 case MONO_TYPE_GENERICINST:
1317 if (!parse_generic_inst (ctx, &ptr, end))
1318 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1321 case MONO_TYPE_FNPTR:
1322 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1323 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1326 case MONO_TYPE_SZARRAY:
1327 if (!parse_custom_mods (ctx, &ptr, end))
1328 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1329 if (!parse_type (ctx, &ptr, end))
1330 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1338 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1343 if (!parse_custom_mods (ctx, _ptr, end))
1347 if (!safe_read8 (type, ptr, end))
1348 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1350 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1355 //it's a byref, update the cursor ptr
1356 if (type == MONO_TYPE_BYREF)
1359 return parse_type (ctx, _ptr, end);
1363 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1368 if (!parse_custom_mods (ctx, _ptr, end))
1372 if (!safe_read8 (type, ptr, end))
1373 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1375 if (type == MONO_TYPE_TYPEDBYREF) {
1380 //it's a byref, update the cursor ptr
1381 if (type == MONO_TYPE_BYREF)
1384 return parse_type (ctx, _ptr, end);
1388 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1391 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1392 const char *ptr = *_ptr;
1393 gboolean saw_sentinel = FALSE;
1395 if (!safe_read8 (cconv, ptr, end))
1396 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1399 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1401 if (allow_unmanaged) {
1402 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1403 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1404 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1405 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1407 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1408 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1410 if ((cconv & 0x10) && gparam_count == 0)
1411 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1413 if (allow_unmanaged && (cconv & 0x10))
1414 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1416 if (!safe_read_cint (param_count, ptr, end))
1417 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1419 if (!parse_return_type (ctx, &ptr, end))
1420 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1422 for (i = 0; i < param_count; ++i) {
1423 if (allow_sentinel) {
1424 if (!safe_read8 (type, ptr, end))
1425 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1427 if (type == MONO_TYPE_SENTINEL) {
1428 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1429 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1432 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1434 saw_sentinel = TRUE;
1440 if (!parse_param (ctx, &ptr, end))
1441 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1449 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1452 unsigned param_count = 0, i;
1453 const char *ptr = *_ptr;
1455 if (!safe_read8 (sig, ptr, end))
1456 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1458 if (sig != 0x08 && sig != 0x28)
1459 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1461 if (!safe_read_cint (param_count, ptr, end))
1462 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1464 if (!parse_custom_mods (ctx, &ptr, end))
1467 if (!parse_type (ctx, &ptr, end))
1468 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1470 for (i = 0; i < param_count; ++i) {
1471 if (!parse_type (ctx, &ptr, end))
1472 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1480 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1482 const char *ptr = *_ptr;
1483 guint8 signature = 0;
1485 if (!safe_read8 (signature, ptr, end))
1486 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1488 if (signature != 0x06)
1489 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1491 if (!parse_custom_mods (ctx, &ptr, end))
1494 if (safe_read8 (signature, ptr, end)) {
1495 if (signature != MONO_TYPE_BYREF)
1500 return parse_type (ctx, _ptr, end);
1504 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1507 unsigned locals_count = 0, i;
1508 const char *ptr = *_ptr;
1510 if (!safe_read8 (sig, ptr, end))
1511 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1514 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1516 if (!safe_read_cint (locals_count, ptr, end))
1517 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1519 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1520 if (locals_count == 0)
1521 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1524 for (i = 0; i < locals_count; ++i) {
1525 if (!safe_read8 (sig, ptr, end))
1526 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1528 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1529 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1530 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1531 if (!safe_read8 (sig, ptr, end))
1532 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1535 if (sig == MONO_TYPE_BYREF) {
1536 if (!safe_read8 (sig, ptr, end))
1537 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1538 if (sig == MONO_TYPE_TYPEDBYREF)
1539 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1542 if (sig == MONO_TYPE_TYPEDBYREF)
1547 if (!parse_type (ctx, &ptr, end))
1548 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1556 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1558 int size = 0, signature = 0;
1559 const char *ptr = NULL, *end;
1561 if (!decode_signature_header (ctx, offset, &size, &ptr))
1562 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1565 if (!safe_read8 (signature, ptr, end))
1566 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1569 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1572 return parse_field (ctx, &ptr, end);
1576 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1579 const char *ptr = NULL, *end;
1581 if (!decode_signature_header (ctx, offset, &size, &ptr))
1582 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1585 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1589 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1592 unsigned signature = 0;
1593 const char *ptr = NULL, *end;
1595 if (!decode_signature_header (ctx, offset, &size, &ptr))
1596 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1599 if (!safe_read8 (signature, ptr, end))
1600 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1603 if (signature == 0x06)
1604 return parse_field (ctx, &ptr, end);
1606 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1610 is_vald_cattr_blob (VerifyContext *ctx, guint32 offset)
1614 const char *ptr = NULL, *end;
1619 if (!decode_signature_header (ctx, offset, &size, &ptr))
1620 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1623 if (!safe_read16 (prolog, ptr, end))
1624 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1627 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1633 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
1635 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1636 //TODO do proper verification
1637 return blob.size >= 1 && blob.size - 1 >= offset;
1641 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
1643 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1644 //TODO do proper verification
1645 return blob.size >= 1 && blob.size - 1 >= offset;
1649 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
1652 unsigned signature = 0;
1653 const char *ptr = NULL, *end;
1655 if (!decode_signature_header (ctx, offset, &size, &ptr))
1656 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
1659 if (!safe_read8 (signature, ptr, end))
1660 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
1663 if (signature == 0x07)
1664 return parse_locals_signature (ctx, &ptr, end);
1665 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
1669 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
1672 const char *ptr = NULL, *end;
1674 if (!decode_signature_header (ctx, offset, &size, &ptr))
1675 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
1678 return parse_property_signature (ctx, &ptr, end);
1682 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
1685 const char *ptr = NULL, *end;
1689 if (!decode_signature_header (ctx, offset, &size, &ptr))
1690 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
1693 if (!parse_custom_mods (ctx, &ptr, end))
1696 if (!safe_read8 (type, ptr, end))
1697 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
1699 if (type == MONO_TYPE_BYREF) {
1700 if (!safe_read8 (type, ptr, end))
1701 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
1702 if (type == MONO_TYPE_TYPEDBYREF)
1703 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref"));
1706 if (type == MONO_TYPE_TYPEDBYREF)
1710 return parse_type (ctx, &ptr, end);
1714 is_valid_methodspec_blog (VerifyContext *ctx, guint32 offset)
1717 const char *ptr = NULL, *end;
1719 guint32 count = 0, i;
1721 if (!decode_signature_header (ctx, offset, &size, &ptr))
1722 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
1725 if (!safe_read8 (type, ptr, end))
1726 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
1729 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
1731 if (!safe_read_cint (count, ptr, end))
1732 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
1735 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
1737 for (i = 0; i < count; ++i) {
1738 if (!parse_type (ctx, &ptr, end))
1739 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
1745 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
1747 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1748 guint32 entry_size, bytes;
1750 if (blob.size < offset)
1753 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1756 if (entry_size < minsize)
1759 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
1761 entry_size += bytes;
1763 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
1767 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
1769 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1770 guint32 size, entry_size, bytes;
1772 if (blob.size < offset)
1773 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
1775 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1776 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
1778 if (type == MONO_TYPE_STRING) {
1779 //String is encoded as: compressed_int:len len *bytes
1782 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
1783 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
1789 case MONO_TYPE_BOOLEAN:
1794 case MONO_TYPE_CHAR:
1802 case MONO_TYPE_CLASS:
1812 g_assert_not_reached ();
1815 if (size != entry_size)
1816 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
1820 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
1821 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
1823 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
1824 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
1828 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
1829 //only 0x01, 0x40 and 0x80 are allowed
1830 #define SECTION_HEADER_INVALID_FLAGS 0x3E
1833 is_valid_method_header (VerifyContext *ctx, guint32 rva)
1835 guint32 local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
1837 guint16 fat_header = 0, size = 0, max_stack;
1838 const char *ptr = NULL, *end;
1840 if (offset == INVALID_ADDRESS)
1841 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
1843 ptr = ctx->data + offset;
1844 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
1846 if (!safe_read8 (header, ptr, end))
1847 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
1849 switch (header & 0x3) {
1852 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
1855 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
1856 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
1861 if (!safe_read16 (fat_header, ptr, end))
1862 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
1864 size = (fat_header >> 12) & 0xF;
1866 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
1868 if (!safe_read16 (max_stack, ptr, end))
1869 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
1871 if (!safe_read32 (code_size, ptr, end))
1872 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
1874 if (!safe_read32 (local_vars_tok, ptr, end))
1875 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
1877 if (local_vars_tok) {
1878 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
1879 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
1880 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
1881 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
1884 if (fat_header & FAT_HEADER_INVALID_FLAGS)
1885 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
1887 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
1888 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
1890 if (!(fat_header & 0x08))
1896 guint32 section_header = 0, section_size = 0;
1899 ptr = dword_align (ptr);
1900 if (!safe_read32 (section_header, ptr, end))
1901 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
1903 if (section_header & SECTION_HEADER_INVALID_FLAGS)
1904 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
1906 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
1907 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
1909 if (section_size < 4)
1910 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
1912 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
1913 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
1915 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
1916 guint32 i, clauses = (section_size - 4) / (is_fat ? 24 : 12);
1917 if (clauses * (is_fat ? 24 : 12) + 4 != section_size)
1918 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the proper size", section_size));
1920 /* only verify the class token is verified as the rest is done by the IL verifier*/
1921 for (i = 0; i < clauses; ++i) {
1923 guint32 class_token = 0;
1924 ptr += (is_fat ? 20 : 8);
1925 if (!safe_read32 (class_token, ptr, end))
1926 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
1927 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
1928 guint table = mono_metadata_token_table (class_token);
1929 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
1930 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
1931 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
1932 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
1937 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
1944 verify_module_table (VerifyContext *ctx)
1946 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
1947 guint32 data [MONO_MODULE_SIZE];
1949 if (table->rows != 1)
1950 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
1952 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
1954 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
1955 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
1957 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
1958 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
1960 if (data [MONO_MODULE_ENC] != 0)
1961 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
1963 if (data [MONO_MODULE_ENCBASE] != 0)
1964 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
1968 verify_typeref_table (VerifyContext *ctx)
1970 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
1971 guint32 data [MONO_TYPEREF_SIZE];
1974 for (i = 0; i < table->rows; ++i) {
1975 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
1976 if (!is_valid_coded_index (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1977 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i, data [MONO_TYPEREF_SCOPE]));
1979 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1980 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i));
1982 if (!data [MONO_TYPEREF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAME]))
1983 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d name token 0x%08x", i, data [MONO_TYPEREF_NAME]));
1985 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
1986 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d namespace token 0x%08x", i, data [MONO_TYPEREF_NAMESPACE]));
1990 /*bits 9,11,14,15,19,21,24-31 */
1991 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
1993 verify_typedef_table (VerifyContext *ctx)
1995 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
1996 guint32 data [MONO_TYPEDEF_SIZE];
1997 guint32 fieldlist = 1, methodlist = 1;
2000 if (table->rows == 0)
2001 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2003 for (i = 0; i < table->rows; ++i) {
2004 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2005 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2006 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2008 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2009 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2011 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2012 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2014 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2015 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2017 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2018 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2020 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2021 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2023 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2024 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2026 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2027 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2029 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2030 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2032 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2033 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2035 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2036 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));
2038 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2039 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2041 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2042 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2044 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2045 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));
2047 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2048 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2053 verify_typedef_table_full (VerifyContext *ctx)
2055 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2056 guint32 data [MONO_TYPEDEF_SIZE];
2059 if (table->rows == 0)
2060 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2062 for (i = 0; i < table->rows; ++i) {
2063 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2066 if (data [MONO_TYPEDEF_EXTENDS] != 0)
2067 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2071 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2072 if (data [MONO_TYPEDEF_EXTENDS])
2073 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2075 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2076 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2080 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2083 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2091 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2093 verify_field_table (VerifyContext *ctx)
2095 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2096 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2099 module_field_list = (guint32)-1;
2100 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2101 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2102 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2105 for (i = 0; i < table->rows; ++i) {
2106 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2107 flags = data [MONO_FIELD_FLAGS];
2109 if (flags & INVALID_FIELD_FLAG_BITS)
2110 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2112 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2113 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2115 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2116 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2118 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2119 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2121 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2122 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2124 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2125 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2126 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2128 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2129 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2130 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2132 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2133 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2134 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2136 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2137 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2138 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2140 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2141 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2143 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2144 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2146 //TODO verify contant flag
2148 if (i + 1 < module_field_list) {
2149 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2150 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2151 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2152 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2153 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2159 verify_field_table_full (VerifyContext *ctx)
2161 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2162 guint32 data [MONO_FIELD_SIZE];
2165 for (i = 0; i < table->rows; ++i) {
2166 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2168 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2169 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2173 /*bits 6,8,9,10,11,13,14,15*/
2174 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2176 verify_method_table (VerifyContext *ctx)
2178 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2179 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2180 guint32 paramlist = 1;
2181 gboolean is_ctor, is_cctor;
2185 module_method_list = (guint32)-1;
2186 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2187 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2188 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2191 for (i = 0; i < table->rows; ++i) {
2192 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2193 rva = data [MONO_METHOD_RVA];
2194 implflags = data [MONO_METHOD_IMPLFLAGS];
2195 flags = data [MONO_METHOD_FLAGS];
2196 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2197 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2200 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2201 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2204 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2206 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2207 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2209 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2210 is_ctor = !strcmp (".ctor", name);
2211 is_cctor = !strcmp (".cctor", name);
2213 if ((is_ctor || is_cctor) &&
2214 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2215 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2217 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2218 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2220 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2221 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2222 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2223 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2224 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2227 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2228 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2230 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2231 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2233 //XXX no checks against cas stuff 10,11,12,13)
2235 //TODO check iface with .ctor (15,16)
2237 if (i + 1 < module_method_list) {
2238 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2239 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2240 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2241 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2242 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2243 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2246 //TODO check valuetype for synchronized
2248 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2249 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2251 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (flags & METHOD_ATTRIBUTE_VIRTUAL))
2252 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2254 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2255 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2256 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2258 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2259 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2261 //TODO check signature contents
2264 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2265 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2266 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2267 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2269 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2270 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2273 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2275 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2276 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2277 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2279 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2280 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2282 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2283 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2285 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2286 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2288 if (data [MONO_METHOD_PARAMLIST] == 0)
2289 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2291 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2292 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));
2294 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2295 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2297 paramlist = data [MONO_METHOD_PARAMLIST];
2303 verify_method_table_full (VerifyContext *ctx)
2305 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2306 guint32 data [MONO_METHOD_SIZE], rva;
2309 for (i = 0; i < table->rows; ++i) {
2310 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2311 rva = data [MONO_METHOD_RVA];
2313 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2314 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2316 if (rva && !is_valid_method_header (ctx, rva))
2317 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2322 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2324 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2325 guint32 row = *current_method;
2326 guint32 paramlist, tmp;
2329 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2330 while (row < table->rows) {
2331 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2332 if (tmp > paramlist) {
2333 *current_method = row;
2334 return tmp - paramlist;
2339 /*no more methods, all params apply to the last one*/
2340 *current_method = table->rows;
2345 #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))
2347 verify_param_table (VerifyContext *ctx)
2349 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2350 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2351 gboolean first_param = TRUE;
2354 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2355 if (table->rows > 0)
2356 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2360 remaining_params = get_next_param_count (ctx, ¤t_method);
2362 for (i = 0; i < table->rows; ++i) {
2363 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2364 flags = data [MONO_PARAM_FLAGS];
2366 if (flags & INVALID_PARAM_FLAGS_BITS)
2367 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2369 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2370 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2371 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2373 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2374 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2377 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)
2378 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2380 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2381 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2383 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2384 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2386 first_param = FALSE;
2387 sequence = data [MONO_PARAM_SEQUENCE];
2388 if (--remaining_params == 0) {
2389 remaining_params = get_next_param_count (ctx, ¤t_method);
2396 verify_interfaceimpl_table (VerifyContext *ctx)
2398 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2399 guint32 data [MONO_INTERFACEIMPL_SIZE];
2402 for (i = 0; i < table->rows; ++i) {
2403 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2404 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2405 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2407 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2408 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2410 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2411 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2416 verify_memberref_table (VerifyContext *ctx)
2418 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2419 guint32 data [MONO_MEMBERREF_SIZE];
2422 for (i = 0; i < table->rows; ++i) {
2423 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2425 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2426 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2428 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2429 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2431 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2432 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2434 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2435 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2441 verify_memberref_table_full (VerifyContext *ctx)
2443 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2444 guint32 data [MONO_MEMBERREF_SIZE];
2447 for (i = 0; i < table->rows; ++i) {
2448 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2450 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2451 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2456 verify_constant_table (VerifyContext *ctx)
2458 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2459 guint32 data [MONO_CONSTANT_SIZE], type;
2462 for (i = 0; i < table->rows; ++i) {
2463 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2464 type = data [MONO_CONSTANT_TYPE];
2466 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2467 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2469 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2470 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2472 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2473 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2475 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2476 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2481 verify_cattr_table (VerifyContext *ctx)
2483 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2484 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2487 for (i = 0; i < table->rows; ++i) {
2488 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2490 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2491 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2493 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2494 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2496 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2497 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2502 verify_cattr_table_full (VerifyContext *ctx)
2504 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2505 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2508 for (i = 0; i < table->rows; ++i) {
2509 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2511 if (!is_vald_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2512 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2517 verify_field_marshal_table (VerifyContext *ctx)
2519 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2520 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2523 for (i = 0; i < table->rows; ++i) {
2524 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2526 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2527 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2529 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2530 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2532 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2533 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2535 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2536 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2541 verify_field_marshal_table_full (VerifyContext *ctx)
2543 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2544 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2547 for (i = 0; i < table->rows; ++i) {
2548 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2550 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2551 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2556 verify_decl_security_table (VerifyContext *ctx)
2558 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2559 guint32 data [MONO_DECL_SECURITY_SIZE];
2562 for (i = 0; i < table->rows; ++i) {
2563 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2565 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2566 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2568 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2569 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
2571 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
2572 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
2577 verify_decl_security_table_full (VerifyContext *ctx)
2579 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2580 guint32 data [MONO_DECL_SECURITY_SIZE];
2583 for (i = 0; i < table->rows; ++i) {
2584 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2586 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
2587 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
2592 verify_class_layout_table (VerifyContext *ctx)
2594 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
2595 guint32 data [MONO_CLASS_LAYOUT_SIZE];
2598 for (i = 0; i < table->rows; ++i) {
2599 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
2601 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2602 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2604 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
2616 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
2622 verify_field_layout_table (VerifyContext *ctx)
2624 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
2625 guint32 data [MONO_FIELD_LAYOUT_SIZE];
2628 for (i = 0; i < table->rows; ++i) {
2629 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
2631 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2632 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
2637 verify_standalonesig_table (VerifyContext *ctx)
2639 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2640 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2643 for (i = 0; i < table->rows; ++i) {
2644 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2646 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
2647 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2652 verify_standalonesig_table_full (VerifyContext *ctx)
2654 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2655 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2658 for (i = 0; i < table->rows; ++i) {
2659 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2661 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
2662 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2667 verify_eventmap_table (VerifyContext *ctx)
2669 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
2670 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
2673 for (i = 0; i < table->rows; ++i) {
2674 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
2676 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2677 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
2679 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
2680 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
2682 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
2686 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
2688 verify_event_table (VerifyContext *ctx)
2690 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2691 guint32 data [MONO_EVENT_SIZE];
2694 for (i = 0; i < table->rows; ++i) {
2695 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2697 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
2698 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
2700 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
2701 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
2703 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
2704 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
2709 verify_event_table_full (VerifyContext *ctx)
2711 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2712 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
2713 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
2714 gboolean found_add, found_remove;
2717 for (i = 0; i < table->rows; ++i) {
2718 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2720 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
2721 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
2723 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
2725 //first we move to the first row for this event
2727 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
2731 //now move forward looking for AddOn and RemoveOn rows
2732 found_add = found_remove = FALSE;
2733 while (idx < sema_table->rows) {
2734 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
2735 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
2737 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
2739 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
2740 found_remove = TRUE;
2741 if (found_add && found_remove)
2747 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2749 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2754 verify_propertymap_table (VerifyContext *ctx)
2756 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
2757 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
2760 for (i = 0; i < table->rows; ++i) {
2761 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
2763 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2764 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
2766 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
2767 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
2769 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
2773 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
2775 verify_property_table (VerifyContext *ctx)
2777 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
2778 guint32 data [MONO_PROPERTY_SIZE];
2781 for (i = 0; i < table->rows; ++i) {
2782 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
2784 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
2785 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
2787 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
2788 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
2790 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
2791 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
2793 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
2794 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
2795 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
2801 verify_methodimpl_table (VerifyContext *ctx)
2803 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
2804 guint32 data [MONO_METHODIMPL_SIZE];
2807 for (i = 0; i < table->rows; ++i) {
2808 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
2810 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2811 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2813 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2814 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2816 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2817 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2819 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2820 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2822 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2823 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2828 verify_moduleref_table (VerifyContext *ctx)
2830 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
2831 guint32 data [MONO_MODULEREF_SIZE];
2834 for (i = 0; i < table->rows; ++i) {
2835 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
2837 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
2838 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2843 verify_typespec_table (VerifyContext *ctx)
2845 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2846 guint32 data [MONO_TYPESPEC_SIZE];
2849 for (i = 0; i < table->rows; ++i) {
2850 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2852 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
2853 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2858 verify_typespec_table_full (VerifyContext *ctx)
2860 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2861 guint32 data [MONO_TYPESPEC_SIZE];
2864 for (i = 0; i < table->rows; ++i) {
2865 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2867 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
2868 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2872 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10))
2874 verify_implmap_table (VerifyContext *ctx)
2876 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
2877 guint32 data [MONO_IMPLMAP_SIZE], cconv;
2880 for (i = 0; i < table->rows; ++i) {
2881 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
2883 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
2884 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
2886 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
2887 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
2888 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
2890 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2891 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
2893 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
2894 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
2896 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2897 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
2899 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
2900 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
2902 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows + 1)
2903 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
2908 verify_fieldrva_table (VerifyContext *ctx)
2910 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
2911 guint32 data [MONO_FIELD_RVA_SIZE];
2914 for (i = 0; i < table->rows; ++i) {
2915 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
2917 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
2918 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
2920 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2921 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
2925 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
2927 verify_assembly_table (VerifyContext *ctx)
2929 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
2930 guint32 data [MONO_ASSEMBLY_SIZE], hash;
2933 if (table->rows > 1)
2934 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
2936 for (i = 0; i < table->rows; ++i) {
2937 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
2939 hash = data [MONO_ASSEMBLY_HASH_ALG];
2940 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
2941 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
2943 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
2944 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2946 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
2947 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2949 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
2950 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
2952 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
2953 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
2957 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
2959 verify_assemblyref_table (VerifyContext *ctx)
2961 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
2962 guint32 data [MONO_ASSEMBLYREF_SIZE];
2965 for (i = 0; i < table->rows; ++i) {
2966 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
2968 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
2969 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
2971 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
2972 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
2974 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
2975 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
2977 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
2978 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
2980 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
2981 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
2985 #define INVALID_FILE_FLAGS_BITS ~(1)
2987 verify_file_table (VerifyContext *ctx)
2989 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
2990 guint32 data [MONO_FILE_SIZE];
2993 for (i = 0; i < table->rows; ++i) {
2994 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
2996 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
2997 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
2999 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3000 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3002 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3003 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3007 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3009 verify_exportedtype_table (VerifyContext *ctx)
3011 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3012 guint32 data [MONO_EXP_TYPE_SIZE];
3015 for (i = 0; i < table->rows; ++i) {
3016 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3018 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3019 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3021 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3022 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3024 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3025 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3027 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3028 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3030 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3031 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3033 /*nested type can't have a namespace*/
3034 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3035 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3039 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3041 verify_manifest_resource_table (VerifyContext *ctx)
3043 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3044 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3045 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3046 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3049 resources_size = ch->ch_resources.size;
3051 for (i = 0; i < table->rows; ++i) {
3052 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3054 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3055 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3057 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3058 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3060 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3061 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3063 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3064 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3066 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3067 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3069 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3070 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])));
3072 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3073 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3075 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3076 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3081 verify_nested_class_table (VerifyContext *ctx)
3083 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3084 guint32 data [MONO_NESTED_CLASS_SIZE];
3087 for (i = 0; i < table->rows; ++i) {
3088 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3090 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3091 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3092 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3093 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3094 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3095 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3099 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3101 verify_generic_param_table (VerifyContext *ctx)
3103 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3104 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3105 int i, param_number = 0;
3107 for (i = 0; i < table->rows; ++i) {
3108 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3110 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3111 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3113 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3114 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3116 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3117 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3119 token = data [MONO_GENERICPARAM_OWNER];
3121 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3122 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3124 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3125 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3127 if (token != last_token) {
3132 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3133 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));
3140 verify_method_spec_table (VerifyContext *ctx)
3142 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3143 guint32 data [MONO_METHODSPEC_SIZE];
3146 for (i = 0; i < table->rows; ++i) {
3147 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3149 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3150 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3152 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3153 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3155 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3156 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3161 verify_method_spec_table_full (VerifyContext *ctx)
3163 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3164 guint32 data [MONO_METHODSPEC_SIZE];
3167 for (i = 0; i < table->rows; ++i) {
3168 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3170 if (!is_valid_methodspec_blog (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3171 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3176 verify_generic_param_constraint_table (VerifyContext *ctx)
3178 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3179 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3182 for (i = 0; i < table->rows; ++i) {
3183 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3185 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3186 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_TABLE_GENERICPARAM]));
3188 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3189 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3191 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3192 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3197 verify_tables_data (VerifyContext *ctx)
3199 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3200 guint32 size = 0, tables_offset;
3203 for (i = 0; i < 0x2D; ++i) {
3204 MonoTableInfo *table = &ctx->image->tables [i];
3206 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3207 if (tmp_size < size) {
3215 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3217 tables_offset = ctx->image->tables_base - ctx->data;
3218 if (!bounds_check_offset (&tables_area, tables_offset, size))
3219 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)));
3221 verify_module_table (ctx);
3223 verify_typeref_table (ctx);
3225 verify_typedef_table (ctx);
3227 verify_field_table (ctx);
3229 verify_method_table (ctx);
3231 verify_param_table (ctx);
3233 verify_interfaceimpl_table (ctx);
3235 verify_memberref_table (ctx);
3237 verify_constant_table (ctx);
3239 verify_cattr_table (ctx);
3241 verify_field_marshal_table (ctx);
3243 verify_decl_security_table (ctx);
3245 verify_class_layout_table (ctx);
3247 verify_field_layout_table (ctx);
3249 verify_standalonesig_table (ctx);
3251 verify_eventmap_table (ctx);
3253 verify_event_table (ctx);
3255 verify_propertymap_table (ctx);
3257 verify_property_table (ctx);
3259 verify_methodimpl_table (ctx);
3261 verify_moduleref_table (ctx);
3263 verify_typespec_table (ctx);
3265 verify_implmap_table (ctx);
3267 verify_fieldrva_table (ctx);
3269 verify_assembly_table (ctx);
3271 verify_assemblyref_table (ctx);
3273 verify_file_table (ctx);
3275 verify_exportedtype_table (ctx);
3277 verify_manifest_resource_table (ctx);
3279 verify_nested_class_table (ctx);
3281 verify_generic_param_table (ctx);
3283 verify_method_spec_table (ctx);
3285 verify_generic_param_constraint_table (ctx);
3289 init_verify_context (VerifyContext *ctx, MonoImage *image, GSList **error_list)
3291 memset (ctx, 0, sizeof (VerifyContext));
3293 ctx->report_error = error_list != NULL;
3295 ctx->size = image->raw_data_len;
3296 ctx->data = image->raw_data;
3300 cleanup_context (VerifyContext *ctx, GSList **error_list)
3302 g_free (ctx->sections);
3304 *error_list = ctx->errors;
3306 mono_free_verify_list (ctx->errors);
3311 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3315 if (!mono_verifier_is_enabled_for_image (image))
3318 init_verify_context (&ctx, image, error_list);
3319 ctx.stage = STAGE_PE;
3321 verify_msdos_header (&ctx);
3323 verify_pe_header (&ctx);
3325 verify_pe_optional_header (&ctx);
3327 load_section_table (&ctx);
3329 load_data_directories (&ctx);
3331 verify_import_table (&ctx);
3333 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3334 verify_resources_table (&ctx);
3337 return cleanup_context (&ctx, error_list);
3341 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3345 if (!mono_verifier_is_enabled_for_image (image))
3348 init_verify_context (&ctx, image, error_list);
3349 ctx.stage = STAGE_CLI;
3351 verify_cli_header (&ctx);
3353 verify_metadata_header (&ctx);
3355 verify_tables_schema (&ctx);
3358 return cleanup_context (&ctx, error_list);
3363 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3364 * Other verification checks are meant to be done lazily by the runtime. Those include:
3365 * blob items (signatures, method headers, custom attributes, etc)
3366 * type semantics related
3368 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3370 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3371 * operation still need more checking.
3374 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3378 if (!mono_verifier_is_enabled_for_image (image))
3381 init_verify_context (&ctx, image, error_list);
3382 ctx.stage = STAGE_TABLES;
3384 verify_tables_data (&ctx);
3386 return cleanup_context (&ctx, error_list);
3391 * Verifies all other constraints.
3394 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3398 if (!mono_verifier_is_enabled_for_image (image))
3401 init_verify_context (&ctx, image, error_list);
3402 ctx.stage = STAGE_TABLES;
3404 verify_typedef_table_full (&ctx);
3406 verify_field_table_full (&ctx);
3408 verify_method_table_full (&ctx);
3410 verify_memberref_table_full (&ctx);
3412 verify_cattr_table_full (&ctx);
3414 verify_field_marshal_table_full (&ctx);
3416 verify_decl_security_table_full (&ctx);
3418 verify_standalonesig_table_full (&ctx);
3420 verify_event_table_full (&ctx);
3422 verify_typespec_table_full (&ctx);
3424 verify_method_spec_table_full (&ctx);
3427 return cleanup_context (&ctx, error_list);
3431 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3435 if (!mono_verifier_is_enabled_for_image (image))
3438 init_verify_context (&ctx, image, error_list);
3439 ctx.stage = STAGE_TABLES;
3441 is_valid_field_signature (&ctx, offset);
3442 return cleanup_context (&ctx, error_list);
3446 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3450 if (!mono_verifier_is_enabled_for_image (image))
3453 init_verify_context (&ctx, image, error_list);
3454 ctx.stage = STAGE_TABLES;
3456 is_valid_method_header (&ctx, offset);
3457 return cleanup_context (&ctx, error_list);
3461 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3465 if (!mono_verifier_is_enabled_for_image (image))
3468 init_verify_context (&ctx, image, error_list);
3469 ctx.stage = STAGE_TABLES;
3471 is_valid_method_signature (&ctx, offset);
3472 return cleanup_context (&ctx, error_list);
3476 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3480 if (!mono_verifier_is_enabled_for_image (image))
3483 init_verify_context (&ctx, image, error_list);
3484 ctx.stage = STAGE_TABLES;
3486 is_valid_method_or_field_signature (&ctx, offset);
3487 return cleanup_context (&ctx, error_list);
3491 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3495 if (!mono_verifier_is_enabled_for_image (image))
3498 init_verify_context (&ctx, image, error_list);
3499 ctx.stage = STAGE_TABLES;
3501 is_valid_standalonesig_blob (&ctx, offset);
3502 return cleanup_context (&ctx, error_list);
3506 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3510 if (!mono_verifier_is_enabled_for_image (image))
3513 init_verify_context (&ctx, image, error_list);
3514 ctx.stage = STAGE_TABLES;
3516 is_valid_typespec_blob (&ctx, offset);
3517 return cleanup_context (&ctx, error_list);
3521 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3525 if (!mono_verifier_is_enabled_for_image (image))
3528 init_verify_context (&ctx, image, error_list);
3529 ctx.stage = STAGE_TABLES;
3531 is_valid_methodspec_blog (&ctx, offset);
3532 return cleanup_context (&ctx, error_list);
3537 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3543 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3549 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3555 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3561 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3567 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3573 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3579 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3585 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3591 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3597 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3602 #endif /* DISABLE_VERIFIER */