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,
121 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 21)
127 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
134 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
143 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
149 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
153 MONO_TABLE_MEMBERREF,
155 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
161 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
165 MONO_TABLE_ASSEMBLYREF,
166 MONO_TABLE_EXPORTEDTYPE,
168 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
174 MONO_TABLE_MEMBERREF,
177 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
181 MONO_TABLE_MODULEREF,
182 MONO_TABLE_ASSEMBLYREF,
185 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
195 guint32 translated_offset;
207 guint32 rellocationsRVA;
208 guint16 numberOfRelocations;
223 gboolean report_error;
226 DataDirectory data_directories [16];
227 guint32 section_count;
228 SectionHeader *sections;
230 OffsetAndSize metadata_streams [5]; //offset from begin of the image
233 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
235 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
236 vinfo->info.status = __status; \
237 vinfo->info.message = ( __msg); \
238 vinfo->exception_type = (__exception); \
239 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
243 #define ADD_ERROR(__ctx, __msg) \
245 if ((__ctx)->report_error) \
246 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
247 (__ctx)->valid = 0; \
251 #define FAIL(__ctx, __msg) \
253 if ((__ctx)->report_error) \
254 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
255 (__ctx)->valid = 0; \
259 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
261 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
263 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
264 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
266 #if SIZEOF_VOID_P == 4
267 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
269 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
272 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
273 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
276 dword_align (const char *ptr)
278 #if SIZEOF_VOID_P == 8
279 return (const char *) (((guint64) (ptr + 3)) & ~3);
281 return (const char *) (((guint32) (ptr + 3)) & ~3);
286 pe_signature_offset (VerifyContext *ctx)
288 return read32 (ctx->data + 0x3c);
292 pe_header_offset (VerifyContext *ctx)
294 return read32 (ctx->data + 0x3c) + 4;
298 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
302 if (rva + size < rva) //overflow
305 if (ctx->stage > STAGE_PE) {
306 MonoCLIImageInfo *iinfo = ctx->image->image_info;
307 const int top = iinfo->cli_section_count;
308 MonoSectionTable *tables = iinfo->cli_section_tables;
311 for (i = 0; i < top; i++) {
312 guint32 base = tables->st_virtual_address;
313 guint32 end = base + tables->st_raw_data_size;
315 if (rva >= base && rva + size <= end)
318 /*if ((addr >= tables->st_virtual_address) &&
319 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
321 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
331 for (i = 0; i < ctx->section_count; ++i) {
332 guint32 base = ctx->sections [i].baseRVA;
333 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
334 if (rva >= base && rva + size <= end)
341 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
343 if (dir->translated_offset > offset)
345 if (dir->size < size)
347 return offset + size <= dir->translated_offset + dir->size;
351 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
353 if (off->offset > offset)
356 if (off->size < size)
359 return offset + size <= off->offset + off->size;
363 translate_rva (VerifyContext *ctx, guint32 rva)
367 if (ctx->stage > STAGE_PE)
368 return mono_cli_rva_image_map (ctx->image, rva);
373 for (i = 0; i < ctx->section_count; ++i) {
374 guint32 base = ctx->sections [i].baseRVA;
375 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
376 if (rva >= base && rva <= end) {
377 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
379 return res >= ctx->size ? INVALID_OFFSET : res;
383 return INVALID_OFFSET;
387 verify_msdos_header (VerifyContext *ctx)
391 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
392 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
393 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
394 lfanew = pe_signature_offset (ctx);
395 if (lfanew > ctx->size - 4)
396 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
400 verify_pe_header (VerifyContext *ctx)
402 guint32 offset = pe_signature_offset (ctx);
403 const char *pe_header = ctx->data + offset;
404 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
405 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
409 if (offset > ctx->size - 20)
410 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
411 if (read16 (pe_header) != 0x14c)
412 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
416 verify_pe_optional_header (VerifyContext *ctx)
418 guint32 offset = pe_header_offset (ctx);
419 guint32 header_size, file_alignment;
420 const char *pe_header = ctx->data + offset;
421 const char *pe_optional_header = pe_header + 20;
423 header_size = read16 (pe_header + 16);
426 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
427 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
429 if (offset > ctx->size - header_size || header_size > ctx->size)
430 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
432 if (read16 (pe_optional_header) == 0x10b) {
433 if (header_size != 224)
434 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
436 /* LAMESPEC MS plays around this value and ignore it during validation
437 if (read32 (pe_optional_header + 28) != 0x400000)
438 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
439 if (read32 (pe_optional_header + 32) != 0x2000)
440 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
441 file_alignment = read32 (pe_optional_header + 36);
442 if (file_alignment != 0x200 && file_alignment != 0x1000)
443 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
444 /* All the junk in the middle is irrelevant, specially for mono. */
445 if (read32 (pe_optional_header + 92) > 0x10)
446 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
448 if (read16 (pe_optional_header) == 0x20B)
449 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
451 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
456 load_section_table (VerifyContext *ctx)
459 SectionHeader *sections;
460 guint32 offset = pe_header_offset (ctx);
461 const char *ptr = ctx->data + offset;
462 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
464 offset += 244;/*FIXME, this constant is different under PE32+*/
467 if (num_sections * 40 > ctx->size - offset)
468 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
470 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
471 for (i = 0; i < num_sections; ++i) {
472 sections [i].size = read32 (ptr + 8);
473 sections [i].baseRVA = read32 (ptr + 12);
474 sections [i].baseOffset = read32 (ptr + 20);
475 sections [i].rellocationsRVA = read32 (ptr + 24);
476 sections [i].numberOfRelocations = read16 (ptr + 32);
480 ptr = ctx->data + offset; /*reset it to the beggining*/
481 for (i = 0; i < num_sections; ++i) {
482 guint32 raw_size, flags;
483 if (sections [i].baseOffset == 0)
484 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
485 if (sections [i].baseOffset >= ctx->size)
486 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
487 if (sections [i].size > ctx->size - sections [i].baseOffset)
488 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
490 raw_size = read32 (ptr + 16);
491 if (raw_size < sections [i].size)
492 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
494 if (raw_size > ctx->size - sections [i].baseOffset)
495 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
497 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
498 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
500 flags = read32 (ptr + 36);
501 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
502 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
503 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
510 is_valid_data_directory (int i)
512 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
513 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
517 load_data_directories (VerifyContext *ctx)
519 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
520 const char *ptr = ctx->data + offset;
523 for (i = 0; i < 16; ++i) {
524 guint32 rva = read32 (ptr);
525 guint32 size = read32 (ptr + 4);
527 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
528 if (i == CERTIFICATE_TABLE_IDX) {
532 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
533 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
535 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
536 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
538 ctx->data_directories [i].rva = rva;
539 ctx->data_directories [i].size = size;
540 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
546 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
548 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
551 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
554 guint32 hint_table_rva;
556 import_rva = translate_rva (ctx, import_rva);
557 g_assert (import_rva != INVALID_OFFSET);
559 hint_table_rva = read32 (ctx->data + import_rva);
560 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
561 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
563 hint_table_rva = translate_rva (ctx, hint_table_rva);
564 g_assert (hint_table_rva != INVALID_OFFSET);
565 ptr = ctx->data + hint_table_rva + 2;
567 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
568 char name[SIZE_OF_CORMAIN];
569 memcpy (name, ptr, SIZE_OF_CORMAIN);
570 name [SIZE_OF_CORMAIN - 1] = 0;
571 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
576 verify_import_table (VerifyContext *ctx)
578 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
579 guint32 offset = it.translated_offset;
580 const char *ptr = ctx->data + offset;
581 guint32 name_rva, ilt_rva, iat_rva;
583 g_assert (offset != INVALID_OFFSET);
586 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
588 ilt_rva = read32 (ptr);
589 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
590 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
592 name_rva = read32 (ptr + 12);
593 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
594 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
596 iat_rva = read32 (ptr + 16);
598 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
599 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
601 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
602 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));
606 name_rva = translate_rva (ctx, name_rva);
607 g_assert (name_rva != INVALID_OFFSET);
608 ptr = ctx->data + name_rva;
610 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
611 char name[SIZE_OF_MSCOREE];
612 memcpy (name, ptr, SIZE_OF_MSCOREE);
613 name [SIZE_OF_MSCOREE - 1] = 0;
614 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
619 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
624 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
628 verify_resources_table (VerifyContext *ctx)
630 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
632 guint16 named_entries, id_entries;
633 const char *ptr, *root, *end;
639 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));
641 offset = it.translated_offset;
642 root = ptr = ctx->data + offset;
643 end = root + it.size;
645 g_assert (offset != INVALID_OFFSET);
647 named_entries = read16 (ptr + 12);
648 id_entries = read16 (ptr + 14);
650 if ((named_entries + id_entries) * 8 + 16 > it.size)
651 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));
653 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
654 if (named_entries || id_entries)
655 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
659 /*----------nothing from here on can use data_directory---*/
662 get_data_dir (VerifyContext *ctx, int idx)
664 MonoCLIImageInfo *iinfo = ctx->image->image_info;
665 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
669 res.rva = entry->rva;
670 res.size = entry->size;
671 res.translated_offset = translate_rva (ctx, res.rva);
676 verify_cli_header (VerifyContext *ctx)
678 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
684 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
687 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
689 offset = it.translated_offset;
690 ptr = ctx->data + offset;
692 g_assert (offset != INVALID_OFFSET);
694 if (read16 (ptr) != 72)
695 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
697 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
698 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
701 if (!read32 (ptr + 8) || !read32 (ptr + 12))
702 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
704 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
705 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
708 for (i = 0; i < 6; ++i) {
709 guint32 rva = read32 (ptr);
710 guint32 size = read32 (ptr + 4);
712 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
713 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
718 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
723 pad4 (guint32 offset)
725 if (offset & 0x3) //pad to the next 4 byte boundary
726 offset = (offset & ~0x3) + 4;
731 verify_metadata_header (VerifyContext *ctx)
734 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
738 offset = it.translated_offset;
739 ptr = ctx->data + offset;
740 g_assert (offset != INVALID_OFFSET);
742 //build a directory entry for the metadata root
744 it.rva = read32 (ptr);
746 it.size = read32 (ptr);
747 it.translated_offset = offset = translate_rva (ctx, it.rva);
749 ptr = ctx->data + offset;
750 g_assert (offset != INVALID_OFFSET);
753 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
755 if (read32 (ptr) != 0x424A5342)
756 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
758 offset = pad4 (offset + 16 + read32 (ptr + 12));
760 if (!bounds_check_datadir (&it, offset, 4))
761 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));
763 ptr = ctx->data + offset; //move to streams header
765 if (read16 (ptr + 2) < 3)
766 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 3 streams (#~, #GUID and #Blob"));
771 for (i = 0; i < 5; ++i) {
772 guint32 stream_off, stream_size;
773 int string_size, stream_idx;
775 if (!bounds_check_datadir (&it, offset, 8))
776 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));
778 stream_off = it.translated_offset + read32 (ptr);
779 stream_size = read32 (ptr + 4);
781 if (!bounds_check_datadir (&it, stream_off, stream_size))
782 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
787 for (string_size = 0; string_size < 32; ++string_size) {
788 if (!bounds_check_datadir (&it, offset++, 1))
789 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
790 if (!ptr [string_size])
794 if (ptr [string_size])
795 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
797 if (!strncmp ("#Strings", ptr, 9))
798 stream_idx = STRINGS_STREAM;
799 else if (!strncmp ("#US", ptr, 4))
800 stream_idx = USER_STRINGS_STREAM;
801 else if (!strncmp ("#Blob", ptr, 6))
802 stream_idx = BLOB_STREAM;
803 else if (!strncmp ("#GUID", ptr, 6))
804 stream_idx = GUID_STREAM;
805 else if (!strncmp ("#~", ptr, 3))
806 stream_idx = TILDE_STREAM;
808 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
810 if (ctx->metadata_streams [stream_idx].offset != 0)
811 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
813 ctx->metadata_streams [stream_idx].offset = stream_off;
814 ctx->metadata_streams [stream_idx].size = stream_size;
816 offset = pad4 (offset);
817 ptr = ctx->data + offset;
820 if (!ctx->metadata_streams [TILDE_STREAM].size)
821 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
822 if (!ctx->metadata_streams [GUID_STREAM].size)
823 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
824 if (!ctx->metadata_streams [BLOB_STREAM].size)
825 ADD_ERROR (ctx, g_strdup_printf ("Metadata blob stream missing"));
830 verify_tables_schema (VerifyContext *ctx)
832 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
833 unsigned offset = tables_area.offset;
834 const char *ptr = ctx->data + offset;
835 guint64 valid_tables;
839 //printf ("tables_area size %d offset %x %s\n", tables_area.size, tables_area.offset, ctx->image->name);
840 if (tables_area.size < 24)
841 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
843 //printf ("ptr %x %x\n", ptr[4], ptr[5]);
844 if (ptr [4] != 2 && ptr [4] != 1)
845 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
847 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
849 if ((ptr [6] & ~0x7) != 0)
850 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]));
852 valid_tables = read64 (ptr + 8);
854 for (i = 0; i < 64; ++i) {
855 if (!(valid_tables & ((guint64)1 << i)))
858 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
859 Unused: 0x1E 0x1F 0x2D-0x3F
860 We don't care about the MS extensions.*/
861 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
862 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifies doesn't support MS specific table %x", i));
863 if (i == 0x1E || i == 0x1F || i >= 0x2D)
864 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
868 if (tables_area.size < 24 + count * 4)
869 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));
872 for (i = 0; i < 64; ++i) {
873 if (valid_tables & ((guint64)1 << i)) {
874 guint32 row_count = read32 (ptr);
875 if (row_count > (1 << 24) - 1)
876 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
882 /*----------nothing from here on can use data_directory or metadata_streams ---*/
885 get_col_offset (VerifyContext *ctx, int table, int column)
887 guint32 bitfield = ctx->image->tables [table].size_bitfield;
891 offset += mono_metadata_table_size (bitfield, column);
897 get_col_size (VerifyContext *ctx, int table, int column)
899 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
903 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
906 res.offset = header->data - ctx->data;
907 res.size = header->size;
913 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
915 OffsetAndSize strings = get_metadata_stream (ctx, &ctx->image->heap_strings);
917 const char *data = ctx->data + strings.offset;
919 if (offset >= strings.size)
921 if (data + offset < data) //FIXME, use a generalized and smart unsigned add with overflow check and fix the whole thing
924 if (!mono_utf8_validate_and_len_with_bounds (data + offset, strings.size - offset, &length, NULL))
926 return allow_empty || length > 0;
930 is_valid_string (VerifyContext *ctx, guint32 offset)
932 return is_valid_string_full (ctx, offset, TRUE);
936 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
938 return is_valid_string_full (ctx, offset, FALSE);
942 is_valid_guid (VerifyContext *ctx, guint32 offset)
944 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
945 return guids.size >= 8 && guids.size - 8 >= offset;
949 get_coded_index_token (int token_kind, guint32 coded_token)
951 guint32 bits = coded_index_desc [token_kind];
952 return coded_token >> bits;
956 get_coded_index_table (int kind, guint32 coded_token)
958 guint32 idx, bits = coded_index_desc [kind];
960 idx = coded_token & ((1 << bits) - 1);
961 return coded_index_desc [kind + idx];
965 make_coded_token (int kind, guint32 table, guint32 table_idx)
967 guint32 bits = coded_index_desc [kind++];
968 guint32 tables = coded_index_desc [kind++];
970 for (i = 0; i < tables; ++i) {
971 if (coded_index_desc [kind++] == table)
972 return ((table_idx + 1) << bits) | i;
974 g_assert_not_reached ();
979 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
981 guint32 bits = coded_index_desc [token_kind++];
982 guint32 table_count = coded_index_desc [token_kind++];
983 guint32 table = coded_token & ((1 << bits) - 1);
984 guint32 token = coded_token >> bits;
986 if (table >= table_count)
989 /*token_kind points to the first table idx*/
990 table = coded_index_desc [token_kind + table];
992 if (table == INVALID_TABLE)
994 return token <= ctx->image->tables [table].rows;
1001 MonoTableInfo *table;
1005 token_locator (const void *a, const void *b)
1007 RowLocator *loc = (RowLocator *)a;
1008 unsigned const char *row = (unsigned const char *)b;
1009 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1011 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1012 return (int)loc->token - (int)token;
1016 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1018 MonoTableInfo *tinfo = &ctx->image->tables [table];
1020 const char *res, *base;
1021 locator.token = coded_token;
1022 locator.col_offset = get_col_offset (ctx, table, column);
1023 locator.col_size = get_col_size (ctx, table, column);
1024 locator.table = tinfo;
1028 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) );
1029 res = bsearch (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1033 return (res - base) / tinfo->row_size;
1036 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1038 get_string_ptr (VerifyContext *ctx, guint offset)
1040 return ctx->image->heap_strings.data + offset;
1043 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1045 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1048 return strcmp (str, "");
1050 return strcmp (str, get_string_ptr (ctx, offset));
1054 mono_verifier_is_corlib (MonoImage *image)
1056 gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
1057 TRUE : mono_security_core_clr_is_platform_image (image);
1059 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1063 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1065 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1069 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1072 const unsigned char *ptr = (const unsigned char *)_ptr;
1080 if ((b & 0x80) == 0) {
1083 } else if ((b & 0x40) == 0) {
1087 *value = ((b & 0x3f) << 8 | ptr [1]);
1092 *value = ((b & 0x1f) << 24) |
1102 decode_signature_header (VerifyContext *ctx, guint32 offset, int *size, const char **first_byte)
1104 MonoStreamHeader blob = ctx->image->heap_blob;
1105 guint32 value, enc_size;
1107 if (offset >= blob.size)
1110 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1113 if (offset + enc_size + value < offset)
1116 if (offset + enc_size + value > blob.size)
1120 *first_byte = blob.data + offset + enc_size;
1125 safe_read (const char **_ptr, const char *limit, void *dest, int size)
1127 const char *ptr = *_ptr;
1128 if (ptr + size > limit)
1132 *((guint8*)dest) = *((guint8*)ptr);
1136 *((guint16*)dest) = read16 (ptr);
1140 *((guint32*)dest) = read32 (ptr);
1149 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1152 const char *ptr = *_ptr;
1153 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1158 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1159 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1160 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1161 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1164 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1167 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1170 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1172 const char *ptr = *_ptr;
1177 if (!safe_read8 (type, ptr, end))
1178 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1180 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1185 if (!safe_read_cint (token, ptr, end))
1186 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1188 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1189 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1197 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1199 const char *ptr = *_ptr;
1201 guint32 size, num, i;
1203 if (!safe_read8 (val, ptr, end))
1204 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1207 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1209 if (!safe_read_cint (size, ptr, end))
1210 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1212 for (i = 0; i < size; ++i) {
1213 if (!safe_read_cint (num, ptr, end))
1214 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1217 if (!safe_read_cint (size, ptr, end))
1218 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1220 for (i = 0; i < size; ++i) {
1221 if (!safe_read_cint (num, ptr, end))
1222 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1230 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1232 const char *ptr = *_ptr;
1234 guint32 count, token, i;
1236 if (!safe_read8 (type, ptr, end))
1237 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1239 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1240 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1242 if (!safe_read_cint (token, ptr, end))
1243 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1245 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1246 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1248 if (!safe_read_cint (count, ptr, end))
1249 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1252 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1254 for (i = 0; i < count; ++i) {
1255 if (!parse_type (ctx, &ptr, end))
1256 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1263 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1265 const char *ptr = *_ptr;
1269 if (!safe_read8 (type, ptr, end))
1270 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1272 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1273 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1274 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1275 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1276 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1280 if (!parse_custom_mods (ctx, &ptr, end))
1281 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1283 if (!safe_read8 (type, ptr, end))
1284 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1286 if (type != MONO_TYPE_VOID) {
1288 if (!parse_type (ctx, &ptr, end))
1289 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1293 case MONO_TYPE_VALUETYPE:
1294 case MONO_TYPE_CLASS:
1295 if (!safe_read_cint (token, ptr, end))
1296 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1298 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1299 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1303 case MONO_TYPE_MVAR:
1304 if (!safe_read_cint (token, ptr, end))
1305 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1308 case MONO_TYPE_ARRAY:
1309 if (!parse_type (ctx, &ptr, end))
1310 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1311 if (!parse_array_shape (ctx, &ptr, end))
1312 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1315 case MONO_TYPE_GENERICINST:
1316 if (!parse_generic_inst (ctx, &ptr, end))
1317 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1320 case MONO_TYPE_FNPTR:
1321 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1322 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1325 case MONO_TYPE_SZARRAY:
1326 if (!parse_custom_mods (ctx, &ptr, end))
1327 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1328 if (!parse_type (ctx, &ptr, end))
1329 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1337 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1342 if (!parse_custom_mods (ctx, _ptr, end))
1346 if (!safe_read8 (type, ptr, end))
1347 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1349 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1354 //it's a byref, update the cursor ptr
1355 if (type == MONO_TYPE_BYREF)
1358 return parse_type (ctx, _ptr, end);
1362 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1367 if (!parse_custom_mods (ctx, _ptr, end))
1371 if (!safe_read8 (type, ptr, end))
1372 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1374 if (type == MONO_TYPE_TYPEDBYREF) {
1379 //it's a byref, update the cursor ptr
1380 if (type == MONO_TYPE_BYREF)
1383 return parse_type (ctx, _ptr, end);
1387 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1390 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1391 const char *ptr = *_ptr;
1392 gboolean saw_sentinel = FALSE;
1394 if (!safe_read8 (cconv, ptr, end))
1395 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1398 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1400 if (allow_unmanaged) {
1401 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1402 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1403 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1404 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1406 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1407 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1409 if ((cconv & 0x10) && gparam_count == 0)
1410 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1412 if (allow_unmanaged && (cconv & 0x10))
1413 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1415 if (!safe_read_cint (param_count, ptr, end))
1416 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1418 if (!parse_return_type (ctx, &ptr, end))
1419 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1421 for (i = 0; i < param_count; ++i) {
1422 if (allow_sentinel) {
1423 if (!safe_read8 (type, ptr, end))
1424 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1426 if (type == MONO_TYPE_SENTINEL) {
1427 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1428 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1431 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1433 saw_sentinel = TRUE;
1439 if (!parse_param (ctx, &ptr, end))
1440 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1448 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1451 unsigned param_count = 0, i;
1452 const char *ptr = *_ptr;
1454 if (!safe_read8 (sig, ptr, end))
1455 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1457 if (sig != 0x08 && sig != 0x28)
1458 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1460 if (!safe_read_cint (param_count, ptr, end))
1461 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1463 if (!parse_custom_mods (ctx, &ptr, end))
1466 if (!parse_type (ctx, &ptr, end))
1467 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1469 for (i = 0; i < param_count; ++i) {
1470 if (!parse_type (ctx, &ptr, end))
1471 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1479 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1481 const char *ptr = *_ptr;
1482 guint8 signature = 0;
1484 if (!safe_read8 (signature, ptr, end))
1485 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1487 if (signature != 0x06)
1488 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1491 if (!parse_custom_mods (ctx, _ptr, end))
1494 return parse_type (ctx, _ptr, end);
1498 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1501 unsigned locals_count = 0, i;
1502 const char *ptr = *_ptr;
1504 if (!safe_read8 (sig, ptr, end))
1505 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1508 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1510 if (!safe_read_cint (locals_count, ptr, end))
1511 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1513 if (locals_count == 0)
1514 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1516 for (i = 0; i < locals_count; ++i) {
1517 if (!safe_read8 (sig, ptr, end))
1518 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1520 if (sig == MONO_TYPE_TYPEDBYREF)
1523 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1524 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1525 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1526 if (!safe_read8 (sig, ptr, end))
1527 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1530 if (!parse_type (ctx, &ptr, end))
1531 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1539 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1541 int size = 0, signature = 0;
1542 const char *ptr = NULL, *end;
1544 if (!decode_signature_header (ctx, offset, &size, &ptr))
1545 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1548 if (!safe_read8 (signature, ptr, end))
1549 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1552 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1555 return parse_field (ctx, &ptr, end);
1559 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1562 const char *ptr = NULL, *end;
1564 if (!decode_signature_header (ctx, offset, &size, &ptr))
1565 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1568 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1572 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1575 unsigned signature = 0;
1576 const char *ptr = NULL, *end;
1578 if (!decode_signature_header (ctx, offset, &size, &ptr))
1579 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1582 if (!safe_read8 (signature, ptr, end))
1583 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1586 if (signature == 0x06)
1587 return parse_field (ctx, &ptr, end);
1589 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1593 is_vald_cattr_blob (VerifyContext *ctx, guint32 offset)
1597 const char *ptr = NULL, *end;
1602 if (!decode_signature_header (ctx, offset, &size, &ptr))
1603 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1606 if (!safe_read16 (prolog, ptr, end))
1607 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1610 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1616 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
1618 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1619 //TODO do proper verification
1620 return blob.size >= 1 && blob.size - 1 >= offset;
1624 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
1626 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1627 //TODO do proper verification
1628 return blob.size >= 1 && blob.size - 1 >= offset;
1632 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
1635 unsigned signature = 0;
1636 const char *ptr = NULL, *end;
1638 if (!decode_signature_header (ctx, offset, &size, &ptr))
1639 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
1642 if (!safe_read8 (signature, ptr, end))
1643 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
1646 if (signature == 0x07)
1647 return parse_locals_signature (ctx, &ptr, end);
1648 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
1652 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
1655 const char *ptr = NULL, *end;
1657 if (!decode_signature_header (ctx, offset, &size, &ptr))
1658 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
1661 return parse_property_signature (ctx, &ptr, end);
1665 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
1668 const char *ptr = NULL, *end;
1672 if (!decode_signature_header (ctx, offset, &size, &ptr))
1673 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
1676 if (!parse_custom_mods (ctx, &ptr, end))
1679 if (!safe_read8 (type, ptr, end))
1680 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
1683 if (type == MONO_TYPE_TYPEDBYREF)
1686 return parse_type (ctx, &ptr, end);
1690 is_valid_methodspec_blog (VerifyContext *ctx, guint32 offset)
1693 const char *ptr = NULL, *end;
1695 guint32 count = 0, i;
1697 if (!decode_signature_header (ctx, offset, &size, &ptr))
1698 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
1701 if (!safe_read8 (type, ptr, end))
1702 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
1705 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
1707 if (!safe_read_cint (count, ptr, end))
1708 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
1711 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
1713 for (i = 0; i < count; ++i) {
1714 if (!parse_type (ctx, &ptr, end))
1715 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
1721 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
1723 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1724 guint32 entry_size, bytes;
1726 if (blob.size < offset)
1729 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1732 if (entry_size < minsize)
1735 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
1737 entry_size += bytes;
1739 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
1743 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
1745 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1746 guint32 size, entry_size, bytes;
1748 if (blob.size < offset)
1749 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
1751 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1752 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
1754 if (type == MONO_TYPE_STRING) {
1755 //String is encoded as: compressed_int:len len *bytes
1758 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
1759 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
1765 case MONO_TYPE_BOOLEAN:
1770 case MONO_TYPE_CHAR:
1778 case MONO_TYPE_CLASS:
1788 g_assert_not_reached ();
1791 if (size != entry_size)
1792 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
1796 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
1797 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
1799 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
1800 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
1804 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
1805 //only 0x01, 0x40 and 0x80 are allowed
1806 #define SECTION_HEADER_INVALID_FLAGS 0x3E
1809 is_valid_method_header (VerifyContext *ctx, guint32 rva)
1811 guint32 local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
1813 guint16 fat_header = 0, size = 0, max_stack;
1814 const char *ptr = NULL, *end;
1816 if (offset == INVALID_ADDRESS)
1817 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
1819 ptr = ctx->data + offset;
1820 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
1822 if (!safe_read8 (header, ptr, end))
1823 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
1825 switch (header & 0x3) {
1828 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
1831 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
1832 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
1837 if (!safe_read16 (fat_header, ptr, end))
1838 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
1840 size = (fat_header >> 12) & 0xF;
1842 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
1844 if (!safe_read16 (max_stack, ptr, end))
1845 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
1847 if (!safe_read32 (code_size, ptr, end))
1848 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
1850 if (!safe_read32 (local_vars_tok, ptr, end))
1851 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
1853 if (local_vars_tok) {
1854 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
1855 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
1856 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
1857 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
1860 if (fat_header & FAT_HEADER_INVALID_FLAGS)
1861 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
1863 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
1864 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
1866 if (!(fat_header & 0x08))
1872 guint32 section_header = 0, section_size = 0;
1875 ptr = dword_align (ptr);
1876 if (!safe_read32 (section_header, ptr, end))
1877 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
1879 if (section_header & SECTION_HEADER_INVALID_FLAGS)
1880 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
1882 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
1883 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
1885 if (section_size < 4)
1886 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
1888 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
1889 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
1891 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
1892 guint32 i, clauses = (section_size - 4) / (is_fat ? 24 : 12);
1893 if (clauses * (is_fat ? 24 : 12) + 4 != section_size)
1894 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the proper size", section_size));
1896 /* only verify the class token is verified as the rest is done by the IL verifier*/
1897 for (i = 0; i < clauses; ++i) {
1898 guint32 class_token = 0;
1899 ptr += (is_fat ? 20 : 8);
1900 if (!safe_read32 (class_token, ptr, end))
1901 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
1902 if (!*ptr == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
1903 guint table = mono_metadata_token_table (class_token);
1904 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
1905 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
1906 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
1907 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
1912 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
1919 verify_module_table (VerifyContext *ctx)
1921 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
1922 guint32 data [MONO_MODULE_SIZE];
1924 if (table->rows != 1)
1925 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
1927 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
1929 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
1930 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
1932 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
1933 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
1935 if (data [MONO_MODULE_ENC] != 0)
1936 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
1938 if (data [MONO_MODULE_ENCBASE] != 0)
1939 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
1943 verify_typeref_table (VerifyContext *ctx)
1945 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
1946 guint32 data [MONO_TYPEREF_SIZE];
1949 for (i = 0; i < table->rows; ++i) {
1950 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
1951 if (!is_valid_coded_index (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1952 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i, data [MONO_TYPEREF_SCOPE]));
1954 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1955 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i));
1957 if (!data [MONO_TYPEREF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAME]))
1958 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d name token 0x%08x", i, data [MONO_TYPEREF_NAME]));
1960 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
1961 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d namespace token 0x%08x", i, data [MONO_TYPEREF_NAMESPACE]));
1965 /*bits 9,11,14,15,19,21,24-31 */
1966 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
1968 verify_typedef_table (VerifyContext *ctx)
1970 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
1971 guint32 data [MONO_TYPEDEF_SIZE];
1972 guint32 fieldlist = 1, methodlist = 1;
1975 if (table->rows == 0)
1976 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
1978 for (i = 0; i < table->rows; ++i) {
1979 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
1980 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
1981 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
1983 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
1984 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
1986 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
1987 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
1989 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
1990 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
1992 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
1993 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
1995 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
1996 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
1998 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
1999 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2001 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2002 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2004 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2005 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2007 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2008 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2010 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2011 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));
2013 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2014 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2016 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2017 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2019 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2020 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));
2022 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2023 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2028 verify_typedef_table_full (VerifyContext *ctx)
2030 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2031 guint32 data [MONO_TYPEDEF_SIZE];
2034 if (table->rows == 0)
2035 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2037 for (i = 0; i < table->rows; ++i) {
2038 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2041 if (data [MONO_TYPEDEF_EXTENDS] != 0)
2042 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2046 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2047 if (data [MONO_TYPEDEF_EXTENDS])
2048 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2050 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2051 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2055 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2058 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2066 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2068 verify_field_table (VerifyContext *ctx)
2070 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2071 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2074 module_field_list = (guint32)-1;
2075 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2076 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2077 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2080 for (i = 0; i < table->rows; ++i) {
2081 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2082 flags = data [MONO_FIELD_FLAGS];
2084 if (flags & INVALID_FIELD_FLAG_BITS)
2085 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2087 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2088 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2090 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2091 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2093 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2094 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2096 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2097 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2099 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2100 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2101 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2103 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2104 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2105 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2107 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2108 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2109 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2111 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2112 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2113 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2115 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2116 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2118 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2119 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2121 //TODO verify contant flag
2123 if (i + 1 < module_field_list) {
2124 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2125 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2126 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2127 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2128 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2134 verify_field_table_full (VerifyContext *ctx)
2136 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2137 guint32 data [MONO_FIELD_SIZE];
2140 for (i = 0; i < table->rows; ++i) {
2141 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2143 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2144 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2148 /*bits 6,8,9,10,11,13,14,15*/
2149 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2151 verify_method_table (VerifyContext *ctx)
2153 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2154 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2155 guint32 paramlist = 1;
2156 gboolean is_ctor, is_cctor;
2160 module_method_list = (guint32)-1;
2161 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2162 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2163 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2166 for (i = 0; i < table->rows; ++i) {
2167 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2168 rva = data [MONO_METHOD_RVA];
2169 implflags = data [MONO_METHOD_IMPLFLAGS];
2170 flags = data [MONO_METHOD_FLAGS];
2171 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2172 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2175 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2176 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2179 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2181 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2182 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2184 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2185 is_ctor = !strcmp (".ctor", name);
2186 is_cctor = !strcmp (".cctor", name);
2188 if ((is_ctor || is_cctor) &&
2189 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2190 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2192 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2193 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2195 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2196 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2197 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2198 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2199 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2202 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2203 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2205 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2206 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2208 //XXX no checks against cas stuff 10,11,12,13)
2210 //TODO check iface with .ctor (15,16)
2212 if (i + 1 < module_method_list) {
2213 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2214 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2215 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2216 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2217 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2218 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2221 //TODO check valuetype for synchronized
2223 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2224 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2226 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (flags & METHOD_ATTRIBUTE_VIRTUAL))
2227 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2229 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2230 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2231 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2233 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2234 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2236 //TODO check signature contents
2239 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2240 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2241 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2242 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2244 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2245 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2248 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2250 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2251 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2252 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2254 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2255 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2257 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2258 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2260 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2261 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2263 if (data [MONO_METHOD_PARAMLIST] == 0)
2264 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2266 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2267 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));
2269 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2270 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2272 paramlist = data [MONO_METHOD_PARAMLIST];
2278 verify_method_table_full (VerifyContext *ctx)
2280 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2281 guint32 data [MONO_METHOD_SIZE], rva;
2284 for (i = 0; i < table->rows; ++i) {
2285 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2286 rva = data [MONO_METHOD_RVA];
2288 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2289 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2291 if (rva && !is_valid_method_header (ctx, rva))
2292 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2297 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2299 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2300 guint32 row = *current_method;
2301 guint32 paramlist, tmp;
2304 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2305 while (row < table->rows) {
2306 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2307 if (tmp > paramlist) {
2308 *current_method = row;
2309 return tmp - paramlist;
2314 /*no more methods, all params apply to the last one*/
2315 *current_method = table->rows;
2320 #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))
2322 verify_param_table (VerifyContext *ctx)
2324 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2325 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2326 gboolean first_param = TRUE;
2329 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2330 if (table->rows > 0)
2331 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2335 remaining_params = get_next_param_count (ctx, ¤t_method);
2337 for (i = 0; i < table->rows; ++i) {
2338 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2339 flags = data [MONO_PARAM_FLAGS];
2341 if (flags & INVALID_PARAM_FLAGS_BITS)
2342 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2344 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2345 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2346 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2348 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2349 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2352 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)
2353 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2355 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2356 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2358 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2359 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2361 first_param = FALSE;
2362 sequence = data [MONO_PARAM_SEQUENCE];
2363 if (--remaining_params == 0) {
2364 remaining_params = get_next_param_count (ctx, ¤t_method);
2371 verify_interfaceimpl_table (VerifyContext *ctx)
2373 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2374 guint32 data [MONO_INTERFACEIMPL_SIZE];
2377 for (i = 0; i < table->rows; ++i) {
2378 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2379 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2380 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2382 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2383 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2385 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2386 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2391 verify_memberref_table (VerifyContext *ctx)
2393 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2394 guint32 data [MONO_MEMBERREF_SIZE];
2397 for (i = 0; i < table->rows; ++i) {
2398 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2400 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2401 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2403 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2404 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2406 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2407 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2409 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2410 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2416 verify_memberref_table_full (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_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2426 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2431 verify_constant_table (VerifyContext *ctx)
2433 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2434 guint32 data [MONO_CONSTANT_SIZE], type;
2437 for (i = 0; i < table->rows; ++i) {
2438 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2439 type = data [MONO_CONSTANT_TYPE];
2441 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2442 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2444 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2445 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2447 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2448 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2450 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2451 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2456 verify_cattr_table (VerifyContext *ctx)
2458 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2459 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2462 for (i = 0; i < table->rows; ++i) {
2463 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2465 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2466 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2468 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2469 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2471 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2472 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2477 verify_cattr_table_full (VerifyContext *ctx)
2479 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2480 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2483 for (i = 0; i < table->rows; ++i) {
2484 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2486 if (!is_vald_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2487 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2492 verify_field_marshal_table (VerifyContext *ctx)
2494 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2495 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2498 for (i = 0; i < table->rows; ++i) {
2499 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2501 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2502 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2504 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2505 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2507 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2508 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2510 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2511 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2516 verify_field_marshal_table_full (VerifyContext *ctx)
2518 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2519 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2522 for (i = 0; i < table->rows; ++i) {
2523 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2525 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2526 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2531 verify_decl_security_table (VerifyContext *ctx)
2533 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2534 guint32 data [MONO_DECL_SECURITY_SIZE];
2537 for (i = 0; i < table->rows; ++i) {
2538 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2540 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2541 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2543 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2544 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
2546 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
2547 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
2552 verify_decl_security_table_full (VerifyContext *ctx)
2554 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2555 guint32 data [MONO_DECL_SECURITY_SIZE];
2558 for (i = 0; i < table->rows; ++i) {
2559 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2561 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
2562 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
2567 verify_class_layout_table (VerifyContext *ctx)
2569 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
2570 guint32 data [MONO_CLASS_LAYOUT_SIZE];
2573 for (i = 0; i < table->rows; ++i) {
2574 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
2576 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2577 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2579 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
2591 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
2597 verify_field_layout_table (VerifyContext *ctx)
2599 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
2600 guint32 data [MONO_FIELD_LAYOUT_SIZE];
2603 for (i = 0; i < table->rows; ++i) {
2604 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
2606 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2607 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
2612 verify_standalonesig_table (VerifyContext *ctx)
2614 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2615 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2618 for (i = 0; i < table->rows; ++i) {
2619 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2621 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
2622 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2627 verify_standalonesig_table_full (VerifyContext *ctx)
2629 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2630 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2633 for (i = 0; i < table->rows; ++i) {
2634 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2636 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
2637 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2642 verify_eventmap_table (VerifyContext *ctx)
2644 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
2645 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
2648 for (i = 0; i < table->rows; ++i) {
2649 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
2651 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2652 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
2654 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
2655 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
2657 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
2661 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
2663 verify_event_table (VerifyContext *ctx)
2665 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2666 guint32 data [MONO_EVENT_SIZE];
2669 for (i = 0; i < table->rows; ++i) {
2670 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2672 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
2673 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
2675 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
2676 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
2678 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
2679 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
2684 verify_event_table_full (VerifyContext *ctx)
2686 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2687 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
2688 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
2689 gboolean found_add, found_remove;
2692 for (i = 0; i < table->rows; ++i) {
2693 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2695 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
2696 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
2698 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
2700 //first we move to the first row for this event
2702 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
2706 //now move forward looking for AddOn and RemoveOn rows
2707 found_add = found_remove = FALSE;
2708 while (idx < sema_table->rows) {
2709 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
2710 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
2712 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
2714 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
2715 found_remove = TRUE;
2716 if (found_add && found_remove)
2722 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2724 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2729 verify_propertymap_table (VerifyContext *ctx)
2731 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
2732 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
2735 for (i = 0; i < table->rows; ++i) {
2736 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
2738 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2739 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
2741 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
2742 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
2744 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
2748 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
2750 verify_property_table (VerifyContext *ctx)
2752 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
2753 guint32 data [MONO_PROPERTY_SIZE];
2756 for (i = 0; i < table->rows; ++i) {
2757 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
2759 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
2760 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
2762 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
2763 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
2765 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
2766 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
2768 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
2769 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
2770 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
2776 verify_methodimpl_table (VerifyContext *ctx)
2778 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
2779 guint32 data [MONO_METHODIMPL_SIZE];
2782 for (i = 0; i < table->rows; ++i) {
2783 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
2785 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2786 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2788 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2789 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2791 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2792 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2794 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2795 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2797 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2798 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2803 verify_moduleref_table (VerifyContext *ctx)
2805 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
2806 guint32 data [MONO_MODULEREF_SIZE];
2809 for (i = 0; i < table->rows; ++i) {
2810 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
2812 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
2813 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2818 verify_typespec_table (VerifyContext *ctx)
2820 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2821 guint32 data [MONO_TYPESPEC_SIZE];
2824 for (i = 0; i < table->rows; ++i) {
2825 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2827 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
2828 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2833 verify_typespec_table_full (VerifyContext *ctx)
2835 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2836 guint32 data [MONO_TYPESPEC_SIZE];
2839 for (i = 0; i < table->rows; ++i) {
2840 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2842 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
2843 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2847 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10))
2849 verify_implmap_table (VerifyContext *ctx)
2851 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
2852 guint32 data [MONO_IMPLMAP_SIZE], cconv;
2855 for (i = 0; i < table->rows; ++i) {
2856 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
2858 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
2859 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
2861 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
2862 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
2863 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
2865 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2866 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
2868 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
2869 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
2871 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2872 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
2874 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
2875 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
2877 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows + 1)
2878 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
2883 verify_fieldrva_table (VerifyContext *ctx)
2885 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
2886 guint32 data [MONO_FIELD_RVA_SIZE];
2889 for (i = 0; i < table->rows; ++i) {
2890 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
2892 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
2893 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
2895 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2896 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
2900 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
2902 verify_assembly_table (VerifyContext *ctx)
2904 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
2905 guint32 data [MONO_ASSEMBLY_SIZE], hash;
2908 if (table->rows > 1)
2909 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
2911 for (i = 0; i < table->rows; ++i) {
2912 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
2914 hash = data [MONO_ASSEMBLY_HASH_ALG];
2915 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
2916 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
2918 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
2919 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2921 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
2922 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2924 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
2925 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
2927 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
2928 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
2932 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
2934 verify_assemblyref_table (VerifyContext *ctx)
2936 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
2937 guint32 data [MONO_ASSEMBLYREF_SIZE];
2940 for (i = 0; i < table->rows; ++i) {
2941 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
2943 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
2944 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
2946 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
2947 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
2949 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
2950 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
2952 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
2953 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
2955 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
2956 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
2960 #define INVALID_FILE_FLAGS_BITS ~(1)
2962 verify_file_table (VerifyContext *ctx)
2964 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
2965 guint32 data [MONO_FILE_SIZE];
2968 for (i = 0; i < table->rows; ++i) {
2969 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
2971 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
2972 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
2974 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
2975 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
2977 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
2978 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
2982 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
2984 verify_exportedtype_table (VerifyContext *ctx)
2986 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
2987 guint32 data [MONO_EXP_TYPE_SIZE];
2990 for (i = 0; i < table->rows; ++i) {
2991 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
2993 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
2994 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
2996 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
2997 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
2999 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3000 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3002 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3003 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3005 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3006 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3008 /*nested type can't have a namespace*/
3009 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3010 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3014 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3016 verify_manifest_resource_table (VerifyContext *ctx)
3018 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3019 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3020 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3021 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3024 resources_size = ch->ch_resources.size;
3026 for (i = 0; i < table->rows; ++i) {
3027 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3029 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3030 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3032 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3033 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3035 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3036 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3038 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3039 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3041 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3042 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3044 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3045 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])));
3047 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3048 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3050 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3051 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3056 verify_nested_class_table (VerifyContext *ctx)
3058 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3059 guint32 data [MONO_NESTED_CLASS_SIZE];
3062 for (i = 0; i < table->rows; ++i) {
3063 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3065 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3066 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3067 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3068 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3069 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3070 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3074 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3076 verify_generic_param_table (VerifyContext *ctx)
3078 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3079 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3080 int i, param_number = 0;
3082 for (i = 0; i < table->rows; ++i) {
3083 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3085 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3086 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3088 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3089 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3091 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3092 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3094 token = data [MONO_GENERICPARAM_OWNER];
3096 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3097 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3099 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3100 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3102 if (token != last_token) {
3107 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3108 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));
3115 verify_method_spec_table (VerifyContext *ctx)
3117 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3118 guint32 data [MONO_METHODSPEC_SIZE];
3121 for (i = 0; i < table->rows; ++i) {
3122 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3124 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3125 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3127 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3128 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3130 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3131 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3136 verify_method_spec_table_full (VerifyContext *ctx)
3138 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3139 guint32 data [MONO_METHODSPEC_SIZE];
3142 for (i = 0; i < table->rows; ++i) {
3143 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3145 if (!is_valid_methodspec_blog (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3146 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3151 verify_generic_param_constraint_table (VerifyContext *ctx)
3153 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3154 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3157 for (i = 0; i < table->rows; ++i) {
3158 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3160 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3161 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_TABLE_GENERICPARAM]));
3163 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3164 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3166 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3167 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3172 verify_tables_data (VerifyContext *ctx)
3174 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3175 guint32 size = 0, tables_offset;
3178 for (i = 0; i < 0x2D; ++i) {
3179 MonoTableInfo *table = &ctx->image->tables [i];
3181 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3182 if (tmp_size < size) {
3190 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3192 tables_offset = ctx->image->tables_base - ctx->data;
3193 if (!bounds_check_offset (&tables_area, tables_offset, size))
3194 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)));
3196 verify_module_table (ctx);
3198 verify_typeref_table (ctx);
3200 verify_typedef_table (ctx);
3202 verify_field_table (ctx);
3204 verify_method_table (ctx);
3206 verify_param_table (ctx);
3208 verify_interfaceimpl_table (ctx);
3210 verify_memberref_table (ctx);
3212 verify_constant_table (ctx);
3214 verify_cattr_table (ctx);
3216 verify_field_marshal_table (ctx);
3218 verify_decl_security_table (ctx);
3220 verify_class_layout_table (ctx);
3222 verify_field_layout_table (ctx);
3224 verify_standalonesig_table (ctx);
3226 verify_eventmap_table (ctx);
3228 verify_event_table (ctx);
3230 verify_propertymap_table (ctx);
3232 verify_property_table (ctx);
3234 verify_methodimpl_table (ctx);
3236 verify_moduleref_table (ctx);
3238 verify_typespec_table (ctx);
3240 verify_implmap_table (ctx);
3242 verify_fieldrva_table (ctx);
3244 verify_assembly_table (ctx);
3246 verify_assemblyref_table (ctx);
3248 verify_file_table (ctx);
3250 verify_exportedtype_table (ctx);
3252 verify_manifest_resource_table (ctx);
3254 verify_nested_class_table (ctx);
3256 verify_generic_param_table (ctx);
3258 verify_method_spec_table (ctx);
3260 verify_generic_param_constraint_table (ctx);
3264 init_verify_context (VerifyContext *ctx, MonoImage *image, GSList **error_list)
3266 memset (ctx, 0, sizeof (VerifyContext));
3268 ctx->report_error = error_list != NULL;
3270 ctx->size = image->raw_data_len;
3271 ctx->data = image->raw_data;
3275 cleanup_context (VerifyContext *ctx, GSList **error_list)
3277 g_free (ctx->sections);
3279 *error_list = ctx->errors;
3281 mono_free_verify_list (ctx->errors);
3286 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3290 if (!mono_verifier_is_enabled_for_image (image))
3293 init_verify_context (&ctx, image, error_list);
3294 ctx.stage = STAGE_PE;
3296 verify_msdos_header (&ctx);
3298 verify_pe_header (&ctx);
3300 verify_pe_optional_header (&ctx);
3302 load_section_table (&ctx);
3304 load_data_directories (&ctx);
3306 verify_import_table (&ctx);
3308 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3309 verify_resources_table (&ctx);
3312 return cleanup_context (&ctx, error_list);
3316 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3320 if (!mono_verifier_is_enabled_for_image (image))
3323 init_verify_context (&ctx, image, error_list);
3324 ctx.stage = STAGE_CLI;
3326 verify_cli_header (&ctx);
3328 verify_metadata_header (&ctx);
3330 verify_tables_schema (&ctx);
3333 return cleanup_context (&ctx, error_list);
3338 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3339 * Other verification checks are meant to be done lazily by the runtime. Those include:
3340 * blob items (signatures, method headers, custom attributes, etc)
3341 * type semantics related
3343 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3345 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3346 * operation still need more checking.
3349 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3353 if (!mono_verifier_is_enabled_for_image (image))
3356 init_verify_context (&ctx, image, error_list);
3357 ctx.stage = STAGE_TABLES;
3359 verify_tables_data (&ctx);
3361 return cleanup_context (&ctx, error_list);
3366 * Verifies all other constraints.
3369 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3373 if (!mono_verifier_is_enabled_for_image (image))
3376 init_verify_context (&ctx, image, error_list);
3377 ctx.stage = STAGE_TABLES;
3379 verify_typedef_table_full (&ctx);
3381 verify_field_table_full (&ctx);
3383 verify_method_table_full (&ctx);
3385 verify_memberref_table_full (&ctx);
3387 verify_cattr_table_full (&ctx);
3389 verify_field_marshal_table_full (&ctx);
3391 verify_decl_security_table_full (&ctx);
3393 verify_standalonesig_table_full (&ctx);
3395 verify_event_table_full (&ctx);
3397 verify_typespec_table_full (&ctx);
3399 verify_method_spec_table_full (&ctx);
3402 return cleanup_context (&ctx, error_list);
3406 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3410 if (!mono_verifier_is_enabled_for_image (image))
3413 init_verify_context (&ctx, image, error_list);
3414 ctx.stage = STAGE_TABLES;
3416 is_valid_field_signature (&ctx, offset);
3417 return cleanup_context (&ctx, error_list);
3421 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3425 if (!mono_verifier_is_enabled_for_image (image))
3428 init_verify_context (&ctx, image, error_list);
3429 ctx.stage = STAGE_TABLES;
3431 is_valid_method_header (&ctx, offset);
3432 return cleanup_context (&ctx, error_list);
3436 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3440 if (!mono_verifier_is_enabled_for_image (image))
3443 init_verify_context (&ctx, image, error_list);
3444 ctx.stage = STAGE_TABLES;
3446 is_valid_method_signature (&ctx, offset);
3447 return cleanup_context (&ctx, error_list);
3451 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3455 if (!mono_verifier_is_enabled_for_image (image))
3458 init_verify_context (&ctx, image, error_list);
3459 ctx.stage = STAGE_TABLES;
3461 is_valid_method_or_field_signature (&ctx, offset);
3462 return cleanup_context (&ctx, error_list);
3466 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3470 if (!mono_verifier_is_enabled_for_image (image))
3473 init_verify_context (&ctx, image, error_list);
3474 ctx.stage = STAGE_TABLES;
3476 is_valid_standalonesig_blob (&ctx, offset);
3477 return cleanup_context (&ctx, error_list);
3481 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3485 if (!mono_verifier_is_enabled_for_image (image))
3488 init_verify_context (&ctx, image, error_list);
3489 ctx.stage = STAGE_TABLES;
3491 is_valid_typespec_blob (&ctx, offset);
3492 return cleanup_context (&ctx, error_list);
3496 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3500 if (!mono_verifier_is_enabled_for_image (image))
3503 init_verify_context (&ctx, image, error_list);
3504 ctx.stage = STAGE_TABLES;
3506 is_valid_methodspec_blog (&ctx, offset);
3507 return cleanup_context (&ctx, error_list);
3512 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3518 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3524 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3530 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3536 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3542 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3548 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3554 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3560 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3566 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3572 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3577 #endif /* DISABLE_VERIFIER */