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>
26 #include <mono/utils/mono-error-internals.h>
27 #include <mono/utils/bsearch.h>
32 #ifndef DISABLE_VERIFIER
34 TODO add fail fast mode
35 TODO add PE32+ support
36 TODO verify the entry point RVA and content.
37 TODO load_section_table and load_data_directories must take PE32+ into account
38 TODO add section relocation support
39 TODO verify the relocation table, since we really don't use, no need so far.
40 TODO do full PECOFF resources verification
41 TODO verify in the CLI header entry point and resources
42 TODO implement null token typeref validation
43 TODO verify table wide invariants for typedef (sorting and uniqueness)
44 TODO implement proper authenticode data directory validation
45 TODO verify properties that require multiple tables to be valid
46 FIXME use subtraction based bounds checking to avoid overflows
47 FIXME get rid of metadata_streams and other fields from VerifyContext
50 #ifdef MONO_VERIFIER_DEBUG
51 #define VERIFIER_DEBUG(code) do { code; } while (0)
53 #define VERIFIER_DEBUG(code)
56 #define INVALID_OFFSET ((guint32)-1)
57 #define INVALID_ADDRESS 0xffffffff
67 RESOURCE_TABLE_IDX = 2,
68 CERTIFICATE_TABLE_IDX = 4,
69 RELOCATION_TABLE_IDX = 5,
83 #define INVALID_TABLE (0xFF)
84 /*format: number of bits, number of tables, tables{n. tables} */
85 const static unsigned char coded_index_desc[] = {
86 #define TYPEDEF_OR_REF_DESC (0)
93 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
100 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
108 MONO_TABLE_INTERFACEIMPL,
109 MONO_TABLE_MEMBERREF,
111 MONO_TABLE_DECLSECURITY,
114 MONO_TABLE_STANDALONESIG,
115 MONO_TABLE_MODULEREF,
118 MONO_TABLE_ASSEMBLYREF,
120 MONO_TABLE_EXPORTEDTYPE,
121 MONO_TABLE_MANIFESTRESOURCE,
122 MONO_TABLE_GENERICPARAM,
124 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
130 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
137 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
142 MONO_TABLE_MODULEREF,
146 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
152 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
156 MONO_TABLE_MEMBERREF,
158 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
164 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
168 MONO_TABLE_ASSEMBLYREF,
169 MONO_TABLE_EXPORTEDTYPE,
171 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
177 MONO_TABLE_MEMBERREF,
180 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
184 MONO_TABLE_MODULEREF,
185 MONO_TABLE_ASSEMBLYREF,
188 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
198 guint32 translated_offset;
210 guint32 rellocationsRVA;
211 guint16 numberOfRelocations;
226 gboolean report_error;
227 gboolean report_warning;
230 DataDirectory data_directories [16];
231 guint32 section_count;
232 SectionHeader *sections;
234 OffsetAndSize metadata_streams [5]; //offset from begin of the image
237 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
239 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
240 vinfo->info.status = __status; \
241 vinfo->info.message = ( __msg); \
242 vinfo->exception_type = (__exception); \
243 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
246 #define ADD_WARNING(__ctx, __msg) \
248 if ((__ctx)->report_warning) { \
249 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
250 (__ctx)->valid = 0; \
255 #define ADD_ERROR_NO_RETURN(__ctx, __msg) \
257 if ((__ctx)->report_error) \
258 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
259 (__ctx)->valid = 0; \
262 #define ADD_ERROR(__ctx, __msg) \
264 if ((__ctx)->report_error) \
265 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
266 (__ctx)->valid = 0; \
270 #define FAIL(__ctx, __msg) \
272 if ((__ctx)->report_error) \
273 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
274 (__ctx)->valid = 0; \
278 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
280 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
282 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
283 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
285 #if SIZEOF_VOID_P == 4
286 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
288 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
291 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
292 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
295 dword_align (const char *ptr)
297 #if SIZEOF_VOID_P == 8
298 return (const char *) (((guint64) (ptr + 3)) & ~3);
300 return (const char *) (((guint32) (ptr + 3)) & ~3);
305 add_from_mono_error (VerifyContext *ctx, MonoError *error)
307 if (mono_error_ok (error))
310 ADD_ERROR (ctx, g_strdup (mono_error_get_message (error)));
311 mono_error_cleanup (error);
315 pe_signature_offset (VerifyContext *ctx)
317 return read32 (ctx->data + 0x3c);
321 pe_header_offset (VerifyContext *ctx)
323 return read32 (ctx->data + 0x3c) + 4;
327 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
331 if (rva + size < rva) //overflow
334 if (ctx->stage > STAGE_PE) {
335 MonoCLIImageInfo *iinfo = ctx->image->image_info;
336 const int top = iinfo->cli_section_count;
337 MonoSectionTable *tables = iinfo->cli_section_tables;
340 for (i = 0; i < top; i++) {
341 guint32 base = tables->st_virtual_address;
342 guint32 end = base + tables->st_raw_data_size;
344 if (rva >= base && rva + size <= end)
347 /*if ((addr >= tables->st_virtual_address) &&
348 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
350 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
360 for (i = 0; i < ctx->section_count; ++i) {
361 guint32 base = ctx->sections [i].baseRVA;
362 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
363 if (rva >= base && rva + size <= end)
370 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
372 if (dir->translated_offset > offset)
374 if (dir->size < size)
376 return offset + size <= dir->translated_offset + dir->size;
380 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
382 if (off->offset > offset)
385 if (off->size < size)
388 return offset + size <= off->offset + off->size;
392 translate_rva (VerifyContext *ctx, guint32 rva)
396 if (ctx->stage > STAGE_PE)
397 return mono_cli_rva_image_map (ctx->image, rva);
402 for (i = 0; i < ctx->section_count; ++i) {
403 guint32 base = ctx->sections [i].baseRVA;
404 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
405 if (rva >= base && rva <= end) {
406 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
408 return res >= ctx->size ? INVALID_OFFSET : res;
412 return INVALID_OFFSET;
416 verify_msdos_header (VerifyContext *ctx)
420 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
421 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
422 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
423 lfanew = pe_signature_offset (ctx);
424 if (lfanew > ctx->size - 4)
425 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
429 verify_pe_header (VerifyContext *ctx)
431 guint32 offset = pe_signature_offset (ctx);
432 const char *pe_header = ctx->data + offset;
433 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
434 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
438 if (offset > ctx->size - 20)
439 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
440 if (read16 (pe_header) != 0x14c)
441 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
445 verify_pe_optional_header (VerifyContext *ctx)
447 guint32 offset = pe_header_offset (ctx);
448 guint32 header_size, file_alignment;
449 const char *pe_header = ctx->data + offset;
450 const char *pe_optional_header = pe_header + 20;
452 header_size = read16 (pe_header + 16);
455 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
456 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
458 if (offset > ctx->size - header_size || header_size > ctx->size)
459 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
461 if (read16 (pe_optional_header) == 0x10b) {
462 if (header_size != 224)
463 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
465 /* LAMESPEC MS plays around this value and ignore it during validation
466 if (read32 (pe_optional_header + 28) != 0x400000)
467 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
468 if (read32 (pe_optional_header + 32) != 0x2000)
469 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
470 file_alignment = read32 (pe_optional_header + 36);
471 if (file_alignment != 0x200 && file_alignment != 0x1000)
472 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
473 /* All the junk in the middle is irrelevant, specially for mono. */
474 if (read32 (pe_optional_header + 92) > 0x10)
475 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
477 if (read16 (pe_optional_header) == 0x20B)
478 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
480 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
485 load_section_table (VerifyContext *ctx)
488 SectionHeader *sections;
489 guint32 offset = pe_header_offset (ctx);
490 const char *ptr = ctx->data + offset;
491 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
493 offset += 244;/*FIXME, this constant is different under PE32+*/
496 if (num_sections * 40 > ctx->size - offset)
497 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
499 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
500 for (i = 0; i < num_sections; ++i) {
501 sections [i].size = read32 (ptr + 8);
502 sections [i].baseRVA = read32 (ptr + 12);
503 sections [i].baseOffset = read32 (ptr + 20);
504 sections [i].rellocationsRVA = read32 (ptr + 24);
505 sections [i].numberOfRelocations = read16 (ptr + 32);
509 ptr = ctx->data + offset; /*reset it to the beggining*/
510 for (i = 0; i < num_sections; ++i) {
511 guint32 raw_size, flags;
512 if (sections [i].baseOffset == 0)
513 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
514 if (sections [i].baseOffset >= ctx->size)
515 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
516 if (sections [i].size > ctx->size - sections [i].baseOffset)
517 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
519 raw_size = read32 (ptr + 16);
520 if (raw_size < sections [i].size)
521 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
523 if (raw_size > ctx->size - sections [i].baseOffset)
524 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
526 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
527 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
529 flags = read32 (ptr + 36);
530 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
531 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
532 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
539 is_valid_data_directory (int i)
541 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
542 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
546 load_data_directories (VerifyContext *ctx)
548 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
549 const char *ptr = ctx->data + offset;
552 for (i = 0; i < 16; ++i) {
553 guint32 rva = read32 (ptr);
554 guint32 size = read32 (ptr + 4);
556 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
557 if (i == CERTIFICATE_TABLE_IDX) {
561 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
562 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
564 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
565 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
567 ctx->data_directories [i].rva = rva;
568 ctx->data_directories [i].size = size;
569 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
575 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
577 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
580 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
583 guint32 hint_table_rva;
585 import_rva = translate_rva (ctx, import_rva);
586 g_assert (import_rva != INVALID_OFFSET);
588 hint_table_rva = read32 (ctx->data + import_rva);
589 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
590 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
592 hint_table_rva = translate_rva (ctx, hint_table_rva);
593 g_assert (hint_table_rva != INVALID_OFFSET);
594 ptr = ctx->data + hint_table_rva + 2;
596 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
597 char name[SIZE_OF_CORMAIN];
598 memcpy (name, ptr, SIZE_OF_CORMAIN);
599 name [SIZE_OF_CORMAIN - 1] = 0;
600 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
605 verify_import_table (VerifyContext *ctx)
607 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
608 guint32 offset = it.translated_offset;
609 const char *ptr = ctx->data + offset;
610 guint32 name_rva, ilt_rva, iat_rva;
612 g_assert (offset != INVALID_OFFSET);
615 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
617 ilt_rva = read32 (ptr);
618 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
619 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
621 name_rva = read32 (ptr + 12);
622 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
623 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
625 iat_rva = read32 (ptr + 16);
627 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
628 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
630 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
631 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));
635 name_rva = translate_rva (ctx, name_rva);
636 g_assert (name_rva != INVALID_OFFSET);
637 ptr = ctx->data + name_rva;
639 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
640 char name[SIZE_OF_MSCOREE];
641 memcpy (name, ptr, SIZE_OF_MSCOREE);
642 name [SIZE_OF_MSCOREE - 1] = 0;
643 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
648 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
653 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
657 verify_resources_table (VerifyContext *ctx)
659 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
661 guint16 named_entries, id_entries;
662 const char *ptr, *root, *end;
668 ADD_ERROR (ctx, g_strdup_printf ("Resource section is too small, must be at least 16 bytes long but it's %d long", it.size));
670 offset = it.translated_offset;
671 root = ptr = ctx->data + offset;
672 end = root + it.size;
674 g_assert (offset != INVALID_OFFSET);
676 named_entries = read16 (ptr + 12);
677 id_entries = read16 (ptr + 14);
679 if ((named_entries + id_entries) * 8 + 16 > it.size)
680 ADD_ERROR (ctx, g_strdup_printf ("Resource section is too small, the number of entries (%d) doesn't fit on it's size %d", named_entries + id_entries, it.size));
682 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
683 if (named_entries || id_entries)
684 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
688 /*----------nothing from here on can use data_directory---*/
691 get_data_dir (VerifyContext *ctx, int idx)
693 MonoCLIImageInfo *iinfo = ctx->image->image_info;
694 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
698 res.rva = entry->rva;
699 res.size = entry->size;
700 res.translated_offset = translate_rva (ctx, res.rva);
705 verify_cli_header (VerifyContext *ctx)
707 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
713 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
716 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
718 offset = it.translated_offset;
719 ptr = ctx->data + offset;
721 g_assert (offset != INVALID_OFFSET);
723 if (read16 (ptr) != 72)
724 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
726 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
727 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
730 if (!read32 (ptr + 8) || !read32 (ptr + 12))
731 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
733 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
734 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
737 for (i = 0; i < 6; ++i) {
738 guint32 rva = read32 (ptr);
739 guint32 size = read32 (ptr + 4);
741 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
742 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
747 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
752 pad4 (guint32 offset)
754 if (offset & 0x3) //pad to the next 4 byte boundary
755 offset = (offset & ~0x3) + 4;
760 verify_metadata_header (VerifyContext *ctx)
763 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
764 guint32 offset, section_count;
767 offset = it.translated_offset;
768 ptr = ctx->data + offset;
769 g_assert (offset != INVALID_OFFSET);
771 //build a directory entry for the metadata root
773 it.rva = read32 (ptr);
775 it.size = read32 (ptr);
776 it.translated_offset = offset = translate_rva (ctx, it.rva);
778 ptr = ctx->data + offset;
779 g_assert (offset != INVALID_OFFSET);
782 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
784 if (read32 (ptr) != 0x424A5342)
785 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
787 offset = pad4 (offset + 16 + read32 (ptr + 12));
789 if (!bounds_check_datadir (&it, offset, 4))
790 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least %d bytes required for flags decoding)", it.size, offset + 4 - it.translated_offset));
792 ptr = ctx->data + offset; //move to streams header
794 section_count = read16 (ptr + 2);
795 if (section_count < 2)
796 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
801 for (i = 0; i < section_count; ++i) {
802 guint32 stream_off, stream_size;
803 int string_size, stream_idx;
805 if (!bounds_check_datadir (&it, offset, 8))
806 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small for initial decode of stream header %d, missing %d bytes", i, offset + 9 - it.translated_offset));
808 stream_off = it.translated_offset + read32 (ptr);
809 stream_size = read32 (ptr + 4);
811 if (!bounds_check_datadir (&it, stream_off, stream_size))
812 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
817 for (string_size = 0; string_size < 32; ++string_size) {
818 if (!bounds_check_datadir (&it, offset++, 1))
819 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
820 if (!ptr [string_size])
824 if (ptr [string_size])
825 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
827 if (!strncmp ("#Strings", ptr, 9))
828 stream_idx = STRINGS_STREAM;
829 else if (!strncmp ("#US", ptr, 4))
830 stream_idx = USER_STRINGS_STREAM;
831 else if (!strncmp ("#Blob", ptr, 6))
832 stream_idx = BLOB_STREAM;
833 else if (!strncmp ("#GUID", ptr, 6))
834 stream_idx = GUID_STREAM;
835 else if (!strncmp ("#~", ptr, 3))
836 stream_idx = TILDE_STREAM;
838 ADD_WARNING (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
839 offset = pad4 (offset);
840 ptr = ctx->data + offset;
844 if (ctx->metadata_streams [stream_idx].offset != 0)
845 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
847 ctx->metadata_streams [stream_idx].offset = stream_off;
848 ctx->metadata_streams [stream_idx].size = stream_size;
850 offset = pad4 (offset);
851 ptr = ctx->data + offset;
854 if (!ctx->metadata_streams [TILDE_STREAM].size)
855 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
856 if (!ctx->metadata_streams [GUID_STREAM].size)
857 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
861 verify_tables_schema (VerifyContext *ctx)
863 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
864 unsigned offset = tables_area.offset;
865 const char *ptr = ctx->data + offset;
866 guint64 valid_tables;
870 if (tables_area.size < 24)
871 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
873 if (ptr [4] != 2 && ptr [4] != 1)
874 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
876 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
878 if ((ptr [6] & ~0x7) != 0)
879 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata heap sizes 0x%02x, only bits 0, 1 and 2 can be set", ((unsigned char *) ptr) [6]));
881 valid_tables = read64 (ptr + 8);
883 for (i = 0; i < 64; ++i) {
884 if (!(valid_tables & ((guint64)1 << i)))
887 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
888 Unused: 0x1E 0x1F 0x2D-0x3F
889 We don't care about the MS extensions.*/
890 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
891 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i));
892 if (i == 0x1E || i == 0x1F || i >= 0x2D)
893 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
897 if (tables_area.size < 24 + count * 4)
898 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for decoding row counts (requires %d bytes)", tables_area.size, 24 + count * 4));
901 for (i = 0; i < 64; ++i) {
902 if (valid_tables & ((guint64)1 << i)) {
903 guint32 row_count = read32 (ptr);
904 if (row_count > (1 << 24) - 1)
905 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
911 /*----------nothing from here on can use data_directory or metadata_streams ---*/
914 get_col_offset (VerifyContext *ctx, int table, int column)
916 guint32 bitfield = ctx->image->tables [table].size_bitfield;
920 offset += mono_metadata_table_size (bitfield, column);
926 get_col_size (VerifyContext *ctx, int table, int column)
928 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
932 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
935 res.offset = header->data - ctx->data;
936 res.size = header->size;
942 is_valid_string_full_with_image (MonoImage *image, guint32 offset, gboolean allow_empty)
944 guint32 heap_offset = (char*)image->heap_strings.data - image->raw_data;
945 guint32 heap_size = image->heap_strings.size;
948 const char *data = image->raw_data + heap_offset;
950 if (offset >= heap_size)
952 if (CHECK_ADDP_OVERFLOW_UN (data, offset))
955 if (!mono_utf8_validate_and_len_with_bounds (data + offset, heap_size - offset, &length, NULL))
957 return allow_empty || length > 0;
962 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
964 return is_valid_string_full_with_image (ctx->image, offset, allow_empty);
968 is_valid_string (VerifyContext *ctx, guint32 offset)
970 return is_valid_string_full (ctx, offset, TRUE);
974 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
976 return is_valid_string_full (ctx, offset, FALSE);
980 is_valid_guid (VerifyContext *ctx, guint32 offset)
982 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
983 return guids.size >= 8 && guids.size - 8 >= offset;
987 get_coded_index_token (int token_kind, guint32 coded_token)
989 guint32 bits = coded_index_desc [token_kind];
990 return coded_token >> bits;
994 get_coded_index_table (int kind, guint32 coded_token)
996 guint32 idx, bits = coded_index_desc [kind];
998 idx = coded_token & ((1 << bits) - 1);
999 return coded_index_desc [kind + idx];
1003 make_coded_token (int kind, guint32 table, guint32 table_idx)
1005 guint32 bits = coded_index_desc [kind++];
1006 guint32 tables = coded_index_desc [kind++];
1008 for (i = 0; i < tables; ++i) {
1009 if (coded_index_desc [kind++] == table)
1010 return ((table_idx + 1) << bits) | i;
1012 g_assert_not_reached ();
1017 is_valid_coded_index_with_image (MonoImage *image, int token_kind, guint32 coded_token)
1019 guint32 bits = coded_index_desc [token_kind++];
1020 guint32 table_count = coded_index_desc [token_kind++];
1021 guint32 table = coded_token & ((1 << bits) - 1);
1022 guint32 token = coded_token >> bits;
1024 if (table >= table_count)
1027 /*token_kind points to the first table idx*/
1028 table = coded_index_desc [token_kind + table];
1030 if (table == INVALID_TABLE)
1032 return token <= image->tables [table].rows;
1036 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
1038 return is_valid_coded_index_with_image (ctx->image, token_kind, coded_token);
1045 MonoTableInfo *table;
1049 token_locator (const void *a, const void *b)
1051 RowLocator *loc = (RowLocator *)a;
1052 unsigned const char *row = (unsigned const char *)b;
1053 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1055 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1056 return (int)loc->token - (int)token;
1060 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1062 MonoTableInfo *tinfo = &ctx->image->tables [table];
1064 const char *res, *base;
1065 locator.token = coded_token;
1066 locator.col_offset = get_col_offset (ctx, table, column);
1067 locator.col_size = get_col_size (ctx, table, column);
1068 locator.table = tinfo;
1072 VERIFIER_DEBUG ( printf ("looking token %x table %d col %d rsize %d roff %d\n", coded_token, table, column, locator.col_size, locator.col_offset) );
1073 res = mono_binary_search (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1077 return (res - base) / tinfo->row_size;
1080 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1082 get_string_ptr (VerifyContext *ctx, guint offset)
1084 return ctx->image->heap_strings.data + offset;
1087 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1089 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1092 return strcmp (str, "");
1094 return strcmp (str, get_string_ptr (ctx, offset));
1098 mono_verifier_is_corlib (MonoImage *image)
1100 gboolean trusted_location = !mono_security_core_clr_enabled () ?
1101 TRUE : mono_security_core_clr_is_platform_image (image);
1103 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1107 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1109 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1113 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1116 const unsigned char *ptr = (const unsigned char *)_ptr;
1124 if ((b & 0x80) == 0) {
1127 } else if ((b & 0x40) == 0) {
1131 *value = ((b & 0x3f) << 8 | ptr [1]);
1136 *value = ((b & 0x1f) << 24) |
1146 decode_signature_header (VerifyContext *ctx, guint32 offset, guint32 *size, const char **first_byte)
1148 MonoStreamHeader blob = ctx->image->heap_blob;
1149 guint32 value, enc_size;
1151 if (offset >= blob.size)
1154 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1157 if (CHECK_ADD4_OVERFLOW_UN (offset, enc_size))
1162 if (ADD_IS_GREATER_OR_OVF (offset, value, blob.size))
1166 *first_byte = blob.data + offset;
1171 safe_read (const char **_ptr, const char *limit, unsigned *dest, int size)
1173 const char *ptr = *_ptr;
1174 if (ptr + size > limit)
1178 *dest = *((guint8*)ptr);
1182 *dest = read16 (ptr);
1186 *dest = read32 (ptr);
1195 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1198 const char *ptr = *_ptr;
1199 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1204 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1205 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1206 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1207 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1210 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1213 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1216 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1218 const char *ptr = *_ptr;
1223 if (!safe_read8 (type, ptr, end))
1224 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1226 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1231 if (!safe_read_cint (token, ptr, end))
1232 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1234 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1235 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1243 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1245 const char *ptr = *_ptr;
1247 unsigned size, num, i;
1249 if (!safe_read8 (val, ptr, end))
1250 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1253 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1255 if (!safe_read_cint (size, ptr, end))
1256 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1258 for (i = 0; i < size; ++i) {
1259 if (!safe_read_cint (num, ptr, end))
1260 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1263 if (!safe_read_cint (size, ptr, end))
1264 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1266 for (i = 0; i < size; ++i) {
1267 if (!safe_read_cint (num, ptr, end))
1268 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1276 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1278 const char *ptr = *_ptr;
1280 unsigned count, token, i;
1282 if (!safe_read8 (type, ptr, end))
1283 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1285 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1286 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1288 if (!safe_read_cint (token, ptr, end))
1289 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1291 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1292 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1295 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1296 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1297 FAIL (ctx, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx->token));
1300 if (!safe_read_cint (count, ptr, end))
1301 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1304 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1306 for (i = 0; i < count; ++i) {
1307 if (!parse_custom_mods (ctx, &ptr, end))
1308 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1310 if (!parse_type (ctx, &ptr, end))
1311 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1318 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1320 const char *ptr = *_ptr;
1324 if (!safe_read8 (type, ptr, end))
1325 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1327 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1328 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1329 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1330 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1331 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1335 if (!parse_custom_mods (ctx, &ptr, end))
1336 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1338 if (!safe_read8 (type, ptr, end))
1339 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1341 if (type != MONO_TYPE_VOID) {
1343 if (!parse_type (ctx, &ptr, end))
1344 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1348 case MONO_TYPE_VALUETYPE:
1349 case MONO_TYPE_CLASS:
1350 if (!safe_read_cint (token, ptr, end))
1351 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1353 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1354 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1356 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1357 FAIL (ctx, g_strdup_printf ("Type: zero TypeDefOrRef token %x", token));
1359 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1360 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1361 FAIL (ctx, g_strdup_printf ("Type: Recursive type specification (%x). A type signature can't reference itself", ctx->token));
1366 case MONO_TYPE_MVAR:
1367 if (!safe_read_cint (token, ptr, end))
1368 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1371 case MONO_TYPE_ARRAY:
1372 if (!parse_type (ctx, &ptr, end))
1373 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1374 if (!parse_array_shape (ctx, &ptr, end))
1375 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1378 case MONO_TYPE_GENERICINST:
1379 if (!parse_generic_inst (ctx, &ptr, end))
1380 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1383 case MONO_TYPE_FNPTR:
1384 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1385 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1388 case MONO_TYPE_SZARRAY:
1389 if (!parse_custom_mods (ctx, &ptr, end))
1390 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1391 if (!parse_type (ctx, &ptr, end))
1392 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1400 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1405 if (!parse_custom_mods (ctx, _ptr, end))
1409 if (!safe_read8 (type, ptr, end))
1410 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1412 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1417 //it's a byref, update the cursor ptr
1418 if (type == MONO_TYPE_BYREF)
1421 return parse_type (ctx, _ptr, end);
1425 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1430 if (!parse_custom_mods (ctx, _ptr, end))
1434 if (!safe_read8 (type, ptr, end))
1435 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1437 if (type == MONO_TYPE_TYPEDBYREF) {
1442 //it's a byref, update the cursor ptr
1443 if (type == MONO_TYPE_BYREF) {
1445 if (!parse_custom_mods (ctx, _ptr, end))
1449 return parse_type (ctx, _ptr, end);
1453 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1456 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1457 const char *ptr = *_ptr;
1458 gboolean saw_sentinel = FALSE;
1460 if (!safe_read8 (cconv, ptr, end))
1461 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1464 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1466 if (allow_unmanaged) {
1467 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1468 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1469 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1470 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1472 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1473 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1475 if ((cconv & 0x10) && gparam_count == 0)
1476 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1478 if (allow_unmanaged && (cconv & 0x10))
1479 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1481 if (!safe_read_cint (param_count, ptr, end))
1482 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1484 if (!parse_return_type (ctx, &ptr, end))
1485 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1487 for (i = 0; i < param_count; ++i) {
1488 if (allow_sentinel) {
1489 if (!safe_read8 (type, ptr, end))
1490 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1492 if (type == MONO_TYPE_SENTINEL) {
1493 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1494 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1497 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1499 saw_sentinel = TRUE;
1505 if (!parse_param (ctx, &ptr, end))
1506 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1514 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1517 unsigned param_count = 0, i;
1518 const char *ptr = *_ptr;
1520 if (!safe_read8 (sig, ptr, end))
1521 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1523 if (sig != 0x08 && sig != 0x28)
1524 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1526 if (!safe_read_cint (param_count, ptr, end))
1527 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1529 if (!parse_custom_mods (ctx, &ptr, end))
1532 if (!parse_type (ctx, &ptr, end))
1533 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1535 for (i = 0; i < param_count; ++i) {
1536 if (!parse_custom_mods (ctx, &ptr, end))
1537 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1538 if (!parse_type (ctx, &ptr, end))
1539 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1547 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1549 const char *ptr = *_ptr;
1550 unsigned signature = 0;
1552 if (!safe_read8 (signature, ptr, end))
1553 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1555 if (signature != 0x06)
1556 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1558 if (!parse_custom_mods (ctx, &ptr, end))
1561 if (safe_read8 (signature, ptr, end)) {
1562 if (signature != MONO_TYPE_BYREF)
1567 return parse_type (ctx, _ptr, end);
1571 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1574 unsigned locals_count = 0, i;
1575 const char *ptr = *_ptr;
1577 if (!safe_read8 (sig, ptr, end))
1578 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1581 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1583 if (!safe_read_cint (locals_count, ptr, end))
1584 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1586 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1587 if (locals_count == 0)
1588 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1591 for (i = 0; i < locals_count; ++i) {
1592 if (!safe_read8 (sig, ptr, end))
1593 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1595 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1596 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1597 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1598 if (!safe_read8 (sig, ptr, end))
1599 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1602 if (sig == MONO_TYPE_BYREF) {
1603 if (!safe_read8 (sig, ptr, end))
1604 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1605 if (sig == MONO_TYPE_TYPEDBYREF)
1606 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1609 if (sig == MONO_TYPE_TYPEDBYREF)
1614 if (!parse_type (ctx, &ptr, end))
1615 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1623 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1626 unsigned signature = 0;
1627 const char *ptr = NULL, *end;
1629 if (!decode_signature_header (ctx, offset, &size, &ptr))
1630 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1633 if (!safe_read8 (signature, ptr, end))
1634 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1637 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1640 return parse_field (ctx, &ptr, end);
1644 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1647 const char *ptr = NULL, *end;
1649 if (!decode_signature_header (ctx, offset, &size, &ptr))
1650 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1653 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1657 is_valid_memberref_method_signature (VerifyContext *ctx, guint32 offset)
1660 const char *ptr = NULL, *end;
1662 if (!decode_signature_header (ctx, offset, &size, &ptr))
1663 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1666 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1671 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1674 unsigned signature = 0;
1675 const char *ptr = NULL, *end;
1677 if (!decode_signature_header (ctx, offset, &size, &ptr))
1678 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1681 if (!safe_read8 (signature, ptr, end))
1682 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1685 if (signature == 0x06)
1686 return parse_field (ctx, &ptr, end);
1688 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1692 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1695 unsigned prolog = 0;
1696 const char *ptr = NULL, *end;
1701 if (!decode_signature_header (ctx, offset, &size, &ptr))
1702 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1705 if (!safe_read16 (prolog, ptr, end))
1706 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1709 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1715 is_valid_cattr_type (MonoType *type)
1719 if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1722 if (type->type == MONO_TYPE_VALUETYPE) {
1723 klass = mono_class_from_mono_type (type);
1724 return klass && klass->enumtype;
1727 if (type->type == MONO_TYPE_CLASS)
1728 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1734 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1737 const char *ptr = *_ptr;
1743 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1746 if (*ptr == (char)0xFF) {
1751 if (!safe_read_cint (size, ptr, end))
1752 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1754 if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1755 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1765 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1767 const char *dummy_str;
1769 return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1773 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1777 const char *str_start = NULL;
1778 const char *ptr = *_ptr;
1780 guint32 str_len = 0;
1782 if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1785 /*NULL or empty string*/
1786 if (str_start == NULL || str_len == 0) {
1787 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1791 enum_name = g_memdup (str_start, str_len + 1);
1792 enum_name [str_len] = 0;
1793 type = mono_reflection_type_from_name (enum_name, ctx->image);
1795 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1801 klass = mono_class_from_mono_type (type);
1802 if (!klass || !klass->enumtype) {
1803 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1812 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1815 const char *ptr = *_ptr;
1817 guint32 element_count, i;
1820 klass = mono_type->data.klass;
1821 type = mono_type->type;
1825 case MONO_TYPE_BOOLEAN:
1832 case MONO_TYPE_CHAR:
1846 case MONO_TYPE_STRING:
1848 return is_valid_ser_string (ctx, _ptr, end);
1850 case MONO_TYPE_OBJECT: {
1851 unsigned sub_type = 0;
1852 if (!safe_read8 (sub_type, ptr, end))
1853 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1855 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1859 if (sub_type == MONO_TYPE_ENUM) {
1860 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1864 klass = klass->element_class;
1865 type = klass->byval_arg.type;
1868 if (sub_type == 0x50) { /*Type*/
1870 return is_valid_ser_string (ctx, _ptr, end);
1872 if (sub_type == MONO_TYPE_SZARRAY) {
1873 MonoType simple_type = {{0}};
1875 if (!safe_read8 (etype, ptr, end))
1876 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1878 if (etype == MONO_TYPE_ENUM) {
1879 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1882 } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
1883 klass = mono_defaults.systemtype_class;
1884 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1885 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
1886 klass = mono_class_from_mono_type (&simple_type);
1888 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1890 type = MONO_TYPE_SZARRAY;
1893 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1897 case MONO_TYPE_CLASS:
1898 if (klass != mono_defaults.systemtype_class)
1899 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1901 return is_valid_ser_string (ctx, _ptr, end);
1903 case MONO_TYPE_VALUETYPE:
1904 if (!klass || !klass->enumtype)
1905 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1907 klass = klass->element_class;
1908 type = klass->byval_arg.type;
1911 case MONO_TYPE_SZARRAY:
1912 mono_type = &klass->byval_arg;
1913 if (!is_valid_cattr_type (mono_type))
1914 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1915 if (!safe_read32 (element_count, ptr, end))
1916 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1917 if (element_count == 0xFFFFFFFFu) {
1921 for (i = 0; i < element_count; ++i) {
1922 if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1928 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1931 if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1932 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1933 *_ptr = ptr + elem_size;
1938 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1941 unsigned prolog = 0;
1943 MonoMethodSignature *sig;
1948 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1950 sig = mono_method_signature_checked (ctor, &error);
1951 if (!mono_error_ok (&error)) {
1952 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1953 mono_error_cleanup (&error);
1957 if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1958 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1962 if (!safe_read16 (prolog, ptr, end))
1963 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1966 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1968 args = sig->param_count;
1969 for (i = 0; i < args; ++i) {
1970 MonoType *arg_type = sig->params [i];
1971 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1975 if (!safe_read16 (num_named, ptr, end))
1976 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1978 for (i = 0; i < num_named; ++i) {
1979 MonoType *type, simple_type = {{0}};
1982 if (!safe_read8 (kind, ptr, end))
1983 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1984 if (kind != 0x53 && kind != 0x54)
1985 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1986 if (!safe_read8 (kind, ptr, end))
1987 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1989 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1990 simple_type.type = kind;
1991 type = &simple_type;
1992 } else if (kind == MONO_TYPE_ENUM) {
1993 MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1996 type = &klass->byval_arg;
1997 } else if (kind == 0x50) {
1998 type = &mono_defaults.systemtype_class->byval_arg;
1999 } else if (kind == 0x51) {
2000 type = &mono_defaults.object_class->byval_arg;
2001 } else if (kind == MONO_TYPE_SZARRAY) {
2004 if (!safe_read8 (etype, ptr, end))
2005 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
2007 if (etype == MONO_TYPE_ENUM) {
2008 klass = get_enum_by_encoded_name (ctx, &ptr, end);
2011 } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
2012 klass = mono_defaults.systemtype_class;
2013 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
2014 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
2015 klass = mono_class_from_mono_type (&simple_type);
2017 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
2019 type = &mono_array_class_get (klass, 1)->byval_arg;
2021 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
2024 if (!is_valid_ser_string (ctx, &ptr, end))
2027 if (!is_valid_fixed_param (ctx, type, &ptr, end))
2036 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
2038 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2039 //TODO do proper verification
2040 return blob.size >= 1 && blob.size - 1 >= offset;
2044 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
2046 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2047 //TODO do proper verification
2048 return blob.size >= 1 && blob.size - 1 >= offset;
2052 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2055 unsigned signature = 0;
2056 const char *ptr = NULL, *end;
2058 if (!decode_signature_header (ctx, offset, &size, &ptr))
2059 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2062 if (!safe_read8 (signature, ptr, end))
2063 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2066 if (signature == 0x07)
2067 return parse_locals_signature (ctx, &ptr, end);
2069 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2070 if (signature == 0x06)
2071 return parse_field (ctx, &ptr, end);
2073 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2077 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2080 const char *ptr = NULL, *end;
2082 if (!decode_signature_header (ctx, offset, &size, &ptr))
2083 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2086 return parse_property_signature (ctx, &ptr, end);
2090 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2093 const char *ptr = NULL, *end;
2096 if (!decode_signature_header (ctx, offset, &size, &ptr))
2097 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2100 if (!parse_custom_mods (ctx, &ptr, end))
2103 if (!safe_read8 (type, ptr, end))
2104 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2106 if (type == MONO_TYPE_BYREF) {
2107 if (!safe_read8 (type, ptr, end))
2108 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2109 if (type == MONO_TYPE_TYPEDBYREF)
2110 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2113 if (type == MONO_TYPE_TYPEDBYREF)
2117 return parse_type (ctx, &ptr, end);
2121 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2124 const char *ptr = NULL, *end;
2126 unsigned count = 0, i;
2128 if (!decode_signature_header (ctx, offset, &size, &ptr))
2129 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2132 if (!safe_read8 (type, ptr, end))
2133 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2136 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2138 if (!safe_read_cint (count, ptr, end))
2139 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2142 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2144 for (i = 0; i < count; ++i) {
2145 if (!parse_custom_mods (ctx, &ptr, end))
2147 if (!parse_type (ctx, &ptr, end))
2148 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2154 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2156 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2157 guint32 entry_size, bytes;
2159 if (blob.size < offset)
2162 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2165 if (entry_size < minsize)
2168 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2170 entry_size += bytes;
2172 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2176 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2178 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2179 guint32 size, entry_size, bytes;
2181 if (blob.size < offset)
2182 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2184 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2185 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2187 if (type == MONO_TYPE_STRING) {
2188 //String is encoded as: compressed_int:len len *bytes
2191 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2192 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
2198 case MONO_TYPE_BOOLEAN:
2203 case MONO_TYPE_CHAR:
2211 case MONO_TYPE_CLASS:
2221 g_assert_not_reached ();
2224 if (size != entry_size)
2225 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2229 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2230 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2232 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2233 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2237 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2238 //only 0x01, 0x40 and 0x80 are allowed
2239 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2242 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2244 unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2245 unsigned header = 0;
2246 unsigned fat_header = 0, size = 0, max_stack;
2247 const char *ptr = NULL, *end;
2251 if (offset == INVALID_ADDRESS)
2252 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2254 ptr = ctx->data + offset;
2255 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2257 if (!safe_read8 (header, ptr, end))
2258 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2260 switch (header & 0x3) {
2263 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2266 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
2267 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2272 if (!safe_read16 (fat_header, ptr, end))
2273 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2275 size = (fat_header >> 12) & 0xF;
2277 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2279 if (!safe_read16 (max_stack, ptr, end))
2280 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2282 if (!safe_read32 (code_size, ptr, end))
2283 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2285 if (!safe_read32 (local_vars_tok, ptr, end))
2286 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2288 if (local_vars_tok) {
2289 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2290 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2291 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
2292 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2293 if (!(local_vars_tok & 0xFFFFFF))
2294 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature with zero index"));
2295 *locals_token = local_vars_tok & 0xFFFFFF;
2298 if (fat_header & FAT_HEADER_INVALID_FLAGS)
2299 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2301 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2302 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2304 if (!(fat_header & 0x08))
2310 unsigned section_header = 0, section_size = 0;
2313 ptr = dword_align (ptr);
2314 if (!safe_read32 (section_header, ptr, end))
2315 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2317 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2318 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2320 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2321 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2323 if (section_size < 4)
2324 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2326 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2327 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2329 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2330 guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2332 LAMEIMPL: MS emits section_size without accounting for header size.
2333 Mono does as the spec says. section_size is header + section
2334 MS's peverify happily accepts both.
2336 if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2337 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the expected size %d", section_size, clauses * (is_fat ? 24 : 12)));
2339 /* only verify the class token is verified as the rest is done by the IL verifier*/
2340 for (i = 0; i < clauses; ++i) {
2341 unsigned flags = *(unsigned char*)ptr;
2342 unsigned class_token = 0;
2343 ptr += (is_fat ? 20 : 8);
2344 if (!safe_read32 (class_token, ptr, end))
2345 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2346 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2347 guint table = mono_metadata_token_table (class_token);
2348 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2349 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2350 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2351 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2356 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2363 verify_module_table (VerifyContext *ctx)
2365 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2366 guint32 data [MONO_MODULE_SIZE];
2368 if (table->rows != 1)
2369 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2371 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2373 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2374 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2376 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2377 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2379 if (data [MONO_MODULE_ENC] != 0)
2380 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2382 if (data [MONO_MODULE_ENCBASE] != 0)
2383 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2387 verify_typeref_table (VerifyContext *ctx)
2389 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2393 for (i = 0; i < table->rows; ++i) {
2394 mono_verifier_verify_typeref_row (ctx->image, i, &error);
2395 add_from_mono_error (ctx, &error);
2399 /*bits 9,11,14,15,19,21,24-31 */
2400 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2402 verify_typedef_table (VerifyContext *ctx)
2404 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2405 guint32 data [MONO_TYPEDEF_SIZE];
2406 guint32 fieldlist = 1, methodlist = 1, visibility;
2409 if (table->rows == 0)
2410 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2412 for (i = 0; i < table->rows; ++i) {
2413 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2414 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2415 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2417 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2418 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2420 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2421 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2423 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2424 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2426 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2427 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2429 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2430 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2432 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2433 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2435 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2436 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2438 if (data [MONO_TYPEDEF_EXTENDS] && !get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2439 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d zero coded extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2441 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2442 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2443 search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2444 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2446 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2447 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2449 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2450 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2452 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2453 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_TYPEDEF_FIELD_LIST], fieldlist));
2455 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2456 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2458 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2459 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2461 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2462 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_TYPEDEF_METHOD_LIST], methodlist));
2464 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2465 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2470 verify_typedef_table_full (VerifyContext *ctx)
2472 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2473 guint32 data [MONO_TYPEDEF_SIZE];
2476 if (table->rows == 0)
2477 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2479 for (i = 0; i < table->rows; ++i) {
2480 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2483 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2484 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2485 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2490 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2491 if (data [MONO_TYPEDEF_EXTENDS])
2492 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2494 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2495 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2499 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2502 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2510 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2512 verify_field_table (VerifyContext *ctx)
2514 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2515 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2518 module_field_list = (guint32)-1;
2519 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2520 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2521 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2524 for (i = 0; i < table->rows; ++i) {
2525 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2526 flags = data [MONO_FIELD_FLAGS];
2528 if (flags & INVALID_FIELD_FLAG_BITS)
2529 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2531 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2532 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2534 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2535 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2537 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2538 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2540 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2541 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2543 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2544 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2545 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2547 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2548 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2549 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2551 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2552 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2553 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2555 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2556 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2557 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2559 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2560 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2562 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2563 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2565 //TODO verify contant flag
2567 if (i + 1 < module_field_list) {
2568 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2569 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2570 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2571 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2572 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2578 verify_field_table_full (VerifyContext *ctx)
2580 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2581 guint32 data [MONO_FIELD_SIZE];
2584 for (i = 0; i < table->rows; ++i) {
2585 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2587 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2588 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2592 /*bits 8,9,10,11,13,14,15*/
2593 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2595 verify_method_table (VerifyContext *ctx)
2597 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2598 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2599 guint32 paramlist = 1;
2600 gboolean is_ctor, is_cctor;
2604 module_method_list = (guint32)-1;
2605 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2606 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2607 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2610 for (i = 0; i < table->rows; ++i) {
2611 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2612 rva = data [MONO_METHOD_RVA];
2613 implflags = data [MONO_METHOD_IMPLFLAGS];
2614 flags = data [MONO_METHOD_FLAGS];
2615 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2616 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2619 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2620 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2623 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2625 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2626 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2628 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2629 is_ctor = !strcmp (".ctor", name);
2630 is_cctor = !strcmp (".cctor", name);
2632 if ((is_ctor || is_cctor) &&
2633 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2634 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2636 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2637 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2639 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2640 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2641 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2642 if (flags & METHOD_ATTRIBUTE_FINAL)
2643 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2644 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2645 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2648 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2649 ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2651 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2652 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2654 //XXX no checks against cas stuff 10,11,12,13)
2656 //TODO check iface with .ctor (15,16)
2658 if (i + 1 < module_method_list) {
2659 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2660 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2661 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2662 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2663 if (access == METHOD_ATTRIBUTE_FAMILY || access == METHOD_ATTRIBUTE_FAM_AND_ASSEM || access == METHOD_ATTRIBUTE_FAM_OR_ASSEM)
2664 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public, Private or Assembly", i));
2667 //TODO check valuetype for synchronized
2669 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2670 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2672 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2673 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2674 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2675 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2676 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2679 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2680 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2681 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2683 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2684 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2686 //TODO check signature contents
2689 if ((flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) || (implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2690 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is either Abstract, InternalCall or PinvokeImpl", i));
2691 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2692 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2694 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2695 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2698 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2700 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2701 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2702 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2704 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2705 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2707 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2708 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2710 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2711 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2713 if (data [MONO_METHOD_PARAMLIST] == 0)
2714 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2716 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2717 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_METHOD_PARAMLIST], paramlist));
2719 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2720 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2722 paramlist = data [MONO_METHOD_PARAMLIST];
2728 verify_method_table_full (VerifyContext *ctx)
2730 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2731 guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2734 for (i = 0; i < table->rows; ++i) {
2735 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2736 rva = data [MONO_METHOD_RVA];
2738 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2739 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2741 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2742 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2747 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2749 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2750 guint32 row = *current_method;
2751 guint32 paramlist, tmp;
2754 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2755 while (row < table->rows) {
2756 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2757 if (tmp > paramlist) {
2758 *current_method = row;
2759 return tmp - paramlist;
2764 /*no more methods, all params apply to the last one*/
2765 *current_method = table->rows;
2770 #define INVALID_PARAM_FLAGS_BITS ((1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15))
2772 verify_param_table (VerifyContext *ctx)
2774 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2775 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2776 gboolean first_param = TRUE;
2779 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2780 if (table->rows > 0)
2781 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2785 remaining_params = get_next_param_count (ctx, ¤t_method);
2787 for (i = 0; i < table->rows; ++i) {
2788 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2789 flags = data [MONO_PARAM_FLAGS];
2791 if (flags & INVALID_PARAM_FLAGS_BITS)
2792 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2794 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2795 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2796 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2798 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2799 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2802 if ((flags & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL) && search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_PARAM, i)) == -1)
2803 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2805 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2806 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2808 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2809 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2811 first_param = FALSE;
2812 sequence = data [MONO_PARAM_SEQUENCE];
2813 if (--remaining_params == 0) {
2814 remaining_params = get_next_param_count (ctx, ¤t_method);
2821 verify_interfaceimpl_table (VerifyContext *ctx)
2823 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2824 guint32 data [MONO_INTERFACEIMPL_SIZE];
2827 for (i = 0; i < table->rows; ++i) {
2828 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2829 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2830 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_INTERFACEIMPL_CLASS]));
2832 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2833 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2835 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2836 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2841 verify_memberref_table (VerifyContext *ctx)
2843 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2844 guint32 data [MONO_MEMBERREF_SIZE];
2847 for (i = 0; i < table->rows; ++i) {
2848 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2850 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2851 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2853 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2854 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2856 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2857 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2859 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2860 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2866 verify_memberref_table_full (VerifyContext *ctx)
2868 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2869 guint32 data [MONO_MEMBERREF_SIZE];
2872 for (i = 0; i < table->rows; ++i) {
2873 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2875 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2876 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2881 verify_constant_table (VerifyContext *ctx)
2883 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2884 guint32 data [MONO_CONSTANT_SIZE], type;
2887 for (i = 0; i < table->rows; ++i) {
2888 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2889 type = data [MONO_CONSTANT_TYPE];
2891 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2892 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2894 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2895 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2897 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2898 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2900 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2901 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2906 verify_cattr_table (VerifyContext *ctx)
2908 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2909 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2912 for (i = 0; i < table->rows; ++i) {
2913 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2915 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2916 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2918 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]) || !get_coded_index_token (CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2919 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Type field 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2921 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2922 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2927 verify_cattr_table_full (VerifyContext *ctx)
2929 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2932 guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2935 for (i = 0; i < table->rows; ++i) {
2936 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2938 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2939 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2941 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2942 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2943 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2944 mtoken |= MONO_TOKEN_METHOD_DEF;
2946 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2947 mtoken |= MONO_TOKEN_MEMBER_REF;
2950 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2953 ctor = mono_get_method (ctx->image, mtoken, NULL);
2955 /*This can't fail since this is checked in is_valid_cattr_blob*/
2956 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2958 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2959 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2964 verify_field_marshal_table (VerifyContext *ctx)
2966 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2967 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2970 for (i = 0; i < table->rows; ++i) {
2971 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2973 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2974 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2976 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2977 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2979 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2980 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2982 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2983 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2988 verify_field_marshal_table_full (VerifyContext *ctx)
2990 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2991 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2994 for (i = 0; i < table->rows; ++i) {
2995 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2997 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2998 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
3003 verify_decl_security_table (VerifyContext *ctx)
3005 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3006 guint32 data [MONO_DECL_SECURITY_SIZE];
3009 for (i = 0; i < table->rows; ++i) {
3010 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3012 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3013 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
3015 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3016 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
3018 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
3019 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
3024 verify_decl_security_table_full (VerifyContext *ctx)
3026 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3027 guint32 data [MONO_DECL_SECURITY_SIZE];
3030 for (i = 0; i < table->rows; ++i) {
3031 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3033 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
3034 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
3039 verify_class_layout_table (VerifyContext *ctx)
3041 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
3042 guint32 data [MONO_CLASS_LAYOUT_SIZE];
3045 for (i = 0; i < table->rows; ++i) {
3046 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
3048 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3049 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
3051 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3063 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3069 verify_field_layout_table (VerifyContext *ctx)
3071 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3072 guint32 data [MONO_FIELD_LAYOUT_SIZE];
3075 for (i = 0; i < table->rows; ++i) {
3076 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3078 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3079 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3084 verify_standalonesig_table (VerifyContext *ctx)
3086 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3087 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3090 for (i = 0; i < table->rows; ++i) {
3091 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3093 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3094 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3099 verify_standalonesig_table_full (VerifyContext *ctx)
3101 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3102 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3105 for (i = 0; i < table->rows; ++i) {
3106 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3108 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3109 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3114 verify_eventmap_table (VerifyContext *ctx)
3116 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3117 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3120 for (i = 0; i < table->rows; ++i) {
3121 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3123 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3124 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3126 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3127 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3129 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3133 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3135 verify_event_table (VerifyContext *ctx)
3137 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3138 guint32 data [MONO_EVENT_SIZE];
3141 for (i = 0; i < table->rows; ++i) {
3142 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3144 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3145 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3147 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3148 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3150 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3151 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3156 verify_event_table_full (VerifyContext *ctx)
3158 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3159 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3160 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3161 gboolean found_add, found_remove;
3164 for (i = 0; i < table->rows; ++i) {
3165 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3167 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3168 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3170 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3172 //first we move to the first row for this event
3174 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3178 //now move forward looking for AddOn and RemoveOn rows
3179 found_add = found_remove = FALSE;
3180 while (idx < sema_table->rows) {
3181 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3182 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3184 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3186 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3187 found_remove = TRUE;
3188 if (found_add && found_remove)
3194 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3196 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no RemoveOn associated method", i));
3201 verify_propertymap_table (VerifyContext *ctx)
3203 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3204 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3207 for (i = 0; i < table->rows; ++i) {
3208 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3210 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3211 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3213 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3214 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3216 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3220 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3222 verify_property_table (VerifyContext *ctx)
3224 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3225 guint32 data [MONO_PROPERTY_SIZE];
3228 for (i = 0; i < table->rows; ++i) {
3229 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3231 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3232 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3234 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3235 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3237 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3238 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3240 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3241 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3242 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3248 verify_methodimpl_table (VerifyContext *ctx)
3250 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3251 guint32 data [MONO_METHODIMPL_SIZE];
3254 for (i = 0; i < table->rows; ++i) {
3255 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3257 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3258 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3260 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3261 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3263 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3264 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3266 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3267 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3269 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3270 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3275 verify_moduleref_table (VerifyContext *ctx)
3277 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3278 guint32 data [MONO_MODULEREF_SIZE];
3281 for (i = 0; i < table->rows; ++i) {
3282 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3284 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3285 ADD_ERROR (ctx, g_strdup_printf ("Invalid ModuleRef row %d name field %08x", i, data [MONO_MODULEREF_NAME]));
3290 verify_typespec_table (VerifyContext *ctx)
3292 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3293 guint32 data [MONO_TYPESPEC_SIZE];
3296 for (i = 0; i < table->rows; ++i) {
3297 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3299 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3300 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3305 verify_typespec_table_full (VerifyContext *ctx)
3307 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3308 guint32 data [MONO_TYPESPEC_SIZE];
3311 for (i = 0; i < table->rows; ++i) {
3312 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3313 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3314 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3315 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3320 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13))
3322 verify_implmap_table (VerifyContext *ctx)
3324 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3325 guint32 data [MONO_IMPLMAP_SIZE], cconv;
3328 for (i = 0; i < table->rows; ++i) {
3329 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3331 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3332 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3334 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3335 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3336 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3338 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3339 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3341 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3342 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3344 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3345 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3347 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3348 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3350 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows)
3351 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3356 verify_fieldrva_table (VerifyContext *ctx)
3358 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3359 guint32 data [MONO_FIELD_RVA_SIZE];
3362 for (i = 0; i < table->rows; ++i) {
3363 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3365 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3366 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3368 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3369 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3373 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 14) | (1 << 15))
3375 verify_assembly_table (VerifyContext *ctx)
3377 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3378 guint32 data [MONO_ASSEMBLY_SIZE], hash;
3381 if (table->rows > 1)
3382 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3384 for (i = 0; i < table->rows; ++i) {
3385 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3387 hash = data [MONO_ASSEMBLY_HASH_ALG];
3388 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3389 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3391 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3392 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3394 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3395 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3397 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3398 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3400 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3401 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3405 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
3407 verify_assemblyref_table (VerifyContext *ctx)
3409 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3410 guint32 data [MONO_ASSEMBLYREF_SIZE];
3413 for (i = 0; i < table->rows; ++i) {
3414 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3416 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3417 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3419 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3420 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3422 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3423 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3425 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3426 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3428 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3429 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3433 #define INVALID_FILE_FLAGS_BITS ~(1)
3435 verify_file_table (VerifyContext *ctx)
3437 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3438 guint32 data [MONO_FILE_SIZE];
3441 for (i = 0; i < table->rows; ++i) {
3442 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3444 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3445 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3447 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3448 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3450 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3451 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3455 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3457 verify_exportedtype_table (VerifyContext *ctx)
3459 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3460 guint32 data [MONO_EXP_TYPE_SIZE];
3463 for (i = 0; i < table->rows; ++i) {
3464 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3466 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3467 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3469 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3470 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3472 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3473 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3475 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3476 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3478 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3479 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3481 /*nested type can't have a namespace*/
3482 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3483 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3487 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3489 verify_manifest_resource_table (VerifyContext *ctx)
3491 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3492 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3493 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3494 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3497 resources_size = ch->ch_resources.size;
3499 for (i = 0; i < table->rows; ++i) {
3500 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3502 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3503 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3505 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3506 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3508 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3509 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3511 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3512 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3514 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3515 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3517 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3518 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])));
3520 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3521 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3523 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3524 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3529 verify_nested_class_table (VerifyContext *ctx)
3531 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3532 guint32 data [MONO_NESTED_CLASS_SIZE];
3535 for (i = 0; i < table->rows; ++i) {
3536 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3538 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3539 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3540 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3541 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3542 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3543 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3547 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3549 verify_generic_param_table (VerifyContext *ctx)
3551 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3552 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3553 int i, param_number = 0;
3555 for (i = 0; i < table->rows; ++i) {
3556 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3558 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3559 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3561 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3562 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3564 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3565 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3567 token = data [MONO_GENERICPARAM_OWNER];
3569 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3570 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3572 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3573 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3575 if (token != last_token) {
3580 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3581 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d Number is out of order %d expected %d", i, data [MONO_GENERICPARAM_NUMBER], param_number));
3588 verify_method_spec_table (VerifyContext *ctx)
3590 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3591 guint32 data [MONO_METHODSPEC_SIZE];
3594 for (i = 0; i < table->rows; ++i) {
3595 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3597 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3598 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3600 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3601 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3603 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3604 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3609 verify_method_spec_table_full (VerifyContext *ctx)
3611 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3612 guint32 data [MONO_METHODSPEC_SIZE];
3615 for (i = 0; i < table->rows; ++i) {
3616 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3618 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3619 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3624 verify_generic_param_constraint_table (VerifyContext *ctx)
3626 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3627 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3629 guint32 last_owner = 0, last_constraint = 0;
3631 for (i = 0; i < table->rows; ++i) {
3632 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3634 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3635 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3637 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3638 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3640 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3641 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3643 if (last_owner > data [MONO_GENPARCONSTRAINT_GENERICPAR])
3644 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d is not properly sorted. Previous value of the owner column is 0x%08x current value is 0x%08x", i, last_owner, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3646 if (last_owner == data [MONO_GENPARCONSTRAINT_GENERICPAR]) {
3647 if (last_constraint == data [MONO_GENPARCONSTRAINT_CONSTRAINT])
3648 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has duplicate constraint 0x%08x", i, last_constraint));
3650 last_owner = data [MONO_GENPARCONSTRAINT_GENERICPAR];
3652 last_constraint = data [MONO_GENPARCONSTRAINT_CONSTRAINT];
3659 const char *name_space;
3660 guint32 resolution_scope;
3664 typedef_hash (gconstpointer _key)
3666 const TypeDefUniqueId *key = _key;
3667 return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3671 typedef_equals (gconstpointer _a, gconstpointer _b)
3673 const TypeDefUniqueId *a = _a;
3674 const TypeDefUniqueId *b = _b;
3675 return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3679 verify_typedef_table_global_constraints (VerifyContext *ctx)
3682 guint32 data [MONO_TYPEDEF_SIZE];
3683 guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3684 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3685 MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3686 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3688 for (i = 0; i < table->rows; ++i) {
3690 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3691 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3693 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3694 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3695 type->resolution_scope = 0;
3697 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3698 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3699 int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3700 g_assert (res >= 0);
3702 mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3703 type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3706 if (g_hash_table_lookup (unique_types, type)) {
3707 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("TypeDef table row %d has duplicate for tuple (%s,%s,%x)", i, type->name, type->name_space, type->resolution_scope));
3708 g_hash_table_destroy (unique_types);
3712 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3715 g_hash_table_destroy (unique_types);
3719 verify_typeref_table_global_constraints (VerifyContext *ctx)
3722 guint32 data [MONO_TYPEREF_SIZE];
3723 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3724 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3726 for (i = 0; i < table->rows; ++i) {
3727 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3728 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3730 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3731 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3732 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3734 if (g_hash_table_lookup (unique_types, type)) {
3735 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("TypeRef table row %d has duplicate for tuple (%s,%s,%x)", i, type->name, type->name_space, type->resolution_scope));
3736 g_hash_table_destroy (unique_types);
3740 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3743 g_hash_table_destroy (unique_types);
3747 verify_tables_data_global_constraints (VerifyContext *ctx)
3749 verify_typedef_table_global_constraints (ctx);
3753 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3755 verify_typeref_table (ctx);
3756 verify_typeref_table_global_constraints (ctx);
3760 verify_tables_data (VerifyContext *ctx)
3762 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3763 guint32 size = 0, tables_offset;
3766 for (i = 0; i < 0x2D; ++i) {
3767 MonoTableInfo *table = &ctx->image->tables [i];
3769 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3770 if (tmp_size < size) {
3778 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3780 tables_offset = ctx->image->tables_base - ctx->data;
3781 if (!bounds_check_offset (&tables_area, tables_offset, size))
3782 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)));
3784 verify_module_table (ctx);
3786 /*Obfuscators love to place broken stuff in the typeref table
3787 verify_typeref_table (ctx);
3789 verify_typedef_table (ctx);
3791 verify_field_table (ctx);
3793 verify_method_table (ctx);
3795 verify_param_table (ctx);
3797 verify_interfaceimpl_table (ctx);
3799 verify_memberref_table (ctx);
3801 verify_constant_table (ctx);
3803 verify_cattr_table (ctx);
3805 verify_field_marshal_table (ctx);
3807 verify_decl_security_table (ctx);
3809 verify_class_layout_table (ctx);
3811 verify_field_layout_table (ctx);
3813 verify_standalonesig_table (ctx);
3815 verify_eventmap_table (ctx);
3817 verify_event_table (ctx);
3819 verify_propertymap_table (ctx);
3821 verify_property_table (ctx);
3823 verify_methodimpl_table (ctx);
3825 verify_moduleref_table (ctx);
3827 verify_typespec_table (ctx);
3829 verify_implmap_table (ctx);
3831 verify_fieldrva_table (ctx);
3833 verify_assembly_table (ctx);
3835 verify_assemblyref_table (ctx);
3837 verify_file_table (ctx);
3839 verify_exportedtype_table (ctx);
3841 verify_manifest_resource_table (ctx);
3843 verify_nested_class_table (ctx);
3845 verify_generic_param_table (ctx);
3847 verify_method_spec_table (ctx);
3849 verify_generic_param_constraint_table (ctx);
3851 verify_tables_data_global_constraints (ctx);
3855 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3857 memset (ctx, 0, sizeof (VerifyContext));
3859 ctx->report_error = report_error;
3860 ctx->report_warning = FALSE; //export this setting in the API
3862 ctx->size = image->raw_data_len;
3863 ctx->data = image->raw_data;
3867 cleanup_context (VerifyContext *ctx, GSList **error_list)
3869 g_free (ctx->sections);
3871 *error_list = ctx->errors;
3873 mono_free_verify_list (ctx->errors);
3878 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3880 g_free (ctx->sections);
3882 MonoVerifyInfo *info = ctx->errors->data;
3883 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3884 mono_free_verify_list (ctx->errors);
3890 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3894 if (!mono_verifier_is_enabled_for_image (image))
3897 init_verify_context (&ctx, image, error_list != NULL);
3898 ctx.stage = STAGE_PE;
3900 verify_msdos_header (&ctx);
3902 verify_pe_header (&ctx);
3904 verify_pe_optional_header (&ctx);
3906 load_section_table (&ctx);
3908 load_data_directories (&ctx);
3910 verify_import_table (&ctx);
3912 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3913 verify_resources_table (&ctx);
3916 return cleanup_context (&ctx, error_list);
3920 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3924 if (!mono_verifier_is_enabled_for_image (image))
3927 init_verify_context (&ctx, image, error_list != NULL);
3928 ctx.stage = STAGE_CLI;
3930 verify_cli_header (&ctx);
3932 verify_metadata_header (&ctx);
3934 verify_tables_schema (&ctx);
3937 return cleanup_context (&ctx, error_list);
3942 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3943 * Other verification checks are meant to be done lazily by the runtime. Those include:
3944 * blob items (signatures, method headers, custom attributes, etc)
3945 * type semantics related
3947 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3949 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3950 * operation still need more checking.
3953 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3957 if (!mono_verifier_is_enabled_for_image (image))
3960 init_verify_context (&ctx, image, error_list != NULL);
3961 ctx.stage = STAGE_TABLES;
3963 verify_tables_data (&ctx);
3965 return cleanup_context (&ctx, error_list);
3970 * Verifies all other constraints.
3973 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3977 if (!mono_verifier_is_enabled_for_image (image))
3980 init_verify_context (&ctx, image, error_list != NULL);
3981 ctx.stage = STAGE_TABLES;
3983 verify_typedef_table_full (&ctx);
3985 verify_field_table_full (&ctx);
3987 verify_method_table_full (&ctx);
3989 verify_memberref_table_full (&ctx);
3991 verify_cattr_table_full (&ctx);
3993 verify_field_marshal_table_full (&ctx);
3995 verify_decl_security_table_full (&ctx);
3997 verify_standalonesig_table_full (&ctx);
3999 verify_event_table_full (&ctx);
4001 verify_typespec_table_full (&ctx);
4003 verify_method_spec_table_full (&ctx);
4005 verify_tables_data_global_constraints_full (&ctx);
4008 return cleanup_context (&ctx, error_list);
4012 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4016 if (!mono_verifier_is_enabled_for_image (image))
4019 init_verify_context (&ctx, image, error_list != NULL);
4020 ctx.stage = STAGE_TABLES;
4022 is_valid_field_signature (&ctx, offset);
4023 return cleanup_context (&ctx, error_list);
4027 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4030 guint32 locals_token;
4032 if (!mono_verifier_is_enabled_for_image (image))
4035 init_verify_context (&ctx, image, error_list != NULL);
4036 ctx.stage = STAGE_TABLES;
4038 is_valid_method_header (&ctx, offset, &locals_token);
4040 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
4041 is_valid_standalonesig_blob (&ctx, sig_offset);
4044 return cleanup_context (&ctx, error_list);
4048 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4052 mono_error_init (error);
4054 if (!mono_verifier_is_enabled_for_image (image))
4057 init_verify_context (&ctx, image, TRUE);
4058 ctx.stage = STAGE_TABLES;
4060 is_valid_method_signature (&ctx, offset);
4061 /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4062 return cleanup_context_checked (&ctx, error);
4066 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4070 if (!mono_verifier_is_enabled_for_image (image))
4073 init_verify_context (&ctx, image, error_list != NULL);
4074 ctx.stage = STAGE_TABLES;
4076 is_valid_memberref_method_signature (&ctx, offset);
4077 return cleanup_context (&ctx, error_list);
4081 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4085 if (!mono_verifier_is_enabled_for_image (image))
4088 init_verify_context (&ctx, image, error_list != NULL);
4089 ctx.stage = STAGE_TABLES;
4091 is_valid_field_signature (&ctx, offset);
4092 return cleanup_context (&ctx, error_list);
4096 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4100 if (!mono_verifier_is_enabled_for_image (image))
4103 init_verify_context (&ctx, image, error_list != NULL);
4104 ctx.stage = STAGE_TABLES;
4106 is_valid_standalonesig_blob (&ctx, offset);
4107 return cleanup_context (&ctx, error_list);
4111 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4115 if (!mono_verifier_is_enabled_for_image (image))
4118 init_verify_context (&ctx, image, error_list != NULL);
4119 ctx.stage = STAGE_TABLES;
4122 is_valid_typespec_blob (&ctx, offset);
4123 return cleanup_context (&ctx, error_list);
4127 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4131 if (!mono_verifier_is_enabled_for_image (image))
4134 init_verify_context (&ctx, image, error_list != NULL);
4135 ctx.stage = STAGE_TABLES;
4137 is_valid_methodspec_blob (&ctx, offset);
4138 return cleanup_context (&ctx, error_list);
4142 verify_user_string (VerifyContext *ctx, guint32 offset)
4144 OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4145 guint32 entry_size, bytes;
4147 if (heap_us.size < offset)
4148 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4150 if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4151 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4153 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4154 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4156 entry_size += bytes;
4158 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4159 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4163 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4167 if (!mono_verifier_is_enabled_for_image (image))
4170 init_verify_context (&ctx, image, error_list != NULL);
4171 ctx.stage = STAGE_TABLES;
4173 verify_user_string (&ctx, offset);
4175 return cleanup_context (&ctx, error_list);
4179 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4183 if (!mono_verifier_is_enabled_for_image (image))
4186 init_verify_context (&ctx, image, error_list != NULL);
4187 ctx.stage = STAGE_TABLES;
4189 is_valid_cattr_blob (&ctx, offset);
4191 return cleanup_context (&ctx, error_list);
4195 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4199 if (!mono_verifier_is_enabled_for_image (image))
4202 init_verify_context (&ctx, image, error_list != NULL);
4203 ctx.stage = STAGE_TABLES;
4205 is_valid_cattr_content (&ctx, ctor, (const char*)data, size);
4207 return cleanup_context (&ctx, error_list);
4211 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4213 MonoMethodSignature *original_sig;
4214 if (!mono_verifier_is_enabled_for_image (image))
4217 original_sig = mono_method_signature (method);
4218 if (original_sig->call_convention == MONO_CALL_VARARG) {
4219 if (original_sig->hasthis != signature->hasthis)
4221 if (original_sig->call_convention != signature->call_convention)
4223 if (original_sig->explicit_this != signature->explicit_this)
4225 if (original_sig->call_convention != signature->call_convention)
4227 if (original_sig->pinvoke != signature->pinvoke)
4229 if (original_sig->sentinelpos != signature->sentinelpos)
4231 } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4239 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4241 MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
4242 guint32 data [MONO_TYPEREF_SIZE];
4244 mono_error_init (error);
4246 if (!mono_verifier_is_enabled_for_image (image))
4249 if (row >= table->rows) {
4250 mono_error_set_bad_image (error, image, "Invalid typeref row %d - table has %d rows", row, table->rows);
4254 mono_metadata_decode_row (table, row, data, MONO_TYPEREF_SIZE);
4255 if (!is_valid_coded_index_with_image (image, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4256 mono_error_set_bad_image (error, image, "Invalid typeref row %d coded index 0x%08x", row, data [MONO_TYPEREF_SCOPE]);
4260 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4261 mono_error_set_bad_image (error, image, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row);
4265 if (!data [MONO_TYPEREF_NAME] || !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAME], FALSE)) {
4266 mono_error_set_bad_image (error, image, "Invalid typeref row %d name token 0x%08x", row, data [MONO_TYPEREF_NAME]);
4270 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAMESPACE], FALSE)) {
4271 mono_error_set_bad_image (error, image, "Invalid typeref row %d namespace token 0x%08x", row, data [MONO_TYPEREF_NAMESPACE]);
4278 /*Perform additional verification including metadata ones*/
4280 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4282 MonoMethod *declaration, *body;
4283 MonoMethodSignature *body_sig, *decl_sig;
4284 MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
4285 guint32 data [MONO_METHODIMPL_SIZE];
4287 mono_error_init (error);
4289 if (!mono_verifier_is_enabled_for_image (image))
4292 if (row >= table->rows) {
4293 mono_error_set_bad_image (error, image, "Invalid methodimpl row %d - table has %d rows", row, table->rows);
4297 mono_metadata_decode_row (table, row, data, MONO_METHODIMPL_SIZE);
4299 body = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_BODY], NULL, error);
4303 declaration = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_DECLARATION], NULL, error);
4308 mono_class_setup_supertypes (class);
4309 if (!mono_class_has_parent (class, body->klass)) {
4310 mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
4314 if (!(body_sig = mono_method_signature_checked (body, error))) {
4318 if (!(decl_sig = mono_method_signature_checked (declaration, error))) {
4322 if (!mono_verifier_is_signature_compatible (decl_sig, body_sig)) {
4323 mono_error_set_bad_image (error, image, "Invalid methodimpl body signature not compatible with declaration row %x", row);
4332 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4338 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4344 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4350 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4356 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4362 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4368 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4370 mono_error_init (error);
4375 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4381 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4387 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4393 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4399 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4405 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4411 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4418 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4420 mono_error_init (error);
4425 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4427 mono_error_init (error);
4432 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4438 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4443 #endif /* DISABLE_VERIFIER */