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_custom_mods (ctx, &ptr, end))
1307 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1309 if (!parse_type (ctx, &ptr, end))
1310 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1317 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1319 const char *ptr = *_ptr;
1323 if (!safe_read8 (type, ptr, end))
1324 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1326 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1327 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1328 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1329 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1330 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1334 if (!parse_custom_mods (ctx, &ptr, end))
1335 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1337 if (!safe_read8 (type, ptr, end))
1338 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1340 if (type != MONO_TYPE_VOID) {
1342 if (!parse_type (ctx, &ptr, end))
1343 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1347 case MONO_TYPE_VALUETYPE:
1348 case MONO_TYPE_CLASS:
1349 if (!safe_read_cint (token, ptr, end))
1350 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1352 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1353 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1355 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1356 FAIL (ctx, g_strdup_printf ("Type: zero TypeDefOrRef token %x", token));
1358 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1359 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1360 FAIL (ctx, g_strdup_printf ("Type: Recursive type specification (%x). A type signature can't reference itself", ctx->token));
1365 case MONO_TYPE_MVAR:
1366 if (!safe_read_cint (token, ptr, end))
1367 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1370 case MONO_TYPE_ARRAY:
1371 if (!parse_type (ctx, &ptr, end))
1372 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1373 if (!parse_array_shape (ctx, &ptr, end))
1374 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1377 case MONO_TYPE_GENERICINST:
1378 if (!parse_generic_inst (ctx, &ptr, end))
1379 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1382 case MONO_TYPE_FNPTR:
1383 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1384 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1387 case MONO_TYPE_SZARRAY:
1388 if (!parse_custom_mods (ctx, &ptr, end))
1389 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1390 if (!parse_type (ctx, &ptr, end))
1391 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1399 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1404 if (!parse_custom_mods (ctx, _ptr, end))
1408 if (!safe_read8 (type, ptr, end))
1409 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1411 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1416 //it's a byref, update the cursor ptr
1417 if (type == MONO_TYPE_BYREF)
1420 return parse_type (ctx, _ptr, end);
1424 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1429 if (!parse_custom_mods (ctx, _ptr, end))
1433 if (!safe_read8 (type, ptr, end))
1434 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1436 if (type == MONO_TYPE_TYPEDBYREF) {
1441 //it's a byref, update the cursor ptr
1442 if (type == MONO_TYPE_BYREF) {
1444 if (!parse_custom_mods (ctx, _ptr, end))
1448 return parse_type (ctx, _ptr, end);
1452 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1455 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1456 const char *ptr = *_ptr;
1457 gboolean saw_sentinel = FALSE;
1459 if (!safe_read8 (cconv, ptr, end))
1460 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1463 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1465 if (allow_unmanaged) {
1466 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1467 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1468 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1469 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1471 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1472 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1474 if ((cconv & 0x10) && gparam_count == 0)
1475 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1477 if (allow_unmanaged && (cconv & 0x10))
1478 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1480 if (!safe_read_cint (param_count, ptr, end))
1481 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1483 if (!parse_return_type (ctx, &ptr, end))
1484 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1486 for (i = 0; i < param_count; ++i) {
1487 if (allow_sentinel) {
1488 if (!safe_read8 (type, ptr, end))
1489 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1491 if (type == MONO_TYPE_SENTINEL) {
1492 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1493 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1496 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1498 saw_sentinel = TRUE;
1504 if (!parse_param (ctx, &ptr, end))
1505 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1513 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1516 unsigned param_count = 0, i;
1517 const char *ptr = *_ptr;
1519 if (!safe_read8 (sig, ptr, end))
1520 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1522 if (sig != 0x08 && sig != 0x28)
1523 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1525 if (!safe_read_cint (param_count, ptr, end))
1526 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1528 if (!parse_custom_mods (ctx, &ptr, end))
1531 if (!parse_type (ctx, &ptr, end))
1532 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1534 for (i = 0; i < param_count; ++i) {
1535 if (!parse_custom_mods (ctx, &ptr, end))
1536 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1537 if (!parse_type (ctx, &ptr, end))
1538 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1546 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1548 const char *ptr = *_ptr;
1549 unsigned signature = 0;
1551 if (!safe_read8 (signature, ptr, end))
1552 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1554 if (signature != 0x06)
1555 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1557 if (!parse_custom_mods (ctx, &ptr, end))
1560 if (safe_read8 (signature, ptr, end)) {
1561 if (signature != MONO_TYPE_BYREF)
1566 return parse_type (ctx, _ptr, end);
1570 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1573 unsigned locals_count = 0, i;
1574 const char *ptr = *_ptr;
1576 if (!safe_read8 (sig, ptr, end))
1577 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1580 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1582 if (!safe_read_cint (locals_count, ptr, end))
1583 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1585 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1586 if (locals_count == 0)
1587 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1590 for (i = 0; i < locals_count; ++i) {
1591 if (!safe_read8 (sig, ptr, end))
1592 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1594 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1595 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1596 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1597 if (!safe_read8 (sig, ptr, end))
1598 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1601 if (sig == MONO_TYPE_BYREF) {
1602 if (!safe_read8 (sig, ptr, end))
1603 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1604 if (sig == MONO_TYPE_TYPEDBYREF)
1605 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1608 if (sig == MONO_TYPE_TYPEDBYREF)
1613 if (!parse_type (ctx, &ptr, end))
1614 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1622 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1625 unsigned signature = 0;
1626 const char *ptr = NULL, *end;
1628 if (!decode_signature_header (ctx, offset, &size, &ptr))
1629 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1632 if (!safe_read8 (signature, ptr, end))
1633 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1636 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1639 return parse_field (ctx, &ptr, end);
1643 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1646 const char *ptr = NULL, *end;
1648 if (!decode_signature_header (ctx, offset, &size, &ptr))
1649 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1652 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1656 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1659 unsigned signature = 0;
1660 const char *ptr = NULL, *end;
1662 if (!decode_signature_header (ctx, offset, &size, &ptr))
1663 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1666 if (!safe_read8 (signature, ptr, end))
1667 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1670 if (signature == 0x06)
1671 return parse_field (ctx, &ptr, end);
1673 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1677 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1680 unsigned prolog = 0;
1681 const char *ptr = NULL, *end;
1686 if (!decode_signature_header (ctx, offset, &size, &ptr))
1687 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1690 if (!safe_read16 (prolog, ptr, end))
1691 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1694 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1700 is_valid_cattr_type (MonoType *type)
1704 if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1707 if (type->type == MONO_TYPE_VALUETYPE) {
1708 klass = mono_class_from_mono_type (type);
1709 return klass && klass->enumtype;
1712 if (type->type == MONO_TYPE_CLASS)
1713 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1719 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1722 const char *ptr = *_ptr;
1728 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1731 if (*ptr == (char)0xFF) {
1736 if (!safe_read_cint (size, ptr, end))
1737 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1739 if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1740 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1750 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1752 const char *dummy_str;
1754 return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1758 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1762 const char *str_start = NULL;
1763 const char *ptr = *_ptr;
1765 guint32 str_len = 0;
1767 if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1770 /*NULL or empty string*/
1771 if (str_start == NULL || str_len == 0) {
1772 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1776 enum_name = g_memdup (str_start, str_len + 1);
1777 enum_name [str_len] = 0;
1778 type = mono_reflection_type_from_name (enum_name, ctx->image);
1780 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1786 klass = mono_class_from_mono_type (type);
1787 if (!klass || !klass->enumtype) {
1788 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1797 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1800 const char *ptr = *_ptr;
1802 guint32 element_count, i;
1805 klass = mono_type->data.klass;
1806 type = mono_type->type;
1810 case MONO_TYPE_BOOLEAN:
1817 case MONO_TYPE_CHAR:
1831 case MONO_TYPE_STRING:
1833 return is_valid_ser_string (ctx, _ptr, end);
1835 case MONO_TYPE_OBJECT: {
1836 unsigned sub_type = 0;
1837 if (!safe_read8 (sub_type, ptr, end))
1838 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1840 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1844 if (sub_type == MONO_TYPE_ENUM) {
1845 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1849 klass = klass->element_class;
1850 type = klass->byval_arg.type;
1853 if (sub_type == 0x50) { /*Type*/
1855 return is_valid_ser_string (ctx, _ptr, end);
1857 if (sub_type == MONO_TYPE_SZARRAY) {
1858 MonoType simple_type = {{0}};
1860 if (!safe_read8 (etype, ptr, end))
1861 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1863 if (etype == MONO_TYPE_ENUM) {
1864 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1867 } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
1868 klass = mono_defaults.systemtype_class;
1869 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1870 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
1871 klass = mono_class_from_mono_type (&simple_type);
1873 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1875 type = MONO_TYPE_SZARRAY;
1878 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1882 case MONO_TYPE_CLASS:
1883 if (klass != mono_defaults.systemtype_class)
1884 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1886 return is_valid_ser_string (ctx, _ptr, end);
1888 case MONO_TYPE_VALUETYPE:
1889 if (!klass || !klass->enumtype)
1890 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1892 klass = klass->element_class;
1893 type = klass->byval_arg.type;
1896 case MONO_TYPE_SZARRAY:
1897 mono_type = &klass->byval_arg;
1898 if (!is_valid_cattr_type (mono_type))
1899 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1900 if (!safe_read32 (element_count, ptr, end))
1901 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1902 if (element_count == 0xFFFFFFFFu) {
1906 for (i = 0; i < element_count; ++i) {
1907 if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1913 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1916 if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1917 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1918 *_ptr = ptr + elem_size;
1923 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1926 unsigned prolog = 0;
1928 MonoMethodSignature *sig;
1933 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1935 sig = mono_method_signature_checked (ctor, &error);
1936 if (!mono_error_ok (&error)) {
1937 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1938 mono_error_cleanup (&error);
1942 if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1943 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1947 if (!safe_read16 (prolog, ptr, end))
1948 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1951 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1953 args = sig->param_count;
1954 for (i = 0; i < args; ++i) {
1955 MonoType *arg_type = sig->params [i];
1956 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1960 if (!safe_read16 (num_named, ptr, end))
1961 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1963 for (i = 0; i < num_named; ++i) {
1964 MonoType *type, simple_type = {{0}};
1967 if (!safe_read8 (kind, ptr, end))
1968 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1969 if (kind != 0x53 && kind != 0x54)
1970 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1971 if (!safe_read8 (kind, ptr, end))
1972 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1974 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1975 simple_type.type = kind;
1976 type = &simple_type;
1977 } else if (kind == MONO_TYPE_ENUM) {
1978 MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1981 type = &klass->byval_arg;
1982 } else if (kind == 0x50) {
1983 type = &mono_defaults.systemtype_class->byval_arg;
1984 } else if (kind == 0x51) {
1985 type = &mono_defaults.object_class->byval_arg;
1986 } else if (kind == MONO_TYPE_SZARRAY) {
1989 if (!safe_read8 (etype, ptr, end))
1990 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1992 if (etype == MONO_TYPE_ENUM) {
1993 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1996 } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
1997 klass = mono_defaults.systemtype_class;
1998 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1999 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
2000 klass = mono_class_from_mono_type (&simple_type);
2002 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
2004 type = &mono_array_class_get (klass, 1)->byval_arg;
2006 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
2009 if (!is_valid_ser_string (ctx, &ptr, end))
2012 if (!is_valid_fixed_param (ctx, type, &ptr, end))
2021 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
2023 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2024 //TODO do proper verification
2025 return blob.size >= 1 && blob.size - 1 >= offset;
2029 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
2031 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2032 //TODO do proper verification
2033 return blob.size >= 1 && blob.size - 1 >= offset;
2037 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2040 unsigned signature = 0;
2041 const char *ptr = NULL, *end;
2043 if (!decode_signature_header (ctx, offset, &size, &ptr))
2044 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2047 if (!safe_read8 (signature, ptr, end))
2048 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2051 if (signature == 0x07)
2052 return parse_locals_signature (ctx, &ptr, end);
2054 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2055 if (signature == 0x06)
2056 return parse_field (ctx, &ptr, end);
2058 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2062 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2065 const char *ptr = NULL, *end;
2067 if (!decode_signature_header (ctx, offset, &size, &ptr))
2068 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2071 return parse_property_signature (ctx, &ptr, end);
2075 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2078 const char *ptr = NULL, *end;
2081 if (!decode_signature_header (ctx, offset, &size, &ptr))
2082 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2085 if (!parse_custom_mods (ctx, &ptr, end))
2088 if (!safe_read8 (type, ptr, end))
2089 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2091 if (type == MONO_TYPE_BYREF) {
2092 if (!safe_read8 (type, ptr, end))
2093 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2094 if (type == MONO_TYPE_TYPEDBYREF)
2095 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2098 if (type == MONO_TYPE_TYPEDBYREF)
2102 return parse_type (ctx, &ptr, end);
2106 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2109 const char *ptr = NULL, *end;
2111 unsigned count = 0, i;
2113 if (!decode_signature_header (ctx, offset, &size, &ptr))
2114 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2117 if (!safe_read8 (type, ptr, end))
2118 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2121 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2123 if (!safe_read_cint (count, ptr, end))
2124 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2127 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2129 for (i = 0; i < count; ++i) {
2130 if (!parse_custom_mods (ctx, &ptr, end))
2132 if (!parse_type (ctx, &ptr, end))
2133 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2139 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2141 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2142 guint32 entry_size, bytes;
2144 if (blob.size < offset)
2147 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2150 if (entry_size < minsize)
2153 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2155 entry_size += bytes;
2157 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2161 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2163 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2164 guint32 size, entry_size, bytes;
2166 if (blob.size < offset)
2167 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2169 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2170 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2172 if (type == MONO_TYPE_STRING) {
2173 //String is encoded as: compressed_int:len len *bytes
2176 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2177 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
2183 case MONO_TYPE_BOOLEAN:
2188 case MONO_TYPE_CHAR:
2196 case MONO_TYPE_CLASS:
2206 g_assert_not_reached ();
2209 if (size != entry_size)
2210 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2214 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2215 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2217 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2218 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2222 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2223 //only 0x01, 0x40 and 0x80 are allowed
2224 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2227 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2229 unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2230 unsigned header = 0;
2231 unsigned fat_header = 0, size = 0, max_stack;
2232 const char *ptr = NULL, *end;
2236 if (offset == INVALID_ADDRESS)
2237 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2239 ptr = ctx->data + offset;
2240 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2242 if (!safe_read8 (header, ptr, end))
2243 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2245 switch (header & 0x3) {
2248 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2251 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
2252 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2257 if (!safe_read16 (fat_header, ptr, end))
2258 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2260 size = (fat_header >> 12) & 0xF;
2262 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2264 if (!safe_read16 (max_stack, ptr, end))
2265 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2267 if (!safe_read32 (code_size, ptr, end))
2268 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2270 if (!safe_read32 (local_vars_tok, ptr, end))
2271 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2273 if (local_vars_tok) {
2274 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2275 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2276 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
2277 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2278 if (!(local_vars_tok & 0xFFFFFF))
2279 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature with zero index"));
2280 *locals_token = local_vars_tok & 0xFFFFFF;
2283 if (fat_header & FAT_HEADER_INVALID_FLAGS)
2284 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2286 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2287 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2289 if (!(fat_header & 0x08))
2295 unsigned section_header = 0, section_size = 0;
2298 ptr = dword_align (ptr);
2299 if (!safe_read32 (section_header, ptr, end))
2300 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2302 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2303 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2305 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2306 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2308 if (section_size < 4)
2309 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2311 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2312 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2314 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2315 guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2317 LAMEIMPL: MS emits section_size without accounting for header size.
2318 Mono does as the spec says. section_size is header + section
2319 MS's peverify happily accepts both.
2321 if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2322 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)));
2324 /* only verify the class token is verified as the rest is done by the IL verifier*/
2325 for (i = 0; i < clauses; ++i) {
2326 unsigned flags = *(unsigned char*)ptr;
2327 unsigned class_token = 0;
2328 ptr += (is_fat ? 20 : 8);
2329 if (!safe_read32 (class_token, ptr, end))
2330 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2331 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2332 guint table = mono_metadata_token_table (class_token);
2333 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2334 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2335 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2336 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2341 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2348 verify_module_table (VerifyContext *ctx)
2350 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2351 guint32 data [MONO_MODULE_SIZE];
2353 if (table->rows != 1)
2354 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2356 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2358 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2359 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2361 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2362 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2364 if (data [MONO_MODULE_ENC] != 0)
2365 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2367 if (data [MONO_MODULE_ENCBASE] != 0)
2368 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2372 verify_typeref_table (VerifyContext *ctx)
2374 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2378 for (i = 0; i < table->rows; ++i) {
2379 mono_verifier_verify_typeref_row (ctx->image, i, &error);
2380 add_from_mono_error (ctx, &error);
2384 /*bits 9,11,14,15,19,21,24-31 */
2385 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2387 verify_typedef_table (VerifyContext *ctx)
2389 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2390 guint32 data [MONO_TYPEDEF_SIZE];
2391 guint32 fieldlist = 1, methodlist = 1, visibility;
2394 if (table->rows == 0)
2395 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2397 for (i = 0; i < table->rows; ++i) {
2398 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2399 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2400 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2402 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2403 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2405 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2406 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2408 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2409 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2411 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2412 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2414 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2415 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2417 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2418 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2420 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2421 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2423 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2424 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2425 search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2426 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2428 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2429 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2431 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2432 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2434 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2435 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));
2437 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2438 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2440 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2441 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2443 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2444 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));
2446 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2447 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2452 verify_typedef_table_full (VerifyContext *ctx)
2454 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2455 guint32 data [MONO_TYPEDEF_SIZE];
2458 if (table->rows == 0)
2459 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2461 for (i = 0; i < table->rows; ++i) {
2462 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2465 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2466 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2467 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2472 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2473 if (data [MONO_TYPEDEF_EXTENDS])
2474 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2476 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2477 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2481 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2484 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2492 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2494 verify_field_table (VerifyContext *ctx)
2496 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2497 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2500 module_field_list = (guint32)-1;
2501 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2502 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2503 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2506 for (i = 0; i < table->rows; ++i) {
2507 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2508 flags = data [MONO_FIELD_FLAGS];
2510 if (flags & INVALID_FIELD_FLAG_BITS)
2511 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2513 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2514 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2516 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2517 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2519 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2520 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2522 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2523 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2525 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2526 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2527 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2529 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2530 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2531 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2533 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2534 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2535 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2537 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2538 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2539 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2541 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2542 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2544 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2545 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2547 //TODO verify contant flag
2549 if (i + 1 < module_field_list) {
2550 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2551 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2552 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2553 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2554 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2560 verify_field_table_full (VerifyContext *ctx)
2562 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2563 guint32 data [MONO_FIELD_SIZE];
2566 for (i = 0; i < table->rows; ++i) {
2567 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2569 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2570 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2574 /*bits 8,9,10,11,13,14,15*/
2575 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2577 verify_method_table (VerifyContext *ctx)
2579 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2580 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2581 guint32 paramlist = 1;
2582 gboolean is_ctor, is_cctor;
2586 module_method_list = (guint32)-1;
2587 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2588 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2589 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2592 for (i = 0; i < table->rows; ++i) {
2593 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2594 rva = data [MONO_METHOD_RVA];
2595 implflags = data [MONO_METHOD_IMPLFLAGS];
2596 flags = data [MONO_METHOD_FLAGS];
2597 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2598 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2601 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2602 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2605 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2607 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2608 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2610 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2611 is_ctor = !strcmp (".ctor", name);
2612 is_cctor = !strcmp (".cctor", name);
2614 if ((is_ctor || is_cctor) &&
2615 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2616 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2618 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2619 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2621 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2622 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2623 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2624 if (flags & METHOD_ATTRIBUTE_FINAL)
2625 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2626 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2627 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2630 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2631 ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2633 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2634 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2636 //XXX no checks against cas stuff 10,11,12,13)
2638 //TODO check iface with .ctor (15,16)
2640 if (i + 1 < module_method_list) {
2641 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2642 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2643 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2644 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2645 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2646 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2649 //TODO check valuetype for synchronized
2651 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2652 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2654 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2655 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2656 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2657 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2658 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2661 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2662 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2663 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2665 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2666 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2668 //TODO check signature contents
2671 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2672 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2673 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2674 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2676 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2677 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2680 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2682 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2683 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2684 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2686 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2687 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2689 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2690 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2692 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2693 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2695 if (data [MONO_METHOD_PARAMLIST] == 0)
2696 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2698 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2699 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));
2701 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2702 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2704 paramlist = data [MONO_METHOD_PARAMLIST];
2710 verify_method_table_full (VerifyContext *ctx)
2712 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2713 guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2716 for (i = 0; i < table->rows; ++i) {
2717 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2718 rva = data [MONO_METHOD_RVA];
2720 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2721 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2723 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2724 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2729 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2731 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2732 guint32 row = *current_method;
2733 guint32 paramlist, tmp;
2736 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2737 while (row < table->rows) {
2738 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2739 if (tmp > paramlist) {
2740 *current_method = row;
2741 return tmp - paramlist;
2746 /*no more methods, all params apply to the last one*/
2747 *current_method = table->rows;
2752 #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))
2754 verify_param_table (VerifyContext *ctx)
2756 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2757 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2758 gboolean first_param = TRUE;
2761 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2762 if (table->rows > 0)
2763 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2767 remaining_params = get_next_param_count (ctx, ¤t_method);
2769 for (i = 0; i < table->rows; ++i) {
2770 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2771 flags = data [MONO_PARAM_FLAGS];
2773 if (flags & INVALID_PARAM_FLAGS_BITS)
2774 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2776 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2777 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2778 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2780 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2781 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2784 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)
2785 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2787 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2788 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2790 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2791 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2793 first_param = FALSE;
2794 sequence = data [MONO_PARAM_SEQUENCE];
2795 if (--remaining_params == 0) {
2796 remaining_params = get_next_param_count (ctx, ¤t_method);
2803 verify_interfaceimpl_table (VerifyContext *ctx)
2805 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2806 guint32 data [MONO_INTERFACEIMPL_SIZE];
2809 for (i = 0; i < table->rows; ++i) {
2810 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2811 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2812 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_INTERFACEIMPL_CLASS]));
2814 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2815 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2817 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2818 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2823 verify_memberref_table (VerifyContext *ctx)
2825 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2826 guint32 data [MONO_MEMBERREF_SIZE];
2829 for (i = 0; i < table->rows; ++i) {
2830 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2832 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2833 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2835 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2836 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2838 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2839 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2841 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2842 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2848 verify_memberref_table_full (VerifyContext *ctx)
2850 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2851 guint32 data [MONO_MEMBERREF_SIZE];
2854 for (i = 0; i < table->rows; ++i) {
2855 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2857 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2858 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2863 verify_constant_table (VerifyContext *ctx)
2865 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2866 guint32 data [MONO_CONSTANT_SIZE], type;
2869 for (i = 0; i < table->rows; ++i) {
2870 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2871 type = data [MONO_CONSTANT_TYPE];
2873 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2874 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2876 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2877 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2879 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2880 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2882 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2883 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2888 verify_cattr_table (VerifyContext *ctx)
2890 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2891 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2894 for (i = 0; i < table->rows; ++i) {
2895 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2897 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2898 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2900 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]) || !get_coded_index_token (CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2901 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Type field 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2903 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2904 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2909 verify_cattr_table_full (VerifyContext *ctx)
2911 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2914 guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2917 for (i = 0; i < table->rows; ++i) {
2918 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2920 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2921 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2923 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2924 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2925 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2926 mtoken |= MONO_TOKEN_METHOD_DEF;
2928 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2929 mtoken |= MONO_TOKEN_MEMBER_REF;
2932 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2935 ctor = mono_get_method (ctx->image, mtoken, NULL);
2937 /*This can't fail since this is checked in is_valid_cattr_blob*/
2938 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2940 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2941 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2946 verify_field_marshal_table (VerifyContext *ctx)
2948 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2949 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2952 for (i = 0; i < table->rows; ++i) {
2953 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2955 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2956 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2958 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2959 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2961 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2962 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2964 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2965 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2970 verify_field_marshal_table_full (VerifyContext *ctx)
2972 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2973 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2976 for (i = 0; i < table->rows; ++i) {
2977 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2979 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2980 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2985 verify_decl_security_table (VerifyContext *ctx)
2987 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2988 guint32 data [MONO_DECL_SECURITY_SIZE];
2991 for (i = 0; i < table->rows; ++i) {
2992 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2994 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2995 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2997 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2998 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
3000 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
3001 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
3006 verify_decl_security_table_full (VerifyContext *ctx)
3008 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3009 guint32 data [MONO_DECL_SECURITY_SIZE];
3012 for (i = 0; i < table->rows; ++i) {
3013 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3015 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
3016 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
3021 verify_class_layout_table (VerifyContext *ctx)
3023 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
3024 guint32 data [MONO_CLASS_LAYOUT_SIZE];
3027 for (i = 0; i < table->rows; ++i) {
3028 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
3030 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3031 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
3033 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3045 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3051 verify_field_layout_table (VerifyContext *ctx)
3053 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3054 guint32 data [MONO_FIELD_LAYOUT_SIZE];
3057 for (i = 0; i < table->rows; ++i) {
3058 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3060 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3061 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3066 verify_standalonesig_table (VerifyContext *ctx)
3068 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3069 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3072 for (i = 0; i < table->rows; ++i) {
3073 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3075 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3076 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3081 verify_standalonesig_table_full (VerifyContext *ctx)
3083 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3084 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3087 for (i = 0; i < table->rows; ++i) {
3088 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3090 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3091 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3096 verify_eventmap_table (VerifyContext *ctx)
3098 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3099 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3102 for (i = 0; i < table->rows; ++i) {
3103 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3105 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3106 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3108 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3109 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3111 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3115 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3117 verify_event_table (VerifyContext *ctx)
3119 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3120 guint32 data [MONO_EVENT_SIZE];
3123 for (i = 0; i < table->rows; ++i) {
3124 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3126 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3127 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3129 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3130 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3132 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3133 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3138 verify_event_table_full (VerifyContext *ctx)
3140 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3141 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3142 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3143 gboolean found_add, found_remove;
3146 for (i = 0; i < table->rows; ++i) {
3147 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3149 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3150 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3152 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3154 //first we move to the first row for this event
3156 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3160 //now move forward looking for AddOn and RemoveOn rows
3161 found_add = found_remove = FALSE;
3162 while (idx < sema_table->rows) {
3163 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3164 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3166 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3168 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3169 found_remove = TRUE;
3170 if (found_add && found_remove)
3176 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3178 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3183 verify_propertymap_table (VerifyContext *ctx)
3185 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3186 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3189 for (i = 0; i < table->rows; ++i) {
3190 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3192 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3193 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3195 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3196 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3198 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3202 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3204 verify_property_table (VerifyContext *ctx)
3206 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3207 guint32 data [MONO_PROPERTY_SIZE];
3210 for (i = 0; i < table->rows; ++i) {
3211 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3213 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3214 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3216 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3217 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3219 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3220 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3222 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3223 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3224 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3230 verify_methodimpl_table (VerifyContext *ctx)
3232 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3233 guint32 data [MONO_METHODIMPL_SIZE];
3236 for (i = 0; i < table->rows; ++i) {
3237 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3239 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3240 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3242 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3243 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3245 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3246 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3248 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3249 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3251 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3252 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3257 verify_moduleref_table (VerifyContext *ctx)
3259 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3260 guint32 data [MONO_MODULEREF_SIZE];
3263 for (i = 0; i < table->rows; ++i) {
3264 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3266 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3267 ADD_ERROR (ctx, g_strdup_printf ("Invalid ModuleRef row %d name field %08x", i, data [MONO_MODULEREF_NAME]));
3272 verify_typespec_table (VerifyContext *ctx)
3274 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3275 guint32 data [MONO_TYPESPEC_SIZE];
3278 for (i = 0; i < table->rows; ++i) {
3279 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3281 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3282 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3287 verify_typespec_table_full (VerifyContext *ctx)
3289 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3290 guint32 data [MONO_TYPESPEC_SIZE];
3293 for (i = 0; i < table->rows; ++i) {
3294 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3295 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3296 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3297 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3302 #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))
3304 verify_implmap_table (VerifyContext *ctx)
3306 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3307 guint32 data [MONO_IMPLMAP_SIZE], cconv;
3310 for (i = 0; i < table->rows; ++i) {
3311 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3313 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3314 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3316 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3317 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3318 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3320 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3321 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3323 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3324 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3326 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3327 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3329 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3330 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3332 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows)
3333 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3338 verify_fieldrva_table (VerifyContext *ctx)
3340 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3341 guint32 data [MONO_FIELD_RVA_SIZE];
3344 for (i = 0; i < table->rows; ++i) {
3345 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3347 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3348 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3350 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3351 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3355 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 8) | (1 << 14) | (1 << 15))
3357 verify_assembly_table (VerifyContext *ctx)
3359 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3360 guint32 data [MONO_ASSEMBLY_SIZE], hash;
3363 if (table->rows > 1)
3364 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3366 for (i = 0; i < table->rows; ++i) {
3367 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3369 hash = data [MONO_ASSEMBLY_HASH_ALG];
3370 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3371 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3373 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3374 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3376 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3377 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3379 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3380 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3382 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3383 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3387 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
3389 verify_assemblyref_table (VerifyContext *ctx)
3391 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3392 guint32 data [MONO_ASSEMBLYREF_SIZE];
3395 for (i = 0; i < table->rows; ++i) {
3396 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3398 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3399 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3401 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3402 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3404 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3405 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3407 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3408 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3410 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3411 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3415 #define INVALID_FILE_FLAGS_BITS ~(1)
3417 verify_file_table (VerifyContext *ctx)
3419 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3420 guint32 data [MONO_FILE_SIZE];
3423 for (i = 0; i < table->rows; ++i) {
3424 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3426 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3427 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3429 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3430 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3432 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3433 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3437 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3439 verify_exportedtype_table (VerifyContext *ctx)
3441 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3442 guint32 data [MONO_EXP_TYPE_SIZE];
3445 for (i = 0; i < table->rows; ++i) {
3446 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3448 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3449 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3451 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3452 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3454 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3455 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3457 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3458 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3460 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3461 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3463 /*nested type can't have a namespace*/
3464 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3465 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3469 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3471 verify_manifest_resource_table (VerifyContext *ctx)
3473 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3474 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3475 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3476 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3479 resources_size = ch->ch_resources.size;
3481 for (i = 0; i < table->rows; ++i) {
3482 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3484 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3485 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3487 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3488 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3490 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3491 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3493 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3494 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3496 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3497 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3499 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3500 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])));
3502 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3503 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3505 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3506 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3511 verify_nested_class_table (VerifyContext *ctx)
3513 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3514 guint32 data [MONO_NESTED_CLASS_SIZE];
3517 for (i = 0; i < table->rows; ++i) {
3518 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3520 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3521 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3522 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3523 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3524 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3525 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3529 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3531 verify_generic_param_table (VerifyContext *ctx)
3533 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3534 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3535 int i, param_number = 0;
3537 for (i = 0; i < table->rows; ++i) {
3538 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3540 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3541 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3543 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3544 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3546 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3547 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3549 token = data [MONO_GENERICPARAM_OWNER];
3551 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3552 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3554 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3555 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3557 if (token != last_token) {
3562 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3563 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));
3570 verify_method_spec_table (VerifyContext *ctx)
3572 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3573 guint32 data [MONO_METHODSPEC_SIZE];
3576 for (i = 0; i < table->rows; ++i) {
3577 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3579 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3580 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3582 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3583 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3585 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3586 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3591 verify_method_spec_table_full (VerifyContext *ctx)
3593 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3594 guint32 data [MONO_METHODSPEC_SIZE];
3597 for (i = 0; i < table->rows; ++i) {
3598 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3600 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3601 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3606 verify_generic_param_constraint_table (VerifyContext *ctx)
3608 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3609 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3612 for (i = 0; i < table->rows; ++i) {
3613 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3615 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3616 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3618 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3619 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3621 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3622 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3629 const char *name_space;
3630 guint32 resolution_scope;
3634 typedef_hash (gconstpointer _key)
3636 const TypeDefUniqueId *key = _key;
3637 return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3641 typedef_equals (gconstpointer _a, gconstpointer _b)
3643 const TypeDefUniqueId *a = _a;
3644 const TypeDefUniqueId *b = _b;
3645 return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3649 verify_typedef_table_global_constraints (VerifyContext *ctx)
3652 guint32 data [MONO_TYPEDEF_SIZE];
3653 guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3654 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3655 MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3656 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3658 for (i = 0; i < table->rows; ++i) {
3660 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3661 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3663 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3664 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3665 type->resolution_scope = 0;
3667 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3668 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3669 int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3670 g_assert (res >= 0);
3672 mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3673 type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3676 if (g_hash_table_lookup (unique_types, type)) {
3677 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));
3678 g_hash_table_destroy (unique_types);
3682 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3685 g_hash_table_destroy (unique_types);
3689 verify_typeref_table_global_constraints (VerifyContext *ctx)
3692 guint32 data [MONO_TYPEREF_SIZE];
3693 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3694 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3696 for (i = 0; i < table->rows; ++i) {
3697 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3698 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3700 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3701 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3702 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3704 if (g_hash_table_lookup (unique_types, type)) {
3705 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));
3706 g_hash_table_destroy (unique_types);
3710 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3713 g_hash_table_destroy (unique_types);
3717 verify_tables_data_global_constraints (VerifyContext *ctx)
3719 verify_typedef_table_global_constraints (ctx);
3723 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3725 verify_typeref_table (ctx);
3726 verify_typeref_table_global_constraints (ctx);
3730 verify_tables_data (VerifyContext *ctx)
3732 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3733 guint32 size = 0, tables_offset;
3736 for (i = 0; i < 0x2D; ++i) {
3737 MonoTableInfo *table = &ctx->image->tables [i];
3739 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3740 if (tmp_size < size) {
3748 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3750 tables_offset = ctx->image->tables_base - ctx->data;
3751 if (!bounds_check_offset (&tables_area, tables_offset, size))
3752 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)));
3754 verify_module_table (ctx);
3756 /*Obfuscators love to place broken stuff in the typeref table
3757 verify_typeref_table (ctx);
3759 verify_typedef_table (ctx);
3761 verify_field_table (ctx);
3763 verify_method_table (ctx);
3765 verify_param_table (ctx);
3767 verify_interfaceimpl_table (ctx);
3769 verify_memberref_table (ctx);
3771 verify_constant_table (ctx);
3773 verify_cattr_table (ctx);
3775 verify_field_marshal_table (ctx);
3777 verify_decl_security_table (ctx);
3779 verify_class_layout_table (ctx);
3781 verify_field_layout_table (ctx);
3783 verify_standalonesig_table (ctx);
3785 verify_eventmap_table (ctx);
3787 verify_event_table (ctx);
3789 verify_propertymap_table (ctx);
3791 verify_property_table (ctx);
3793 verify_methodimpl_table (ctx);
3795 verify_moduleref_table (ctx);
3797 verify_typespec_table (ctx);
3799 verify_implmap_table (ctx);
3801 verify_fieldrva_table (ctx);
3803 verify_assembly_table (ctx);
3805 verify_assemblyref_table (ctx);
3807 verify_file_table (ctx);
3809 verify_exportedtype_table (ctx);
3811 verify_manifest_resource_table (ctx);
3813 verify_nested_class_table (ctx);
3815 verify_generic_param_table (ctx);
3817 verify_method_spec_table (ctx);
3819 verify_generic_param_constraint_table (ctx);
3821 verify_tables_data_global_constraints (ctx);
3825 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3827 memset (ctx, 0, sizeof (VerifyContext));
3829 ctx->report_error = report_error;
3830 ctx->report_warning = FALSE; //export this setting in the API
3832 ctx->size = image->raw_data_len;
3833 ctx->data = image->raw_data;
3837 cleanup_context (VerifyContext *ctx, GSList **error_list)
3839 g_free (ctx->sections);
3841 *error_list = ctx->errors;
3843 mono_free_verify_list (ctx->errors);
3848 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3850 g_free (ctx->sections);
3852 MonoVerifyInfo *info = ctx->errors->data;
3853 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3854 mono_free_verify_list (ctx->errors);
3860 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3864 if (!mono_verifier_is_enabled_for_image (image))
3867 init_verify_context (&ctx, image, error_list != NULL);
3868 ctx.stage = STAGE_PE;
3870 verify_msdos_header (&ctx);
3872 verify_pe_header (&ctx);
3874 verify_pe_optional_header (&ctx);
3876 load_section_table (&ctx);
3878 load_data_directories (&ctx);
3880 verify_import_table (&ctx);
3882 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3883 verify_resources_table (&ctx);
3886 return cleanup_context (&ctx, error_list);
3890 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3894 if (!mono_verifier_is_enabled_for_image (image))
3897 init_verify_context (&ctx, image, error_list != NULL);
3898 ctx.stage = STAGE_CLI;
3900 verify_cli_header (&ctx);
3902 verify_metadata_header (&ctx);
3904 verify_tables_schema (&ctx);
3907 return cleanup_context (&ctx, error_list);
3912 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3913 * Other verification checks are meant to be done lazily by the runtime. Those include:
3914 * blob items (signatures, method headers, custom attributes, etc)
3915 * type semantics related
3917 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3919 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3920 * operation still need more checking.
3923 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3927 if (!mono_verifier_is_enabled_for_image (image))
3930 init_verify_context (&ctx, image, error_list != NULL);
3931 ctx.stage = STAGE_TABLES;
3933 verify_tables_data (&ctx);
3935 return cleanup_context (&ctx, error_list);
3940 * Verifies all other constraints.
3943 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3947 if (!mono_verifier_is_enabled_for_image (image))
3950 init_verify_context (&ctx, image, error_list != NULL);
3951 ctx.stage = STAGE_TABLES;
3953 verify_typedef_table_full (&ctx);
3955 verify_field_table_full (&ctx);
3957 verify_method_table_full (&ctx);
3959 verify_memberref_table_full (&ctx);
3961 verify_cattr_table_full (&ctx);
3963 verify_field_marshal_table_full (&ctx);
3965 verify_decl_security_table_full (&ctx);
3967 verify_standalonesig_table_full (&ctx);
3969 verify_event_table_full (&ctx);
3971 verify_typespec_table_full (&ctx);
3973 verify_method_spec_table_full (&ctx);
3975 verify_tables_data_global_constraints_full (&ctx);
3978 return cleanup_context (&ctx, error_list);
3982 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3986 if (!mono_verifier_is_enabled_for_image (image))
3989 init_verify_context (&ctx, image, error_list != NULL);
3990 ctx.stage = STAGE_TABLES;
3992 is_valid_field_signature (&ctx, offset);
3993 return cleanup_context (&ctx, error_list);
3997 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4000 guint32 locals_token;
4002 if (!mono_verifier_is_enabled_for_image (image))
4005 init_verify_context (&ctx, image, error_list != NULL);
4006 ctx.stage = STAGE_TABLES;
4008 is_valid_method_header (&ctx, offset, &locals_token);
4010 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
4011 is_valid_standalonesig_blob (&ctx, sig_offset);
4014 return cleanup_context (&ctx, error_list);
4018 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4022 mono_error_init (error);
4024 if (!mono_verifier_is_enabled_for_image (image))
4027 init_verify_context (&ctx, image, TRUE);
4028 ctx.stage = STAGE_TABLES;
4030 is_valid_method_signature (&ctx, offset);
4031 /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4032 return cleanup_context_checked (&ctx, error);
4036 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
4040 if (!mono_verifier_is_enabled_for_image (image))
4043 init_verify_context (&ctx, image, error_list != NULL);
4044 ctx.stage = STAGE_TABLES;
4046 is_valid_method_or_field_signature (&ctx, offset);
4047 return cleanup_context (&ctx, error_list);
4051 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4055 if (!mono_verifier_is_enabled_for_image (image))
4058 init_verify_context (&ctx, image, error_list != NULL);
4059 ctx.stage = STAGE_TABLES;
4061 is_valid_standalonesig_blob (&ctx, offset);
4062 return cleanup_context (&ctx, error_list);
4066 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4070 if (!mono_verifier_is_enabled_for_image (image))
4073 init_verify_context (&ctx, image, error_list != NULL);
4074 ctx.stage = STAGE_TABLES;
4077 is_valid_typespec_blob (&ctx, offset);
4078 return cleanup_context (&ctx, error_list);
4082 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4086 if (!mono_verifier_is_enabled_for_image (image))
4089 init_verify_context (&ctx, image, error_list != NULL);
4090 ctx.stage = STAGE_TABLES;
4092 is_valid_methodspec_blob (&ctx, offset);
4093 return cleanup_context (&ctx, error_list);
4097 verify_user_string (VerifyContext *ctx, guint32 offset)
4099 OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4100 guint32 entry_size, bytes;
4102 if (heap_us.size < offset)
4103 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4105 if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4106 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4108 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4109 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4111 entry_size += bytes;
4113 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4114 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4118 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4122 if (!mono_verifier_is_enabled_for_image (image))
4125 init_verify_context (&ctx, image, error_list != NULL);
4126 ctx.stage = STAGE_TABLES;
4128 verify_user_string (&ctx, offset);
4130 return cleanup_context (&ctx, error_list);
4134 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4138 if (!mono_verifier_is_enabled_for_image (image))
4141 init_verify_context (&ctx, image, error_list != NULL);
4142 ctx.stage = STAGE_TABLES;
4144 is_valid_cattr_blob (&ctx, offset);
4146 return cleanup_context (&ctx, error_list);
4150 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4154 if (!mono_verifier_is_enabled_for_image (image))
4157 init_verify_context (&ctx, image, error_list != NULL);
4158 ctx.stage = STAGE_TABLES;
4160 is_valid_cattr_content (&ctx, ctor, (const char*)data, size);
4162 return cleanup_context (&ctx, error_list);
4166 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4168 MonoMethodSignature *original_sig;
4169 if (!mono_verifier_is_enabled_for_image (image))
4172 original_sig = mono_method_signature (method);
4173 if (original_sig->call_convention == MONO_CALL_VARARG) {
4174 if (original_sig->hasthis != signature->hasthis)
4176 if (original_sig->call_convention != signature->call_convention)
4178 if (original_sig->explicit_this != signature->explicit_this)
4180 if (original_sig->call_convention != signature->call_convention)
4182 if (original_sig->pinvoke != signature->pinvoke)
4184 if (original_sig->sentinelpos != signature->sentinelpos)
4186 } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4194 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4196 MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
4197 guint32 data [MONO_TYPEREF_SIZE];
4199 mono_error_init (error);
4201 if (!mono_verifier_is_enabled_for_image (image))
4204 if (row >= table->rows) {
4205 mono_error_set_bad_image (error, image, "Invalid typeref row %d - table has %d rows", row, table->rows);
4209 mono_metadata_decode_row (table, row, data, MONO_TYPEREF_SIZE);
4210 if (!is_valid_coded_index_with_image (image, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4211 mono_error_set_bad_image (error, image, "Invalid typeref row %d coded index 0x%08x", row, data [MONO_TYPEREF_SCOPE]);
4215 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4216 mono_error_set_bad_image (error, image, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row);
4220 if (!data [MONO_TYPEREF_NAME] || !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAME], FALSE)) {
4221 mono_error_set_bad_image (error, image, "Invalid typeref row %d name token 0x%08x", row, data [MONO_TYPEREF_NAME]);
4225 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAMESPACE], FALSE)) {
4226 mono_error_set_bad_image (error, image, "Invalid typeref row %d namespace token 0x%08x", row, data [MONO_TYPEREF_NAMESPACE]);
4233 /*Perform additional verification including metadata ones*/
4235 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4237 MonoMethod *declaration, *body;
4238 MonoMethodSignature *body_sig, *decl_sig;
4239 MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
4240 guint32 data [MONO_METHODIMPL_SIZE];
4242 mono_error_init (error);
4244 if (!mono_verifier_is_enabled_for_image (image))
4247 if (row >= table->rows) {
4248 mono_error_set_bad_image (error, image, "Invalid methodimpl row %d - table has %d rows", row, table->rows);
4252 mono_metadata_decode_row (table, row, data, MONO_METHODIMPL_SIZE);
4254 body = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_BODY], NULL);
4255 if (mono_loader_get_last_error ()) {
4256 mono_loader_clear_error ();
4257 mono_error_set_bad_image (error, image, "Invalid methodimpl body for row %x", row);
4261 declaration = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_DECLARATION], NULL);
4262 if (mono_loader_get_last_error ()) {
4263 mono_loader_clear_error ();
4264 mono_error_set_bad_image (error, image, "Invalid methodimpl declaration for row %x", row);
4269 mono_class_setup_supertypes (class);
4270 if (!mono_class_has_parent (class, body->klass)) {
4271 mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
4275 if (!(body_sig = mono_method_signature_checked (body, error))) {
4279 if (!(decl_sig = mono_method_signature_checked (declaration, error))) {
4283 if (!mono_verifier_is_signature_compatible (decl_sig, body_sig)) {
4284 mono_error_set_bad_image (error, image, "Invalid methodimpl body signature not compatible with declaration row %x", row);
4293 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4299 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4305 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4311 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4317 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4323 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4329 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4331 mono_error_init (error);
4336 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
4342 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4348 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4354 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4360 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4366 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4372 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4378 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4385 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4387 mono_error_init (error);
4392 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4394 mono_error_init (error);
4398 #endif /* DISABLE_VERIFIER */