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>
31 #ifndef DISABLE_VERIFIER
33 TODO add fail fast mode
34 TODO add PE32+ support
35 TODO verify the entry point RVA and content.
36 TODO load_section_table and load_data_directories must take PE32+ into account
37 TODO add section relocation support
38 TODO verify the relocation table, since we really don't use, no need so far.
39 TODO do full PECOFF resources verification
40 TODO verify in the CLI header entry point and resources
41 TODO implement null token typeref validation
42 TODO verify table wide invariants for typedef (sorting and uniqueness)
43 TODO implement proper authenticode data directory validation
44 TODO verify properties that require multiple tables to be valid
45 FIXME use subtraction based bounds checking to avoid overflows
46 FIXME get rid of metadata_streams and other fields from VerifyContext
49 #ifdef MONO_VERIFIER_DEBUG
50 #define VERIFIER_DEBUG(code) do { code; } while (0)
52 #define VERIFIER_DEBUG(code)
55 #define INVALID_OFFSET ((guint32)-1)
56 #define INVALID_ADDRESS 0xffffffff
66 RESOURCE_TABLE_IDX = 2,
67 CERTIFICATE_TABLE_IDX = 4,
68 RELOCATION_TABLE_IDX = 5,
82 #define INVALID_TABLE (0xFF)
83 /*format: number of bits, number of tables, tables{n. tables} */
84 const static unsigned char coded_index_desc[] = {
85 #define TYPEDEF_OR_REF_DESC (0)
92 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
99 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
107 MONO_TABLE_INTERFACEIMPL,
108 MONO_TABLE_MEMBERREF,
110 MONO_TABLE_DECLSECURITY,
113 MONO_TABLE_STANDALONESIG,
114 MONO_TABLE_MODULEREF,
117 MONO_TABLE_ASSEMBLYREF,
119 MONO_TABLE_EXPORTEDTYPE,
120 MONO_TABLE_MANIFESTRESOURCE,
121 MONO_TABLE_GENERICPARAM,
123 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
129 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
136 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
145 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
151 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
155 MONO_TABLE_MEMBERREF,
157 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
163 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
167 MONO_TABLE_ASSEMBLYREF,
168 MONO_TABLE_EXPORTEDTYPE,
170 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
176 MONO_TABLE_MEMBERREF,
179 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
183 MONO_TABLE_MODULEREF,
184 MONO_TABLE_ASSEMBLYREF,
187 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
197 guint32 translated_offset;
209 guint32 rellocationsRVA;
210 guint16 numberOfRelocations;
225 gboolean report_error;
226 gboolean report_warning;
229 DataDirectory data_directories [16];
230 guint32 section_count;
231 SectionHeader *sections;
233 OffsetAndSize metadata_streams [5]; //offset from begin of the image
236 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
238 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
239 vinfo->info.status = __status; \
240 vinfo->info.message = ( __msg); \
241 vinfo->exception_type = (__exception); \
242 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
245 #define ADD_WARNING(__ctx, __msg) \
247 if ((__ctx)->report_warning) { \
248 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
249 (__ctx)->valid = 0; \
254 #define ADD_ERROR_NO_RETURN(__ctx, __msg) \
256 if ((__ctx)->report_error) \
257 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
258 (__ctx)->valid = 0; \
261 #define ADD_ERROR(__ctx, __msg) \
263 if ((__ctx)->report_error) \
264 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
265 (__ctx)->valid = 0; \
269 #define FAIL(__ctx, __msg) \
271 if ((__ctx)->report_error) \
272 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
273 (__ctx)->valid = 0; \
277 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
279 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
281 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
282 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
284 #if SIZEOF_VOID_P == 4
285 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
287 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
290 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
291 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
294 dword_align (const char *ptr)
296 #if SIZEOF_VOID_P == 8
297 return (const char *) (((guint64) (ptr + 3)) & ~3);
299 return (const char *) (((guint32) (ptr + 3)) & ~3);
304 add_from_mono_error (VerifyContext *ctx, MonoError *error)
306 if (mono_error_ok (error))
309 ADD_ERROR (ctx, g_strdup (mono_error_get_message (error)));
310 mono_error_cleanup (error);
314 pe_signature_offset (VerifyContext *ctx)
316 return read32 (ctx->data + 0x3c);
320 pe_header_offset (VerifyContext *ctx)
322 return read32 (ctx->data + 0x3c) + 4;
326 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
330 if (rva + size < rva) //overflow
333 if (ctx->stage > STAGE_PE) {
334 MonoCLIImageInfo *iinfo = ctx->image->image_info;
335 const int top = iinfo->cli_section_count;
336 MonoSectionTable *tables = iinfo->cli_section_tables;
339 for (i = 0; i < top; i++) {
340 guint32 base = tables->st_virtual_address;
341 guint32 end = base + tables->st_raw_data_size;
343 if (rva >= base && rva + size <= end)
346 /*if ((addr >= tables->st_virtual_address) &&
347 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
349 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
359 for (i = 0; i < ctx->section_count; ++i) {
360 guint32 base = ctx->sections [i].baseRVA;
361 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
362 if (rva >= base && rva + size <= end)
369 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
371 if (dir->translated_offset > offset)
373 if (dir->size < size)
375 return offset + size <= dir->translated_offset + dir->size;
379 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
381 if (off->offset > offset)
384 if (off->size < size)
387 return offset + size <= off->offset + off->size;
391 translate_rva (VerifyContext *ctx, guint32 rva)
395 if (ctx->stage > STAGE_PE)
396 return mono_cli_rva_image_map (ctx->image, rva);
401 for (i = 0; i < ctx->section_count; ++i) {
402 guint32 base = ctx->sections [i].baseRVA;
403 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
404 if (rva >= base && rva <= end) {
405 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
407 return res >= ctx->size ? INVALID_OFFSET : res;
411 return INVALID_OFFSET;
415 verify_msdos_header (VerifyContext *ctx)
419 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
420 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
421 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
422 lfanew = pe_signature_offset (ctx);
423 if (lfanew > ctx->size - 4)
424 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
428 verify_pe_header (VerifyContext *ctx)
430 guint32 offset = pe_signature_offset (ctx);
431 const char *pe_header = ctx->data + offset;
432 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
433 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
437 if (offset > ctx->size - 20)
438 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
439 if (read16 (pe_header) != 0x14c)
440 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
444 verify_pe_optional_header (VerifyContext *ctx)
446 guint32 offset = pe_header_offset (ctx);
447 guint32 header_size, file_alignment;
448 const char *pe_header = ctx->data + offset;
449 const char *pe_optional_header = pe_header + 20;
451 header_size = read16 (pe_header + 16);
454 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
455 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
457 if (offset > ctx->size - header_size || header_size > ctx->size)
458 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
460 if (read16 (pe_optional_header) == 0x10b) {
461 if (header_size != 224)
462 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
464 /* LAMESPEC MS plays around this value and ignore it during validation
465 if (read32 (pe_optional_header + 28) != 0x400000)
466 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
467 if (read32 (pe_optional_header + 32) != 0x2000)
468 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
469 file_alignment = read32 (pe_optional_header + 36);
470 if (file_alignment != 0x200 && file_alignment != 0x1000)
471 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
472 /* All the junk in the middle is irrelevant, specially for mono. */
473 if (read32 (pe_optional_header + 92) > 0x10)
474 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
476 if (read16 (pe_optional_header) == 0x20B)
477 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
479 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
484 load_section_table (VerifyContext *ctx)
487 SectionHeader *sections;
488 guint32 offset = pe_header_offset (ctx);
489 const char *ptr = ctx->data + offset;
490 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
492 offset += 244;/*FIXME, this constant is different under PE32+*/
495 if (num_sections * 40 > ctx->size - offset)
496 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
498 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
499 for (i = 0; i < num_sections; ++i) {
500 sections [i].size = read32 (ptr + 8);
501 sections [i].baseRVA = read32 (ptr + 12);
502 sections [i].baseOffset = read32 (ptr + 20);
503 sections [i].rellocationsRVA = read32 (ptr + 24);
504 sections [i].numberOfRelocations = read16 (ptr + 32);
508 ptr = ctx->data + offset; /*reset it to the beggining*/
509 for (i = 0; i < num_sections; ++i) {
510 guint32 raw_size, flags;
511 if (sections [i].baseOffset == 0)
512 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
513 if (sections [i].baseOffset >= ctx->size)
514 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
515 if (sections [i].size > ctx->size - sections [i].baseOffset)
516 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
518 raw_size = read32 (ptr + 16);
519 if (raw_size < sections [i].size)
520 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
522 if (raw_size > ctx->size - sections [i].baseOffset)
523 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
525 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
526 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
528 flags = read32 (ptr + 36);
529 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
530 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
531 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
538 is_valid_data_directory (int i)
540 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
541 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
545 load_data_directories (VerifyContext *ctx)
547 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
548 const char *ptr = ctx->data + offset;
551 for (i = 0; i < 16; ++i) {
552 guint32 rva = read32 (ptr);
553 guint32 size = read32 (ptr + 4);
555 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
556 if (i == CERTIFICATE_TABLE_IDX) {
560 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
561 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
563 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
564 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
566 ctx->data_directories [i].rva = rva;
567 ctx->data_directories [i].size = size;
568 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
574 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
576 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
579 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
582 guint32 hint_table_rva;
584 import_rva = translate_rva (ctx, import_rva);
585 g_assert (import_rva != INVALID_OFFSET);
587 hint_table_rva = read32 (ctx->data + import_rva);
588 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
589 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
591 hint_table_rva = translate_rva (ctx, hint_table_rva);
592 g_assert (hint_table_rva != INVALID_OFFSET);
593 ptr = ctx->data + hint_table_rva + 2;
595 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
596 char name[SIZE_OF_CORMAIN];
597 memcpy (name, ptr, SIZE_OF_CORMAIN);
598 name [SIZE_OF_CORMAIN - 1] = 0;
599 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
604 verify_import_table (VerifyContext *ctx)
606 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
607 guint32 offset = it.translated_offset;
608 const char *ptr = ctx->data + offset;
609 guint32 name_rva, ilt_rva, iat_rva;
611 g_assert (offset != INVALID_OFFSET);
614 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
616 ilt_rva = read32 (ptr);
617 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
618 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
620 name_rva = read32 (ptr + 12);
621 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
622 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
624 iat_rva = read32 (ptr + 16);
626 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
627 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
629 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
630 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));
634 name_rva = translate_rva (ctx, name_rva);
635 g_assert (name_rva != INVALID_OFFSET);
636 ptr = ctx->data + name_rva;
638 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
639 char name[SIZE_OF_MSCOREE];
640 memcpy (name, ptr, SIZE_OF_MSCOREE);
641 name [SIZE_OF_MSCOREE - 1] = 0;
642 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
647 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
652 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
656 verify_resources_table (VerifyContext *ctx)
658 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
660 guint16 named_entries, id_entries;
661 const char *ptr, *root, *end;
667 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));
669 offset = it.translated_offset;
670 root = ptr = ctx->data + offset;
671 end = root + it.size;
673 g_assert (offset != INVALID_OFFSET);
675 named_entries = read16 (ptr + 12);
676 id_entries = read16 (ptr + 14);
678 if ((named_entries + id_entries) * 8 + 16 > it.size)
679 ADD_ERROR (ctx, g_strdup_printf ("Resource section is too small, the number of entries (%d) doesn't fit on it's size %d", named_entries + id_entries, it.size));
681 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
682 if (named_entries || id_entries)
683 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
687 /*----------nothing from here on can use data_directory---*/
690 get_data_dir (VerifyContext *ctx, int idx)
692 MonoCLIImageInfo *iinfo = ctx->image->image_info;
693 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
697 res.rva = entry->rva;
698 res.size = entry->size;
699 res.translated_offset = translate_rva (ctx, res.rva);
704 verify_cli_header (VerifyContext *ctx)
706 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
712 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
715 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
717 offset = it.translated_offset;
718 ptr = ctx->data + offset;
720 g_assert (offset != INVALID_OFFSET);
722 if (read16 (ptr) != 72)
723 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
725 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
726 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
729 if (!read32 (ptr + 8) || !read32 (ptr + 12))
730 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
732 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
733 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
736 for (i = 0; i < 6; ++i) {
737 guint32 rva = read32 (ptr);
738 guint32 size = read32 (ptr + 4);
740 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
741 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
746 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
751 pad4 (guint32 offset)
753 if (offset & 0x3) //pad to the next 4 byte boundary
754 offset = (offset & ~0x3) + 4;
759 verify_metadata_header (VerifyContext *ctx)
762 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
763 guint32 offset, section_count;
766 offset = it.translated_offset;
767 ptr = ctx->data + offset;
768 g_assert (offset != INVALID_OFFSET);
770 //build a directory entry for the metadata root
772 it.rva = read32 (ptr);
774 it.size = read32 (ptr);
775 it.translated_offset = offset = translate_rva (ctx, it.rva);
777 ptr = ctx->data + offset;
778 g_assert (offset != INVALID_OFFSET);
781 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
783 if (read32 (ptr) != 0x424A5342)
784 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
786 offset = pad4 (offset + 16 + read32 (ptr + 12));
788 if (!bounds_check_datadir (&it, offset, 4))
789 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least %d bytes required for flags decoding)", it.size, offset + 4 - it.translated_offset));
791 ptr = ctx->data + offset; //move to streams header
793 section_count = read16 (ptr + 2);
794 if (section_count < 2)
795 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
800 for (i = 0; i < section_count; ++i) {
801 guint32 stream_off, stream_size;
802 int string_size, stream_idx;
804 if (!bounds_check_datadir (&it, offset, 8))
805 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small for initial decode of stream header %d, missing %d bytes", i, offset + 9 - it.translated_offset));
807 stream_off = it.translated_offset + read32 (ptr);
808 stream_size = read32 (ptr + 4);
810 if (!bounds_check_datadir (&it, stream_off, stream_size))
811 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
816 for (string_size = 0; string_size < 32; ++string_size) {
817 if (!bounds_check_datadir (&it, offset++, 1))
818 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
819 if (!ptr [string_size])
823 if (ptr [string_size])
824 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
826 if (!strncmp ("#Strings", ptr, 9))
827 stream_idx = STRINGS_STREAM;
828 else if (!strncmp ("#US", ptr, 4))
829 stream_idx = USER_STRINGS_STREAM;
830 else if (!strncmp ("#Blob", ptr, 6))
831 stream_idx = BLOB_STREAM;
832 else if (!strncmp ("#GUID", ptr, 6))
833 stream_idx = GUID_STREAM;
834 else if (!strncmp ("#~", ptr, 3))
835 stream_idx = TILDE_STREAM;
837 ADD_WARNING (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
838 offset = pad4 (offset);
839 ptr = ctx->data + offset;
843 if (ctx->metadata_streams [stream_idx].offset != 0)
844 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
846 ctx->metadata_streams [stream_idx].offset = stream_off;
847 ctx->metadata_streams [stream_idx].size = stream_size;
849 offset = pad4 (offset);
850 ptr = ctx->data + offset;
853 if (!ctx->metadata_streams [TILDE_STREAM].size)
854 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
855 if (!ctx->metadata_streams [GUID_STREAM].size)
856 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
860 verify_tables_schema (VerifyContext *ctx)
862 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
863 unsigned offset = tables_area.offset;
864 const char *ptr = ctx->data + offset;
865 guint64 valid_tables;
869 if (tables_area.size < 24)
870 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
872 if (ptr [4] != 2 && ptr [4] != 1)
873 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
875 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
877 if ((ptr [6] & ~0x7) != 0)
878 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata heap sizes 0x%02x, only bits 0, 1 and 2 can be set", ((unsigned char *) ptr) [6]));
880 valid_tables = read64 (ptr + 8);
882 for (i = 0; i < 64; ++i) {
883 if (!(valid_tables & ((guint64)1 << i)))
886 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
887 Unused: 0x1E 0x1F 0x2D-0x3F
888 We don't care about the MS extensions.*/
889 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
890 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i));
891 if (i == 0x1E || i == 0x1F || i >= 0x2D)
892 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
896 if (tables_area.size < 24 + count * 4)
897 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));
900 for (i = 0; i < 64; ++i) {
901 if (valid_tables & ((guint64)1 << i)) {
902 guint32 row_count = read32 (ptr);
903 if (row_count > (1 << 24) - 1)
904 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
910 /*----------nothing from here on can use data_directory or metadata_streams ---*/
913 get_col_offset (VerifyContext *ctx, int table, int column)
915 guint32 bitfield = ctx->image->tables [table].size_bitfield;
919 offset += mono_metadata_table_size (bitfield, column);
925 get_col_size (VerifyContext *ctx, int table, int column)
927 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
931 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
934 res.offset = header->data - ctx->data;
935 res.size = header->size;
941 is_valid_string_full_with_image (MonoImage *image, guint32 offset, gboolean allow_empty)
943 guint32 heap_offset = (char*)image->heap_strings.data - image->raw_data;
944 guint32 heap_size = image->heap_strings.size;
947 const char *data = image->raw_data + heap_offset;
949 if (offset >= heap_size)
951 if (CHECK_ADDP_OVERFLOW_UN (data, offset))
954 if (!mono_utf8_validate_and_len_with_bounds (data + offset, heap_size - offset, &length, NULL))
956 return allow_empty || length > 0;
961 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
963 return is_valid_string_full_with_image (ctx->image, offset, allow_empty);
967 is_valid_string (VerifyContext *ctx, guint32 offset)
969 return is_valid_string_full (ctx, offset, TRUE);
973 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
975 return is_valid_string_full (ctx, offset, FALSE);
979 is_valid_guid (VerifyContext *ctx, guint32 offset)
981 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
982 return guids.size >= 8 && guids.size - 8 >= offset;
986 get_coded_index_token (int token_kind, guint32 coded_token)
988 guint32 bits = coded_index_desc [token_kind];
989 return coded_token >> bits;
993 get_coded_index_table (int kind, guint32 coded_token)
995 guint32 idx, bits = coded_index_desc [kind];
997 idx = coded_token & ((1 << bits) - 1);
998 return coded_index_desc [kind + idx];
1002 make_coded_token (int kind, guint32 table, guint32 table_idx)
1004 guint32 bits = coded_index_desc [kind++];
1005 guint32 tables = coded_index_desc [kind++];
1007 for (i = 0; i < tables; ++i) {
1008 if (coded_index_desc [kind++] == table)
1009 return ((table_idx + 1) << bits) | i;
1011 g_assert_not_reached ();
1016 is_valid_coded_index_with_image (MonoImage *image, int token_kind, guint32 coded_token)
1018 guint32 bits = coded_index_desc [token_kind++];
1019 guint32 table_count = coded_index_desc [token_kind++];
1020 guint32 table = coded_token & ((1 << bits) - 1);
1021 guint32 token = coded_token >> bits;
1023 if (table >= table_count)
1026 /*token_kind points to the first table idx*/
1027 table = coded_index_desc [token_kind + table];
1029 if (table == INVALID_TABLE)
1031 return token <= image->tables [table].rows;
1035 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
1037 return is_valid_coded_index_with_image (ctx->image, token_kind, coded_token);
1044 MonoTableInfo *table;
1048 token_locator (const void *a, const void *b)
1050 RowLocator *loc = (RowLocator *)a;
1051 unsigned const char *row = (unsigned const char *)b;
1052 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1054 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1055 return (int)loc->token - (int)token;
1059 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1061 MonoTableInfo *tinfo = &ctx->image->tables [table];
1063 const char *res, *base;
1064 locator.token = coded_token;
1065 locator.col_offset = get_col_offset (ctx, table, column);
1066 locator.col_size = get_col_size (ctx, table, column);
1067 locator.table = tinfo;
1071 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) );
1072 res = bsearch (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1076 return (res - base) / tinfo->row_size;
1079 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1081 get_string_ptr (VerifyContext *ctx, guint offset)
1083 return ctx->image->heap_strings.data + offset;
1086 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1088 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1091 return strcmp (str, "");
1093 return strcmp (str, get_string_ptr (ctx, offset));
1097 mono_verifier_is_corlib (MonoImage *image)
1099 gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
1100 TRUE : mono_security_core_clr_is_platform_image (image);
1102 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1106 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1108 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1112 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1115 const unsigned char *ptr = (const unsigned char *)_ptr;
1123 if ((b & 0x80) == 0) {
1126 } else if ((b & 0x40) == 0) {
1130 *value = ((b & 0x3f) << 8 | ptr [1]);
1135 *value = ((b & 0x1f) << 24) |
1145 decode_signature_header (VerifyContext *ctx, guint32 offset, guint32 *size, const char **first_byte)
1147 MonoStreamHeader blob = ctx->image->heap_blob;
1148 guint32 value, enc_size;
1150 if (offset >= blob.size)
1153 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1156 if (CHECK_ADD4_OVERFLOW_UN (offset, enc_size))
1161 if (ADD_IS_GREATER_OR_OVF (offset, value, blob.size))
1165 *first_byte = blob.data + offset;
1170 safe_read (const char **_ptr, const char *limit, unsigned *dest, int size)
1172 const char *ptr = *_ptr;
1173 if (ptr + size > limit)
1177 *dest = *((guint8*)ptr);
1181 *dest = read16 (ptr);
1185 *dest = read32 (ptr);
1194 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1197 const char *ptr = *_ptr;
1198 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1203 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1204 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1205 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1206 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1209 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1212 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1215 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1217 const char *ptr = *_ptr;
1222 if (!safe_read8 (type, ptr, end))
1223 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1225 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1230 if (!safe_read_cint (token, ptr, end))
1231 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1233 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1234 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1242 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1244 const char *ptr = *_ptr;
1246 unsigned size, num, i;
1248 if (!safe_read8 (val, ptr, end))
1249 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1252 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1254 if (!safe_read_cint (size, ptr, end))
1255 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1257 for (i = 0; i < size; ++i) {
1258 if (!safe_read_cint (num, ptr, end))
1259 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1262 if (!safe_read_cint (size, ptr, end))
1263 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1265 for (i = 0; i < size; ++i) {
1266 if (!safe_read_cint (num, ptr, end))
1267 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1275 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1277 const char *ptr = *_ptr;
1279 unsigned count, token, i;
1281 if (!safe_read8 (type, ptr, end))
1282 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1284 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1285 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1287 if (!safe_read_cint (token, ptr, end))
1288 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1290 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1291 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1294 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1295 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1296 FAIL (ctx, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx->token));
1299 if (!safe_read_cint (count, ptr, end))
1300 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1303 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1305 for (i = 0; i < count; ++i) {
1306 if (!parse_type (ctx, &ptr, end))
1307 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1314 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1316 const char *ptr = *_ptr;
1320 if (!safe_read8 (type, ptr, end))
1321 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1323 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1324 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1325 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1326 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1327 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1331 if (!parse_custom_mods (ctx, &ptr, end))
1332 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1334 if (!safe_read8 (type, ptr, end))
1335 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1337 if (type != MONO_TYPE_VOID) {
1339 if (!parse_type (ctx, &ptr, end))
1340 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1344 case MONO_TYPE_VALUETYPE:
1345 case MONO_TYPE_CLASS:
1346 if (!safe_read_cint (token, ptr, end))
1347 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1349 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1350 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1352 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1353 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1354 FAIL (ctx, g_strdup_printf ("Type: Recurside type specification (%x). A type signature can't reference itself", ctx->token));
1359 case MONO_TYPE_MVAR:
1360 if (!safe_read_cint (token, ptr, end))
1361 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1364 case MONO_TYPE_ARRAY:
1365 if (!parse_type (ctx, &ptr, end))
1366 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1367 if (!parse_array_shape (ctx, &ptr, end))
1368 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1371 case MONO_TYPE_GENERICINST:
1372 if (!parse_generic_inst (ctx, &ptr, end))
1373 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1376 case MONO_TYPE_FNPTR:
1377 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1378 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1381 case MONO_TYPE_SZARRAY:
1382 if (!parse_custom_mods (ctx, &ptr, end))
1383 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1384 if (!parse_type (ctx, &ptr, end))
1385 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1393 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1398 if (!parse_custom_mods (ctx, _ptr, end))
1402 if (!safe_read8 (type, ptr, end))
1403 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1405 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1410 //it's a byref, update the cursor ptr
1411 if (type == MONO_TYPE_BYREF)
1414 return parse_type (ctx, _ptr, end);
1418 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1423 if (!parse_custom_mods (ctx, _ptr, end))
1427 if (!safe_read8 (type, ptr, end))
1428 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1430 if (type == MONO_TYPE_TYPEDBYREF) {
1435 //it's a byref, update the cursor ptr
1436 if (type == MONO_TYPE_BYREF)
1439 return parse_type (ctx, _ptr, end);
1443 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1446 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1447 const char *ptr = *_ptr;
1448 gboolean saw_sentinel = FALSE;
1450 if (!safe_read8 (cconv, ptr, end))
1451 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1454 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1456 if (allow_unmanaged) {
1457 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1458 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1459 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1460 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1462 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1463 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1465 if ((cconv & 0x10) && gparam_count == 0)
1466 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1468 if (allow_unmanaged && (cconv & 0x10))
1469 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1471 if (!safe_read_cint (param_count, ptr, end))
1472 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1474 if (!parse_return_type (ctx, &ptr, end))
1475 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1477 for (i = 0; i < param_count; ++i) {
1478 if (allow_sentinel) {
1479 if (!safe_read8 (type, ptr, end))
1480 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1482 if (type == MONO_TYPE_SENTINEL) {
1483 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1484 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1487 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1489 saw_sentinel = TRUE;
1495 if (!parse_param (ctx, &ptr, end))
1496 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1504 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1507 unsigned param_count = 0, i;
1508 const char *ptr = *_ptr;
1510 if (!safe_read8 (sig, ptr, end))
1511 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1513 if (sig != 0x08 && sig != 0x28)
1514 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1516 if (!safe_read_cint (param_count, ptr, end))
1517 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1519 if (!parse_custom_mods (ctx, &ptr, end))
1522 if (!parse_type (ctx, &ptr, end))
1523 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1525 for (i = 0; i < param_count; ++i) {
1526 if (!parse_type (ctx, &ptr, end))
1527 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1535 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1537 const char *ptr = *_ptr;
1538 unsigned signature = 0;
1540 if (!safe_read8 (signature, ptr, end))
1541 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1543 if (signature != 0x06)
1544 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1546 if (!parse_custom_mods (ctx, &ptr, end))
1549 if (safe_read8 (signature, ptr, end)) {
1550 if (signature != MONO_TYPE_BYREF)
1555 return parse_type (ctx, _ptr, end);
1559 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1562 unsigned locals_count = 0, i;
1563 const char *ptr = *_ptr;
1565 if (!safe_read8 (sig, ptr, end))
1566 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1569 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1571 if (!safe_read_cint (locals_count, ptr, end))
1572 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1574 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1575 if (locals_count == 0)
1576 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1579 for (i = 0; i < locals_count; ++i) {
1580 if (!safe_read8 (sig, ptr, end))
1581 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1583 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1584 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1585 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1586 if (!safe_read8 (sig, ptr, end))
1587 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1590 if (sig == MONO_TYPE_BYREF) {
1591 if (!safe_read8 (sig, ptr, end))
1592 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1593 if (sig == MONO_TYPE_TYPEDBYREF)
1594 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1597 if (sig == MONO_TYPE_TYPEDBYREF)
1602 if (!parse_type (ctx, &ptr, end))
1603 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1611 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1614 unsigned signature = 0;
1615 const char *ptr = NULL, *end;
1617 if (!decode_signature_header (ctx, offset, &size, &ptr))
1618 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1621 if (!safe_read8 (signature, ptr, end))
1622 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1625 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1628 return parse_field (ctx, &ptr, end);
1632 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1635 const char *ptr = NULL, *end;
1637 if (!decode_signature_header (ctx, offset, &size, &ptr))
1638 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1641 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1645 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1648 unsigned signature = 0;
1649 const char *ptr = NULL, *end;
1651 if (!decode_signature_header (ctx, offset, &size, &ptr))
1652 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1655 if (!safe_read8 (signature, ptr, end))
1656 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1659 if (signature == 0x06)
1660 return parse_field (ctx, &ptr, end);
1662 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1666 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1669 unsigned prolog = 0;
1670 const char *ptr = NULL, *end;
1675 if (!decode_signature_header (ctx, offset, &size, &ptr))
1676 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1679 if (!safe_read16 (prolog, ptr, end))
1680 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1683 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1689 is_valid_cattr_type (MonoType *type)
1693 if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1696 if (type->type == MONO_TYPE_VALUETYPE) {
1697 klass = mono_class_from_mono_type (type);
1698 return klass && klass->enumtype;
1701 if (type->type == MONO_TYPE_CLASS)
1702 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1708 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1711 const char *ptr = *_ptr;
1717 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1720 if (*ptr == (char)0xFF) {
1725 if (!safe_read_cint (size, ptr, end))
1726 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1728 if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1729 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1739 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1741 const char *dummy_str;
1743 return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1747 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1751 const char *str_start = NULL;
1752 const char *ptr = *_ptr;
1754 guint32 str_len = 0;
1756 if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1759 /*NULL or empty string*/
1760 if (str_start == NULL || str_len == 0) {
1761 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1765 enum_name = g_memdup (str_start, str_len + 1);
1766 enum_name [str_len] = 0;
1767 type = mono_reflection_type_from_name (enum_name, ctx->image);
1769 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1775 klass = mono_class_from_mono_type (type);
1776 if (!klass || !klass->enumtype) {
1777 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1786 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1789 const char *ptr = *_ptr;
1791 guint32 element_count, i;
1794 klass = mono_type->data.klass;
1795 type = mono_type->type;
1799 case MONO_TYPE_BOOLEAN:
1806 case MONO_TYPE_CHAR:
1820 case MONO_TYPE_STRING:
1822 return is_valid_ser_string (ctx, _ptr, end);
1824 case MONO_TYPE_OBJECT: {
1825 unsigned sub_type = 0;
1826 if (!safe_read8 (sub_type, ptr, end))
1827 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1829 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1833 if (sub_type == MONO_TYPE_ENUM) {
1834 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1838 klass = klass->element_class;
1839 type = klass->byval_arg.type;
1842 if (sub_type == 0x50) { /*Type*/
1844 return is_valid_ser_string (ctx, _ptr, end);
1846 if (sub_type == MONO_TYPE_SZARRAY) {
1847 MonoType simple_type = {{0}};
1849 if (!safe_read8 (etype, ptr, end))
1850 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1852 if (etype == MONO_TYPE_ENUM) {
1853 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1856 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1857 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
1858 klass = mono_class_from_mono_type (&simple_type);
1860 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1862 type = MONO_TYPE_SZARRAY;
1865 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1869 case MONO_TYPE_CLASS:
1870 if (klass != mono_defaults.systemtype_class)
1871 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1873 return is_valid_ser_string (ctx, _ptr, end);
1875 case MONO_TYPE_VALUETYPE:
1876 if (!klass || !klass->enumtype)
1877 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1879 klass = klass->element_class;
1880 type = klass->byval_arg.type;
1883 case MONO_TYPE_SZARRAY:
1884 mono_type = &klass->byval_arg;
1885 if (!is_valid_cattr_type (mono_type))
1886 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1887 if (!safe_read32 (element_count, ptr, end))
1888 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1889 if (element_count == 0xFFFFFFFFu) {
1893 for (i = 0; i < element_count; ++i) {
1894 if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1900 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1903 if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1904 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1905 *_ptr = ptr + elem_size;
1910 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1913 unsigned prolog = 0;
1915 MonoMethodSignature *sig;
1920 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1922 sig = mono_method_signature_checked (ctor, &error);
1923 if (!mono_error_ok (&error)) {
1924 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1925 mono_error_cleanup (&error);
1929 if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1930 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1934 if (!safe_read16 (prolog, ptr, end))
1935 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1938 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1940 args = sig->param_count;
1941 for (i = 0; i < args; ++i) {
1942 MonoType *arg_type = sig->params [i];
1943 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1947 if (!safe_read16 (num_named, ptr, end))
1948 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1950 for (i = 0; i < num_named; ++i) {
1951 MonoType *type, simple_type = {{0}};
1954 if (!safe_read8 (kind, ptr, end))
1955 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1956 if (kind != 0x53 && kind != 0x54)
1957 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1958 if (!safe_read8 (kind, ptr, end))
1959 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1961 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1962 simple_type.type = kind;
1963 type = &simple_type;
1964 } else if (kind == MONO_TYPE_ENUM) {
1965 MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1968 type = &klass->byval_arg;
1969 } else if (kind == 0x50) {
1970 type = &mono_defaults.systemtype_class->byval_arg;
1971 } else if (kind == 0x51) {
1972 type = &mono_defaults.object_class->byval_arg;
1973 } else if (kind == MONO_TYPE_SZARRAY) {
1976 if (!safe_read8 (etype, ptr, end))
1977 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1979 if (etype == MONO_TYPE_ENUM) {
1980 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1983 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1984 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
1985 klass = mono_class_from_mono_type (&simple_type);
1987 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1989 type = &mono_array_class_get (klass, 1)->byval_arg;
1991 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
1994 if (!is_valid_ser_string (ctx, &ptr, end))
1997 if (!is_valid_fixed_param (ctx, type, &ptr, end))
2006 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
2008 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2009 //TODO do proper verification
2010 return blob.size >= 1 && blob.size - 1 >= offset;
2014 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
2016 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2017 //TODO do proper verification
2018 return blob.size >= 1 && blob.size - 1 >= offset;
2022 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2025 unsigned signature = 0;
2026 const char *ptr = NULL, *end;
2028 if (!decode_signature_header (ctx, offset, &size, &ptr))
2029 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2032 if (!safe_read8 (signature, ptr, end))
2033 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2036 if (signature == 0x07)
2037 return parse_locals_signature (ctx, &ptr, end);
2039 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2040 if (signature == 0x06)
2041 return parse_field (ctx, &ptr, end);
2043 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2047 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2050 const char *ptr = NULL, *end;
2052 if (!decode_signature_header (ctx, offset, &size, &ptr))
2053 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2056 return parse_property_signature (ctx, &ptr, end);
2060 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2063 const char *ptr = NULL, *end;
2066 if (!decode_signature_header (ctx, offset, &size, &ptr))
2067 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2070 if (!parse_custom_mods (ctx, &ptr, end))
2073 if (!safe_read8 (type, ptr, end))
2074 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2076 if (type == MONO_TYPE_BYREF) {
2077 if (!safe_read8 (type, ptr, end))
2078 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2079 if (type == MONO_TYPE_TYPEDBYREF)
2080 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2083 if (type == MONO_TYPE_TYPEDBYREF)
2087 return parse_type (ctx, &ptr, end);
2091 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2094 const char *ptr = NULL, *end;
2096 unsigned count = 0, i;
2098 if (!decode_signature_header (ctx, offset, &size, &ptr))
2099 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2102 if (!safe_read8 (type, ptr, end))
2103 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2106 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2108 if (!safe_read_cint (count, ptr, end))
2109 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2112 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2114 for (i = 0; i < count; ++i) {
2115 if (!parse_type (ctx, &ptr, end))
2116 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2122 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2124 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2125 guint32 entry_size, bytes;
2127 if (blob.size < offset)
2130 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2133 if (entry_size < minsize)
2136 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2138 entry_size += bytes;
2140 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2144 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2146 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2147 guint32 size, entry_size, bytes;
2149 if (blob.size < offset)
2150 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2152 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2153 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2155 if (type == MONO_TYPE_STRING) {
2156 //String is encoded as: compressed_int:len len *bytes
2159 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2160 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
2166 case MONO_TYPE_BOOLEAN:
2171 case MONO_TYPE_CHAR:
2179 case MONO_TYPE_CLASS:
2189 g_assert_not_reached ();
2192 if (size != entry_size)
2193 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2197 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2198 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2200 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2201 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2205 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2206 //only 0x01, 0x40 and 0x80 are allowed
2207 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2210 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2212 unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2213 unsigned header = 0;
2214 unsigned fat_header = 0, size = 0, max_stack;
2215 const char *ptr = NULL, *end;
2219 if (offset == INVALID_ADDRESS)
2220 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2222 ptr = ctx->data + offset;
2223 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2225 if (!safe_read8 (header, ptr, end))
2226 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2228 switch (header & 0x3) {
2231 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2234 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
2235 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2240 if (!safe_read16 (fat_header, ptr, end))
2241 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2243 size = (fat_header >> 12) & 0xF;
2245 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2247 if (!safe_read16 (max_stack, ptr, end))
2248 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2250 if (!safe_read32 (code_size, ptr, end))
2251 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2253 if (!safe_read32 (local_vars_tok, ptr, end))
2254 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2256 if (local_vars_tok) {
2257 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2258 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2259 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
2260 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2261 *locals_token = local_vars_tok & 0xFFFFFF;
2264 if (fat_header & FAT_HEADER_INVALID_FLAGS)
2265 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2267 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2268 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2270 if (!(fat_header & 0x08))
2276 unsigned section_header = 0, section_size = 0;
2279 ptr = dword_align (ptr);
2280 if (!safe_read32 (section_header, ptr, end))
2281 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2283 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2284 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2286 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2287 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2289 if (section_size < 4)
2290 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2292 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2293 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2295 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2296 guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2298 LAMEIMPL: MS emits section_size without accounting for header size.
2299 Mono does as the spec says. section_size is header + section
2300 MS's peverify happily accepts both.
2302 if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2303 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)));
2305 /* only verify the class token is verified as the rest is done by the IL verifier*/
2306 for (i = 0; i < clauses; ++i) {
2307 unsigned flags = *(unsigned char*)ptr;
2308 unsigned class_token = 0;
2309 ptr += (is_fat ? 20 : 8);
2310 if (!safe_read32 (class_token, ptr, end))
2311 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2312 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2313 guint table = mono_metadata_token_table (class_token);
2314 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2315 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2316 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2317 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2322 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2329 verify_module_table (VerifyContext *ctx)
2331 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2332 guint32 data [MONO_MODULE_SIZE];
2334 if (table->rows != 1)
2335 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2337 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2339 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2340 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2342 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2343 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2345 if (data [MONO_MODULE_ENC] != 0)
2346 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2348 if (data [MONO_MODULE_ENCBASE] != 0)
2349 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2353 verify_typeref_table (VerifyContext *ctx)
2355 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2359 for (i = 0; i < table->rows; ++i) {
2360 mono_verifier_verify_typeref_row (ctx->image, i, &error);
2361 add_from_mono_error (ctx, &error);
2365 /*bits 9,11,14,15,19,21,24-31 */
2366 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2368 verify_typedef_table (VerifyContext *ctx)
2370 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2371 guint32 data [MONO_TYPEDEF_SIZE];
2372 guint32 fieldlist = 1, methodlist = 1, visibility;
2375 if (table->rows == 0)
2376 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2378 for (i = 0; i < table->rows; ++i) {
2379 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2380 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2381 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2383 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2384 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2386 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2387 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2389 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2390 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2392 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2393 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2395 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2396 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2398 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2399 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2401 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2402 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2404 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2405 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2406 search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2407 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2409 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2410 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2412 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2413 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2415 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2416 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));
2418 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2419 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2421 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2422 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2424 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2425 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));
2427 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2428 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2433 verify_typedef_table_full (VerifyContext *ctx)
2435 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2436 guint32 data [MONO_TYPEDEF_SIZE];
2439 if (table->rows == 0)
2440 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2442 for (i = 0; i < table->rows; ++i) {
2443 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2446 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2447 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2448 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2453 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2454 if (data [MONO_TYPEDEF_EXTENDS])
2455 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2457 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2458 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2462 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2465 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2473 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2475 verify_field_table (VerifyContext *ctx)
2477 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2478 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2481 module_field_list = (guint32)-1;
2482 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2483 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2484 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2487 for (i = 0; i < table->rows; ++i) {
2488 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2489 flags = data [MONO_FIELD_FLAGS];
2491 if (flags & INVALID_FIELD_FLAG_BITS)
2492 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2494 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2495 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2497 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2498 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2500 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2501 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2503 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2504 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2506 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2507 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2508 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2510 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2511 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2512 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2514 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2515 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2516 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2518 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2519 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2520 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2522 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2523 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2525 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2526 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2528 //TODO verify contant flag
2530 if (i + 1 < module_field_list) {
2531 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2532 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2533 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2534 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2535 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2541 verify_field_table_full (VerifyContext *ctx)
2543 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2544 guint32 data [MONO_FIELD_SIZE];
2547 for (i = 0; i < table->rows; ++i) {
2548 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2550 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2551 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2555 /*bits 8,9,10,11,13,14,15*/
2556 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2558 verify_method_table (VerifyContext *ctx)
2560 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2561 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2562 guint32 paramlist = 1;
2563 gboolean is_ctor, is_cctor;
2567 module_method_list = (guint32)-1;
2568 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2569 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2570 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2573 for (i = 0; i < table->rows; ++i) {
2574 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2575 rva = data [MONO_METHOD_RVA];
2576 implflags = data [MONO_METHOD_IMPLFLAGS];
2577 flags = data [MONO_METHOD_FLAGS];
2578 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2579 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2582 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2583 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2586 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2588 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2589 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2591 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2592 is_ctor = !strcmp (".ctor", name);
2593 is_cctor = !strcmp (".cctor", name);
2595 if ((is_ctor || is_cctor) &&
2596 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2597 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2599 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2600 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2602 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2603 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2604 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2605 if (flags & METHOD_ATTRIBUTE_FINAL)
2606 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2607 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2608 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2611 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2612 ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2614 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2615 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2617 //XXX no checks against cas stuff 10,11,12,13)
2619 //TODO check iface with .ctor (15,16)
2621 if (i + 1 < module_method_list) {
2622 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2623 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2624 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2625 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2626 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2627 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2630 //TODO check valuetype for synchronized
2632 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2633 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2635 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2636 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2637 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2638 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2639 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2642 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2643 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2644 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2646 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2647 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2649 //TODO check signature contents
2652 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2653 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2654 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2655 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2657 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2658 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2661 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2663 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2664 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2665 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2667 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2668 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2670 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2671 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2673 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2674 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2676 if (data [MONO_METHOD_PARAMLIST] == 0)
2677 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2679 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2680 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));
2682 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2683 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2685 paramlist = data [MONO_METHOD_PARAMLIST];
2691 verify_method_table_full (VerifyContext *ctx)
2693 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2694 guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2697 for (i = 0; i < table->rows; ++i) {
2698 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2699 rva = data [MONO_METHOD_RVA];
2701 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2702 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2704 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2705 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2710 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2712 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2713 guint32 row = *current_method;
2714 guint32 paramlist, tmp;
2717 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2718 while (row < table->rows) {
2719 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2720 if (tmp > paramlist) {
2721 *current_method = row;
2722 return tmp - paramlist;
2727 /*no more methods, all params apply to the last one*/
2728 *current_method = table->rows;
2733 #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))
2735 verify_param_table (VerifyContext *ctx)
2737 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2738 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2739 gboolean first_param = TRUE;
2742 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2743 if (table->rows > 0)
2744 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2748 remaining_params = get_next_param_count (ctx, ¤t_method);
2750 for (i = 0; i < table->rows; ++i) {
2751 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2752 flags = data [MONO_PARAM_FLAGS];
2754 if (flags & INVALID_PARAM_FLAGS_BITS)
2755 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2757 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2758 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2759 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2761 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2762 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2765 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)
2766 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2768 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2769 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2771 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2772 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2774 first_param = FALSE;
2775 sequence = data [MONO_PARAM_SEQUENCE];
2776 if (--remaining_params == 0) {
2777 remaining_params = get_next_param_count (ctx, ¤t_method);
2784 verify_interfaceimpl_table (VerifyContext *ctx)
2786 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2787 guint32 data [MONO_INTERFACEIMPL_SIZE];
2790 for (i = 0; i < table->rows; ++i) {
2791 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2792 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2793 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2795 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2796 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2798 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2799 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2804 verify_memberref_table (VerifyContext *ctx)
2806 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2807 guint32 data [MONO_MEMBERREF_SIZE];
2810 for (i = 0; i < table->rows; ++i) {
2811 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2813 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2814 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2816 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2817 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2819 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2820 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2822 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2823 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2829 verify_memberref_table_full (VerifyContext *ctx)
2831 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2832 guint32 data [MONO_MEMBERREF_SIZE];
2835 for (i = 0; i < table->rows; ++i) {
2836 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2838 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2839 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2844 verify_constant_table (VerifyContext *ctx)
2846 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2847 guint32 data [MONO_CONSTANT_SIZE], type;
2850 for (i = 0; i < table->rows; ++i) {
2851 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2852 type = data [MONO_CONSTANT_TYPE];
2854 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2855 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2857 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2858 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2860 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2861 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2863 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2864 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2869 verify_cattr_table (VerifyContext *ctx)
2871 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2872 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2875 for (i = 0; i < table->rows; ++i) {
2876 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2878 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2879 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2881 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2882 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2884 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2885 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2890 verify_cattr_table_full (VerifyContext *ctx)
2892 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2895 guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2898 for (i = 0; i < table->rows; ++i) {
2899 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2901 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2902 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2904 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2905 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2906 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2907 mtoken |= MONO_TOKEN_METHOD_DEF;
2909 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2910 mtoken |= MONO_TOKEN_MEMBER_REF;
2913 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2916 ctor = mono_get_method (ctx->image, mtoken, NULL);
2918 /*This can't fail since this is checked in is_valid_cattr_blob*/
2919 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2921 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2922 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2927 verify_field_marshal_table (VerifyContext *ctx)
2929 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2930 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2933 for (i = 0; i < table->rows; ++i) {
2934 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2936 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2937 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2939 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2940 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2942 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2943 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2945 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2946 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2951 verify_field_marshal_table_full (VerifyContext *ctx)
2953 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2954 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2957 for (i = 0; i < table->rows; ++i) {
2958 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2960 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2961 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2966 verify_decl_security_table (VerifyContext *ctx)
2968 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2969 guint32 data [MONO_DECL_SECURITY_SIZE];
2972 for (i = 0; i < table->rows; ++i) {
2973 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2975 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2976 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2978 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2979 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
2981 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
2982 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
2987 verify_decl_security_table_full (VerifyContext *ctx)
2989 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2990 guint32 data [MONO_DECL_SECURITY_SIZE];
2993 for (i = 0; i < table->rows; ++i) {
2994 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2996 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
2997 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
3002 verify_class_layout_table (VerifyContext *ctx)
3004 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
3005 guint32 data [MONO_CLASS_LAYOUT_SIZE];
3008 for (i = 0; i < table->rows; ++i) {
3009 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
3011 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3012 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
3014 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3026 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3032 verify_field_layout_table (VerifyContext *ctx)
3034 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3035 guint32 data [MONO_FIELD_LAYOUT_SIZE];
3038 for (i = 0; i < table->rows; ++i) {
3039 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3041 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3042 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3047 verify_standalonesig_table (VerifyContext *ctx)
3049 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3050 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3053 for (i = 0; i < table->rows; ++i) {
3054 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3056 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3057 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3062 verify_standalonesig_table_full (VerifyContext *ctx)
3064 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3065 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3068 for (i = 0; i < table->rows; ++i) {
3069 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3071 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3072 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3077 verify_eventmap_table (VerifyContext *ctx)
3079 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3080 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3083 for (i = 0; i < table->rows; ++i) {
3084 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3086 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3087 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3089 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3090 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3092 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3096 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3098 verify_event_table (VerifyContext *ctx)
3100 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3101 guint32 data [MONO_EVENT_SIZE];
3104 for (i = 0; i < table->rows; ++i) {
3105 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3107 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3108 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3110 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3111 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3113 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3114 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3119 verify_event_table_full (VerifyContext *ctx)
3121 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3122 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3123 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3124 gboolean found_add, found_remove;
3127 for (i = 0; i < table->rows; ++i) {
3128 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3130 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3131 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3133 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3135 //first we move to the first row for this event
3137 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3141 //now move forward looking for AddOn and RemoveOn rows
3142 found_add = found_remove = FALSE;
3143 while (idx < sema_table->rows) {
3144 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3145 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3147 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3149 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3150 found_remove = TRUE;
3151 if (found_add && found_remove)
3157 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3159 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3164 verify_propertymap_table (VerifyContext *ctx)
3166 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3167 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3170 for (i = 0; i < table->rows; ++i) {
3171 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3173 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3174 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3176 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3177 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3179 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3183 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3185 verify_property_table (VerifyContext *ctx)
3187 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3188 guint32 data [MONO_PROPERTY_SIZE];
3191 for (i = 0; i < table->rows; ++i) {
3192 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3194 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3195 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3197 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3198 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3200 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3201 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3203 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3204 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3205 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3211 verify_methodimpl_table (VerifyContext *ctx)
3213 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3214 guint32 data [MONO_METHODIMPL_SIZE];
3217 for (i = 0; i < table->rows; ++i) {
3218 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3220 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3221 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3223 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3224 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3226 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3227 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3229 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3230 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3232 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3233 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3238 verify_moduleref_table (VerifyContext *ctx)
3240 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3241 guint32 data [MONO_MODULEREF_SIZE];
3244 for (i = 0; i < table->rows; ++i) {
3245 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3247 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3248 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3253 verify_typespec_table (VerifyContext *ctx)
3255 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3256 guint32 data [MONO_TYPESPEC_SIZE];
3259 for (i = 0; i < table->rows; ++i) {
3260 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3262 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3263 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3268 verify_typespec_table_full (VerifyContext *ctx)
3270 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3271 guint32 data [MONO_TYPESPEC_SIZE];
3274 for (i = 0; i < table->rows; ++i) {
3275 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3276 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3277 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3278 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3283 #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))
3285 verify_implmap_table (VerifyContext *ctx)
3287 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3288 guint32 data [MONO_IMPLMAP_SIZE], cconv;
3291 for (i = 0; i < table->rows; ++i) {
3292 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3294 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3295 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3297 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3298 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3299 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3301 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3302 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3304 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3305 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3307 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3308 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3310 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3311 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3313 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows)
3314 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3319 verify_fieldrva_table (VerifyContext *ctx)
3321 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3322 guint32 data [MONO_FIELD_RVA_SIZE];
3325 for (i = 0; i < table->rows; ++i) {
3326 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3328 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3329 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3331 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3332 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3336 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 8) | (1 << 14) | (1 << 15))
3338 verify_assembly_table (VerifyContext *ctx)
3340 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3341 guint32 data [MONO_ASSEMBLY_SIZE], hash;
3344 if (table->rows > 1)
3345 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3347 for (i = 0; i < table->rows; ++i) {
3348 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3350 hash = data [MONO_ASSEMBLY_HASH_ALG];
3351 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3352 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3354 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3355 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3357 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3358 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3360 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3361 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3363 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3364 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3368 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
3370 verify_assemblyref_table (VerifyContext *ctx)
3372 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3373 guint32 data [MONO_ASSEMBLYREF_SIZE];
3376 for (i = 0; i < table->rows; ++i) {
3377 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3379 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3380 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3382 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3383 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3385 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3386 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3388 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3389 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3391 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3392 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3396 #define INVALID_FILE_FLAGS_BITS ~(1)
3398 verify_file_table (VerifyContext *ctx)
3400 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3401 guint32 data [MONO_FILE_SIZE];
3404 for (i = 0; i < table->rows; ++i) {
3405 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3407 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3408 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3410 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3411 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3413 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3414 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3418 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3420 verify_exportedtype_table (VerifyContext *ctx)
3422 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3423 guint32 data [MONO_EXP_TYPE_SIZE];
3426 for (i = 0; i < table->rows; ++i) {
3427 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3429 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3430 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3432 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3433 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3435 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3436 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3438 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3439 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3441 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3442 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3444 /*nested type can't have a namespace*/
3445 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3446 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3450 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3452 verify_manifest_resource_table (VerifyContext *ctx)
3454 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3455 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3456 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3457 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3460 resources_size = ch->ch_resources.size;
3462 for (i = 0; i < table->rows; ++i) {
3463 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3465 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3466 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3468 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3469 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3471 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3472 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3474 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3475 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3477 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3478 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3480 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3481 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])));
3483 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3484 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3486 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3487 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3492 verify_nested_class_table (VerifyContext *ctx)
3494 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3495 guint32 data [MONO_NESTED_CLASS_SIZE];
3498 for (i = 0; i < table->rows; ++i) {
3499 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3501 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3502 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3503 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3504 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3505 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3506 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3510 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3512 verify_generic_param_table (VerifyContext *ctx)
3514 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3515 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3516 int i, param_number = 0;
3518 for (i = 0; i < table->rows; ++i) {
3519 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3521 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3522 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3524 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3525 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3527 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3528 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3530 token = data [MONO_GENERICPARAM_OWNER];
3532 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3533 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3535 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3536 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3538 if (token != last_token) {
3543 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3544 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));
3551 verify_method_spec_table (VerifyContext *ctx)
3553 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3554 guint32 data [MONO_METHODSPEC_SIZE];
3557 for (i = 0; i < table->rows; ++i) {
3558 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3560 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3561 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3563 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3564 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3566 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3567 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3572 verify_method_spec_table_full (VerifyContext *ctx)
3574 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3575 guint32 data [MONO_METHODSPEC_SIZE];
3578 for (i = 0; i < table->rows; ++i) {
3579 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3581 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3582 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3587 verify_generic_param_constraint_table (VerifyContext *ctx)
3589 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3590 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3593 for (i = 0; i < table->rows; ++i) {
3594 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3596 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3597 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_TABLE_GENERICPARAM]));
3599 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3600 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3602 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3603 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3610 const char *name_space;
3611 guint32 resolution_scope;
3615 typedef_hash (gconstpointer _key)
3617 const TypeDefUniqueId *key = _key;
3618 return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3622 typedef_equals (gconstpointer _a, gconstpointer _b)
3624 const TypeDefUniqueId *a = _a;
3625 const TypeDefUniqueId *b = _b;
3626 return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3630 verify_typedef_table_global_constraints (VerifyContext *ctx)
3633 guint32 data [MONO_TYPEDEF_SIZE];
3634 guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3635 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3636 MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3637 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3639 for (i = 0; i < table->rows; ++i) {
3641 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3642 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3644 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3645 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3646 type->resolution_scope = 0;
3648 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3649 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3650 int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3651 g_assert (res >= 0);
3653 mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3654 type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3657 if (g_hash_table_lookup (unique_types, type)) {
3658 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));
3659 g_hash_table_destroy (unique_types);
3663 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3666 g_hash_table_destroy (unique_types);
3670 verify_typeref_table_global_constraints (VerifyContext *ctx)
3673 guint32 data [MONO_TYPEREF_SIZE];
3674 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3675 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3677 for (i = 0; i < table->rows; ++i) {
3678 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3679 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3681 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3682 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3683 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3685 if (g_hash_table_lookup (unique_types, type)) {
3686 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));
3687 g_hash_table_destroy (unique_types);
3691 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3694 g_hash_table_destroy (unique_types);
3698 verify_tables_data_global_constraints (VerifyContext *ctx)
3700 verify_typedef_table_global_constraints (ctx);
3704 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3706 verify_typeref_table (ctx);
3707 verify_typeref_table_global_constraints (ctx);
3711 verify_tables_data (VerifyContext *ctx)
3713 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3714 guint32 size = 0, tables_offset;
3717 for (i = 0; i < 0x2D; ++i) {
3718 MonoTableInfo *table = &ctx->image->tables [i];
3720 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3721 if (tmp_size < size) {
3729 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3731 tables_offset = ctx->image->tables_base - ctx->data;
3732 if (!bounds_check_offset (&tables_area, tables_offset, size))
3733 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)));
3735 verify_module_table (ctx);
3737 /*Obfuscators love to place broken stuff in the typeref table
3738 verify_typeref_table (ctx);
3740 verify_typedef_table (ctx);
3742 verify_field_table (ctx);
3744 verify_method_table (ctx);
3746 verify_param_table (ctx);
3748 verify_interfaceimpl_table (ctx);
3750 verify_memberref_table (ctx);
3752 verify_constant_table (ctx);
3754 verify_cattr_table (ctx);
3756 verify_field_marshal_table (ctx);
3758 verify_decl_security_table (ctx);
3760 verify_class_layout_table (ctx);
3762 verify_field_layout_table (ctx);
3764 verify_standalonesig_table (ctx);
3766 verify_eventmap_table (ctx);
3768 verify_event_table (ctx);
3770 verify_propertymap_table (ctx);
3772 verify_property_table (ctx);
3774 verify_methodimpl_table (ctx);
3776 verify_moduleref_table (ctx);
3778 verify_typespec_table (ctx);
3780 verify_implmap_table (ctx);
3782 verify_fieldrva_table (ctx);
3784 verify_assembly_table (ctx);
3786 verify_assemblyref_table (ctx);
3788 verify_file_table (ctx);
3790 verify_exportedtype_table (ctx);
3792 verify_manifest_resource_table (ctx);
3794 verify_nested_class_table (ctx);
3796 verify_generic_param_table (ctx);
3798 verify_method_spec_table (ctx);
3800 verify_generic_param_constraint_table (ctx);
3802 verify_tables_data_global_constraints (ctx);
3806 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3808 memset (ctx, 0, sizeof (VerifyContext));
3810 ctx->report_error = report_error;
3811 ctx->report_warning = FALSE; //export this setting in the API
3813 ctx->size = image->raw_data_len;
3814 ctx->data = image->raw_data;
3818 cleanup_context (VerifyContext *ctx, GSList **error_list)
3820 g_free (ctx->sections);
3822 *error_list = ctx->errors;
3824 mono_free_verify_list (ctx->errors);
3829 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3831 g_free (ctx->sections);
3833 MonoVerifyInfo *info = ctx->errors->data;
3834 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3835 mono_free_verify_list (ctx->errors);
3841 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3845 if (!mono_verifier_is_enabled_for_image (image))
3848 init_verify_context (&ctx, image, error_list != NULL);
3849 ctx.stage = STAGE_PE;
3851 verify_msdos_header (&ctx);
3853 verify_pe_header (&ctx);
3855 verify_pe_optional_header (&ctx);
3857 load_section_table (&ctx);
3859 load_data_directories (&ctx);
3861 verify_import_table (&ctx);
3863 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3864 verify_resources_table (&ctx);
3867 return cleanup_context (&ctx, error_list);
3871 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3875 if (!mono_verifier_is_enabled_for_image (image))
3878 init_verify_context (&ctx, image, error_list != NULL);
3879 ctx.stage = STAGE_CLI;
3881 verify_cli_header (&ctx);
3883 verify_metadata_header (&ctx);
3885 verify_tables_schema (&ctx);
3888 return cleanup_context (&ctx, error_list);
3893 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3894 * Other verification checks are meant to be done lazily by the runtime. Those include:
3895 * blob items (signatures, method headers, custom attributes, etc)
3896 * type semantics related
3898 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3900 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3901 * operation still need more checking.
3904 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3908 if (!mono_verifier_is_enabled_for_image (image))
3911 init_verify_context (&ctx, image, error_list != NULL);
3912 ctx.stage = STAGE_TABLES;
3914 verify_tables_data (&ctx);
3916 return cleanup_context (&ctx, error_list);
3921 * Verifies all other constraints.
3924 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3928 if (!mono_verifier_is_enabled_for_image (image))
3931 init_verify_context (&ctx, image, error_list != NULL);
3932 ctx.stage = STAGE_TABLES;
3934 verify_typedef_table_full (&ctx);
3936 verify_field_table_full (&ctx);
3938 verify_method_table_full (&ctx);
3940 verify_memberref_table_full (&ctx);
3942 verify_cattr_table_full (&ctx);
3944 verify_field_marshal_table_full (&ctx);
3946 verify_decl_security_table_full (&ctx);
3948 verify_standalonesig_table_full (&ctx);
3950 verify_event_table_full (&ctx);
3952 verify_typespec_table_full (&ctx);
3954 verify_method_spec_table_full (&ctx);
3956 verify_tables_data_global_constraints_full (&ctx);
3959 return cleanup_context (&ctx, error_list);
3963 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3967 if (!mono_verifier_is_enabled_for_image (image))
3970 init_verify_context (&ctx, image, error_list != NULL);
3971 ctx.stage = STAGE_TABLES;
3973 is_valid_field_signature (&ctx, offset);
3974 return cleanup_context (&ctx, error_list);
3978 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3981 guint32 locals_token;
3983 if (!mono_verifier_is_enabled_for_image (image))
3986 init_verify_context (&ctx, image, error_list != NULL);
3987 ctx.stage = STAGE_TABLES;
3989 is_valid_method_header (&ctx, offset, &locals_token);
3991 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
3992 is_valid_standalonesig_blob (&ctx, sig_offset);
3995 return cleanup_context (&ctx, error_list);
3999 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4003 mono_error_init (error);
4005 if (!mono_verifier_is_enabled_for_image (image))
4008 init_verify_context (&ctx, image, TRUE);
4009 ctx.stage = STAGE_TABLES;
4011 is_valid_method_signature (&ctx, offset);
4012 /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4013 return cleanup_context_checked (&ctx, error);
4017 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
4021 if (!mono_verifier_is_enabled_for_image (image))
4024 init_verify_context (&ctx, image, error_list != NULL);
4025 ctx.stage = STAGE_TABLES;
4027 is_valid_method_or_field_signature (&ctx, offset);
4028 return cleanup_context (&ctx, error_list);
4032 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4036 if (!mono_verifier_is_enabled_for_image (image))
4039 init_verify_context (&ctx, image, error_list != NULL);
4040 ctx.stage = STAGE_TABLES;
4042 is_valid_standalonesig_blob (&ctx, offset);
4043 return cleanup_context (&ctx, error_list);
4047 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4051 if (!mono_verifier_is_enabled_for_image (image))
4054 init_verify_context (&ctx, image, error_list != NULL);
4055 ctx.stage = STAGE_TABLES;
4058 is_valid_typespec_blob (&ctx, offset);
4059 return cleanup_context (&ctx, error_list);
4063 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4067 if (!mono_verifier_is_enabled_for_image (image))
4070 init_verify_context (&ctx, image, error_list != NULL);
4071 ctx.stage = STAGE_TABLES;
4073 is_valid_methodspec_blob (&ctx, offset);
4074 return cleanup_context (&ctx, error_list);
4078 verify_user_string (VerifyContext *ctx, guint32 offset)
4080 OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4081 guint32 entry_size, bytes;
4083 if (heap_us.size < offset)
4084 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4086 if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4087 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4089 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4090 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4092 entry_size += bytes;
4094 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4095 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4099 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4103 if (!mono_verifier_is_enabled_for_image (image))
4106 init_verify_context (&ctx, image, error_list != NULL);
4107 ctx.stage = STAGE_TABLES;
4109 verify_user_string (&ctx, offset);
4111 return cleanup_context (&ctx, error_list);
4115 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4119 if (!mono_verifier_is_enabled_for_image (image))
4122 init_verify_context (&ctx, image, error_list != NULL);
4123 ctx.stage = STAGE_TABLES;
4125 is_valid_cattr_blob (&ctx, offset);
4127 return cleanup_context (&ctx, error_list);
4131 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4135 if (!mono_verifier_is_enabled_for_image (image))
4138 init_verify_context (&ctx, image, error_list != NULL);
4139 ctx.stage = STAGE_TABLES;
4141 is_valid_cattr_content (&ctx, ctor, (const char*)data, size);
4143 return cleanup_context (&ctx, error_list);
4147 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4149 MonoMethodSignature *original_sig;
4150 if (!mono_verifier_is_enabled_for_image (image))
4153 original_sig = mono_method_signature (method);
4154 if (original_sig->call_convention == MONO_CALL_VARARG) {
4155 if (original_sig->hasthis != signature->hasthis)
4157 if (original_sig->call_convention != signature->call_convention)
4159 if (original_sig->explicit_this != signature->explicit_this)
4161 if (original_sig->call_convention != signature->call_convention)
4163 if (original_sig->pinvoke != signature->pinvoke)
4165 if (original_sig->sentinelpos != signature->sentinelpos)
4167 } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4175 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4177 MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
4178 guint32 data [MONO_TYPEREF_SIZE];
4180 mono_error_init (error);
4182 if (!mono_verifier_is_enabled_for_image (image))
4185 if (row >= table->rows) {
4186 mono_error_set_bad_image (error, image, "Invalid typeref row %d - table has %d rows", row, table->rows);
4190 mono_metadata_decode_row (table, row, data, MONO_TYPEREF_SIZE);
4191 if (!is_valid_coded_index_with_image (image, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4192 mono_error_set_bad_image (error, image, "Invalid typeref row %d coded index 0x%08x", row, data [MONO_TYPEREF_SCOPE]);
4196 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4197 mono_error_set_bad_image (error, image, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row);
4201 if (!data [MONO_TYPEREF_NAME] || !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAME], FALSE)) {
4202 mono_error_set_bad_image (error, image, "Invalid typeref row %d name token 0x%08x", row, data [MONO_TYPEREF_NAME]);
4206 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAMESPACE], FALSE)) {
4207 mono_error_set_bad_image (error, image, "Invalid typeref row %d namespace token 0x%08x", row, data [MONO_TYPEREF_NAMESPACE]);
4216 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4222 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4228 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4234 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4240 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4246 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4252 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4254 mono_error_init (error);
4259 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
4265 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4271 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4277 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4283 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4289 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4295 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4301 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4308 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4310 mono_error_init (error);
4313 #endif /* DISABLE_VERIFIER */