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 pe_signature_offset (VerifyContext *ctx)
306 return read32 (ctx->data + 0x3c);
310 pe_header_offset (VerifyContext *ctx)
312 return read32 (ctx->data + 0x3c) + 4;
316 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
320 if (rva + size < rva) //overflow
323 if (ctx->stage > STAGE_PE) {
324 MonoCLIImageInfo *iinfo = ctx->image->image_info;
325 const int top = iinfo->cli_section_count;
326 MonoSectionTable *tables = iinfo->cli_section_tables;
329 for (i = 0; i < top; i++) {
330 guint32 base = tables->st_virtual_address;
331 guint32 end = base + tables->st_raw_data_size;
333 if (rva >= base && rva + size <= end)
336 /*if ((addr >= tables->st_virtual_address) &&
337 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
339 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
349 for (i = 0; i < ctx->section_count; ++i) {
350 guint32 base = ctx->sections [i].baseRVA;
351 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
352 if (rva >= base && rva + size <= end)
359 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
361 if (dir->translated_offset > offset)
363 if (dir->size < size)
365 return offset + size <= dir->translated_offset + dir->size;
369 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
371 if (off->offset > offset)
374 if (off->size < size)
377 return offset + size <= off->offset + off->size;
381 translate_rva (VerifyContext *ctx, guint32 rva)
385 if (ctx->stage > STAGE_PE)
386 return mono_cli_rva_image_map (ctx->image, rva);
391 for (i = 0; i < ctx->section_count; ++i) {
392 guint32 base = ctx->sections [i].baseRVA;
393 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
394 if (rva >= base && rva <= end) {
395 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
397 return res >= ctx->size ? INVALID_OFFSET : res;
401 return INVALID_OFFSET;
405 verify_msdos_header (VerifyContext *ctx)
409 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
410 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
411 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
412 lfanew = pe_signature_offset (ctx);
413 if (lfanew > ctx->size - 4)
414 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
418 verify_pe_header (VerifyContext *ctx)
420 guint32 offset = pe_signature_offset (ctx);
421 const char *pe_header = ctx->data + offset;
422 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
423 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
427 if (offset > ctx->size - 20)
428 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
429 if (read16 (pe_header) != 0x14c)
430 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
434 verify_pe_optional_header (VerifyContext *ctx)
436 guint32 offset = pe_header_offset (ctx);
437 guint32 header_size, file_alignment;
438 const char *pe_header = ctx->data + offset;
439 const char *pe_optional_header = pe_header + 20;
441 header_size = read16 (pe_header + 16);
444 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
445 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
447 if (offset > ctx->size - header_size || header_size > ctx->size)
448 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
450 if (read16 (pe_optional_header) == 0x10b) {
451 if (header_size != 224)
452 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
454 /* LAMESPEC MS plays around this value and ignore it during validation
455 if (read32 (pe_optional_header + 28) != 0x400000)
456 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
457 if (read32 (pe_optional_header + 32) != 0x2000)
458 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
459 file_alignment = read32 (pe_optional_header + 36);
460 if (file_alignment != 0x200 && file_alignment != 0x1000)
461 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
462 /* All the junk in the middle is irrelevant, specially for mono. */
463 if (read32 (pe_optional_header + 92) > 0x10)
464 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
466 if (read16 (pe_optional_header) == 0x20B)
467 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
469 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
474 load_section_table (VerifyContext *ctx)
477 SectionHeader *sections;
478 guint32 offset = pe_header_offset (ctx);
479 const char *ptr = ctx->data + offset;
480 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
482 offset += 244;/*FIXME, this constant is different under PE32+*/
485 if (num_sections * 40 > ctx->size - offset)
486 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
488 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
489 for (i = 0; i < num_sections; ++i) {
490 sections [i].size = read32 (ptr + 8);
491 sections [i].baseRVA = read32 (ptr + 12);
492 sections [i].baseOffset = read32 (ptr + 20);
493 sections [i].rellocationsRVA = read32 (ptr + 24);
494 sections [i].numberOfRelocations = read16 (ptr + 32);
498 ptr = ctx->data + offset; /*reset it to the beggining*/
499 for (i = 0; i < num_sections; ++i) {
500 guint32 raw_size, flags;
501 if (sections [i].baseOffset == 0)
502 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
503 if (sections [i].baseOffset >= ctx->size)
504 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
505 if (sections [i].size > ctx->size - sections [i].baseOffset)
506 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
508 raw_size = read32 (ptr + 16);
509 if (raw_size < sections [i].size)
510 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
512 if (raw_size > ctx->size - sections [i].baseOffset)
513 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
515 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
516 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
518 flags = read32 (ptr + 36);
519 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
520 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
521 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
528 is_valid_data_directory (int i)
530 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
531 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
535 load_data_directories (VerifyContext *ctx)
537 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
538 const char *ptr = ctx->data + offset;
541 for (i = 0; i < 16; ++i) {
542 guint32 rva = read32 (ptr);
543 guint32 size = read32 (ptr + 4);
545 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
546 if (i == CERTIFICATE_TABLE_IDX) {
550 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
551 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
553 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
554 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
556 ctx->data_directories [i].rva = rva;
557 ctx->data_directories [i].size = size;
558 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
564 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
566 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
569 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
572 guint32 hint_table_rva;
574 import_rva = translate_rva (ctx, import_rva);
575 g_assert (import_rva != INVALID_OFFSET);
577 hint_table_rva = read32 (ctx->data + import_rva);
578 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
579 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
581 hint_table_rva = translate_rva (ctx, hint_table_rva);
582 g_assert (hint_table_rva != INVALID_OFFSET);
583 ptr = ctx->data + hint_table_rva + 2;
585 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
586 char name[SIZE_OF_CORMAIN];
587 memcpy (name, ptr, SIZE_OF_CORMAIN);
588 name [SIZE_OF_CORMAIN - 1] = 0;
589 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
594 verify_import_table (VerifyContext *ctx)
596 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
597 guint32 offset = it.translated_offset;
598 const char *ptr = ctx->data + offset;
599 guint32 name_rva, ilt_rva, iat_rva;
601 g_assert (offset != INVALID_OFFSET);
604 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
606 ilt_rva = read32 (ptr);
607 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
608 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
610 name_rva = read32 (ptr + 12);
611 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
612 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
614 iat_rva = read32 (ptr + 16);
616 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
617 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
619 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
620 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));
624 name_rva = translate_rva (ctx, name_rva);
625 g_assert (name_rva != INVALID_OFFSET);
626 ptr = ctx->data + name_rva;
628 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
629 char name[SIZE_OF_MSCOREE];
630 memcpy (name, ptr, SIZE_OF_MSCOREE);
631 name [SIZE_OF_MSCOREE - 1] = 0;
632 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
637 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
642 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
646 verify_resources_table (VerifyContext *ctx)
648 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
650 guint16 named_entries, id_entries;
651 const char *ptr, *root, *end;
657 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));
659 offset = it.translated_offset;
660 root = ptr = ctx->data + offset;
661 end = root + it.size;
663 g_assert (offset != INVALID_OFFSET);
665 named_entries = read16 (ptr + 12);
666 id_entries = read16 (ptr + 14);
668 if ((named_entries + id_entries) * 8 + 16 > it.size)
669 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));
671 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
672 if (named_entries || id_entries)
673 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
677 /*----------nothing from here on can use data_directory---*/
680 get_data_dir (VerifyContext *ctx, int idx)
682 MonoCLIImageInfo *iinfo = ctx->image->image_info;
683 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
687 res.rva = entry->rva;
688 res.size = entry->size;
689 res.translated_offset = translate_rva (ctx, res.rva);
694 verify_cli_header (VerifyContext *ctx)
696 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
702 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
705 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
707 offset = it.translated_offset;
708 ptr = ctx->data + offset;
710 g_assert (offset != INVALID_OFFSET);
712 if (read16 (ptr) != 72)
713 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
715 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
716 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
719 if (!read32 (ptr + 8) || !read32 (ptr + 12))
720 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
722 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
723 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
726 for (i = 0; i < 6; ++i) {
727 guint32 rva = read32 (ptr);
728 guint32 size = read32 (ptr + 4);
730 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
731 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
736 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
741 pad4 (guint32 offset)
743 if (offset & 0x3) //pad to the next 4 byte boundary
744 offset = (offset & ~0x3) + 4;
749 verify_metadata_header (VerifyContext *ctx)
752 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
753 guint32 offset, section_count;
756 offset = it.translated_offset;
757 ptr = ctx->data + offset;
758 g_assert (offset != INVALID_OFFSET);
760 //build a directory entry for the metadata root
762 it.rva = read32 (ptr);
764 it.size = read32 (ptr);
765 it.translated_offset = offset = translate_rva (ctx, it.rva);
767 ptr = ctx->data + offset;
768 g_assert (offset != INVALID_OFFSET);
771 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
773 if (read32 (ptr) != 0x424A5342)
774 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
776 offset = pad4 (offset + 16 + read32 (ptr + 12));
778 if (!bounds_check_datadir (&it, offset, 4))
779 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));
781 ptr = ctx->data + offset; //move to streams header
783 section_count = read16 (ptr + 2);
784 if (section_count < 2)
785 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
790 for (i = 0; i < section_count; ++i) {
791 guint32 stream_off, stream_size;
792 int string_size, stream_idx;
794 if (!bounds_check_datadir (&it, offset, 8))
795 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));
797 stream_off = it.translated_offset + read32 (ptr);
798 stream_size = read32 (ptr + 4);
800 if (!bounds_check_datadir (&it, stream_off, stream_size))
801 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
806 for (string_size = 0; string_size < 32; ++string_size) {
807 if (!bounds_check_datadir (&it, offset++, 1))
808 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
809 if (!ptr [string_size])
813 if (ptr [string_size])
814 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
816 if (!strncmp ("#Strings", ptr, 9))
817 stream_idx = STRINGS_STREAM;
818 else if (!strncmp ("#US", ptr, 4))
819 stream_idx = USER_STRINGS_STREAM;
820 else if (!strncmp ("#Blob", ptr, 6))
821 stream_idx = BLOB_STREAM;
822 else if (!strncmp ("#GUID", ptr, 6))
823 stream_idx = GUID_STREAM;
824 else if (!strncmp ("#~", ptr, 3))
825 stream_idx = TILDE_STREAM;
827 ADD_WARNING (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
828 offset = pad4 (offset);
829 ptr = ctx->data + offset;
833 if (ctx->metadata_streams [stream_idx].offset != 0)
834 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
836 ctx->metadata_streams [stream_idx].offset = stream_off;
837 ctx->metadata_streams [stream_idx].size = stream_size;
839 offset = pad4 (offset);
840 ptr = ctx->data + offset;
843 if (!ctx->metadata_streams [TILDE_STREAM].size)
844 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
845 if (!ctx->metadata_streams [GUID_STREAM].size)
846 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
850 verify_tables_schema (VerifyContext *ctx)
852 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
853 unsigned offset = tables_area.offset;
854 const char *ptr = ctx->data + offset;
855 guint64 valid_tables;
859 if (tables_area.size < 24)
860 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
862 if (ptr [4] != 2 && ptr [4] != 1)
863 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
865 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
867 if ((ptr [6] & ~0x7) != 0)
868 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]));
870 valid_tables = read64 (ptr + 8);
872 for (i = 0; i < 64; ++i) {
873 if (!(valid_tables & ((guint64)1 << i)))
876 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
877 Unused: 0x1E 0x1F 0x2D-0x3F
878 We don't care about the MS extensions.*/
879 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
880 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i));
881 if (i == 0x1E || i == 0x1F || i >= 0x2D)
882 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
886 if (tables_area.size < 24 + count * 4)
887 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));
890 for (i = 0; i < 64; ++i) {
891 if (valid_tables & ((guint64)1 << i)) {
892 guint32 row_count = read32 (ptr);
893 if (row_count > (1 << 24) - 1)
894 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
900 /*----------nothing from here on can use data_directory or metadata_streams ---*/
903 get_col_offset (VerifyContext *ctx, int table, int column)
905 guint32 bitfield = ctx->image->tables [table].size_bitfield;
909 offset += mono_metadata_table_size (bitfield, column);
915 get_col_size (VerifyContext *ctx, int table, int column)
917 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
921 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
924 res.offset = header->data - ctx->data;
925 res.size = header->size;
931 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
933 OffsetAndSize strings = get_metadata_stream (ctx, &ctx->image->heap_strings);
935 const char *data = ctx->data + strings.offset;
937 if (offset >= strings.size)
939 if (data + offset < data) //FIXME, use a generalized and smart unsigned add with overflow check and fix the whole thing
942 if (!mono_utf8_validate_and_len_with_bounds (data + offset, strings.size - offset, &length, NULL))
944 return allow_empty || length > 0;
948 is_valid_string (VerifyContext *ctx, guint32 offset)
950 return is_valid_string_full (ctx, offset, TRUE);
954 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
956 return is_valid_string_full (ctx, offset, FALSE);
960 is_valid_guid (VerifyContext *ctx, guint32 offset)
962 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
963 return guids.size >= 8 && guids.size - 8 >= offset;
967 get_coded_index_token (int token_kind, guint32 coded_token)
969 guint32 bits = coded_index_desc [token_kind];
970 return coded_token >> bits;
974 get_coded_index_table (int kind, guint32 coded_token)
976 guint32 idx, bits = coded_index_desc [kind];
978 idx = coded_token & ((1 << bits) - 1);
979 return coded_index_desc [kind + idx];
983 make_coded_token (int kind, guint32 table, guint32 table_idx)
985 guint32 bits = coded_index_desc [kind++];
986 guint32 tables = coded_index_desc [kind++];
988 for (i = 0; i < tables; ++i) {
989 if (coded_index_desc [kind++] == table)
990 return ((table_idx + 1) << bits) | i;
992 g_assert_not_reached ();
997 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
999 guint32 bits = coded_index_desc [token_kind++];
1000 guint32 table_count = coded_index_desc [token_kind++];
1001 guint32 table = coded_token & ((1 << bits) - 1);
1002 guint32 token = coded_token >> bits;
1004 if (table >= table_count)
1007 /*token_kind points to the first table idx*/
1008 table = coded_index_desc [token_kind + table];
1010 if (table == INVALID_TABLE)
1012 return token <= ctx->image->tables [table].rows;
1019 MonoTableInfo *table;
1023 token_locator (const void *a, const void *b)
1025 RowLocator *loc = (RowLocator *)a;
1026 unsigned const char *row = (unsigned const char *)b;
1027 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1029 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1030 return (int)loc->token - (int)token;
1034 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1036 MonoTableInfo *tinfo = &ctx->image->tables [table];
1038 const char *res, *base;
1039 locator.token = coded_token;
1040 locator.col_offset = get_col_offset (ctx, table, column);
1041 locator.col_size = get_col_size (ctx, table, column);
1042 locator.table = tinfo;
1046 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) );
1047 res = bsearch (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1051 return (res - base) / tinfo->row_size;
1054 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1056 get_string_ptr (VerifyContext *ctx, guint offset)
1058 return ctx->image->heap_strings.data + offset;
1061 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1063 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1066 return strcmp (str, "");
1068 return strcmp (str, get_string_ptr (ctx, offset));
1072 mono_verifier_is_corlib (MonoImage *image)
1074 gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
1075 TRUE : mono_security_core_clr_is_platform_image (image);
1077 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1081 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1083 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1087 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1090 const unsigned char *ptr = (const unsigned char *)_ptr;
1098 if ((b & 0x80) == 0) {
1101 } else if ((b & 0x40) == 0) {
1105 *value = ((b & 0x3f) << 8 | ptr [1]);
1110 *value = ((b & 0x1f) << 24) |
1120 decode_signature_header (VerifyContext *ctx, guint32 offset, guint32 *size, const char **first_byte)
1122 MonoStreamHeader blob = ctx->image->heap_blob;
1123 guint32 value, enc_size;
1125 if (offset >= blob.size)
1128 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1131 if (CHECK_ADD4_OVERFLOW_UN (offset, enc_size))
1136 if (ADD_IS_GREATER_OR_OVF (offset, value, blob.size))
1140 *first_byte = blob.data + offset;
1145 safe_read (const char **_ptr, const char *limit, unsigned *dest, int size)
1147 const char *ptr = *_ptr;
1148 if (ptr + size > limit)
1152 *dest = *((guint8*)ptr);
1156 *dest = read16 (ptr);
1160 *dest = read32 (ptr);
1169 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1172 const char *ptr = *_ptr;
1173 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1178 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1179 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1180 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1181 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1184 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1187 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1190 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1192 const char *ptr = *_ptr;
1197 if (!safe_read8 (type, ptr, end))
1198 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1200 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1205 if (!safe_read_cint (token, ptr, end))
1206 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1208 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1209 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1217 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1219 const char *ptr = *_ptr;
1221 unsigned size, num, i;
1223 if (!safe_read8 (val, ptr, end))
1224 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1227 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1229 if (!safe_read_cint (size, ptr, end))
1230 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1232 for (i = 0; i < size; ++i) {
1233 if (!safe_read_cint (num, ptr, end))
1234 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1237 if (!safe_read_cint (size, ptr, end))
1238 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1240 for (i = 0; i < size; ++i) {
1241 if (!safe_read_cint (num, ptr, end))
1242 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1250 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1252 const char *ptr = *_ptr;
1254 unsigned count, token, i;
1256 if (!safe_read8 (type, ptr, end))
1257 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1259 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1260 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1262 if (!safe_read_cint (token, ptr, end))
1263 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1265 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1266 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1269 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1270 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1271 FAIL (ctx, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx->token));
1274 if (!safe_read_cint (count, ptr, end))
1275 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1278 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1280 for (i = 0; i < count; ++i) {
1281 if (!parse_type (ctx, &ptr, end))
1282 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1289 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1291 const char *ptr = *_ptr;
1295 if (!safe_read8 (type, ptr, end))
1296 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1298 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1299 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1300 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1301 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1302 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1306 if (!parse_custom_mods (ctx, &ptr, end))
1307 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1309 if (!safe_read8 (type, ptr, end))
1310 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1312 if (type != MONO_TYPE_VOID) {
1314 if (!parse_type (ctx, &ptr, end))
1315 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1319 case MONO_TYPE_VALUETYPE:
1320 case MONO_TYPE_CLASS:
1321 if (!safe_read_cint (token, ptr, end))
1322 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1324 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1325 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1327 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1328 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1329 FAIL (ctx, g_strdup_printf ("Type: Recurside type specification (%x). A type signature can't reference itself", ctx->token));
1334 case MONO_TYPE_MVAR:
1335 if (!safe_read_cint (token, ptr, end))
1336 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1339 case MONO_TYPE_ARRAY:
1340 if (!parse_type (ctx, &ptr, end))
1341 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1342 if (!parse_array_shape (ctx, &ptr, end))
1343 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1346 case MONO_TYPE_GENERICINST:
1347 if (!parse_generic_inst (ctx, &ptr, end))
1348 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1351 case MONO_TYPE_FNPTR:
1352 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1353 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1356 case MONO_TYPE_SZARRAY:
1357 if (!parse_custom_mods (ctx, &ptr, end))
1358 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1359 if (!parse_type (ctx, &ptr, end))
1360 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1368 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1373 if (!parse_custom_mods (ctx, _ptr, end))
1377 if (!safe_read8 (type, ptr, end))
1378 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1380 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1385 //it's a byref, update the cursor ptr
1386 if (type == MONO_TYPE_BYREF)
1389 return parse_type (ctx, _ptr, end);
1393 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1398 if (!parse_custom_mods (ctx, _ptr, end))
1402 if (!safe_read8 (type, ptr, end))
1403 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1405 if (type == MONO_TYPE_TYPEDBYREF) {
1410 //it's a byref, update the cursor ptr
1411 if (type == MONO_TYPE_BYREF)
1414 return parse_type (ctx, _ptr, end);
1418 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1421 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1422 const char *ptr = *_ptr;
1423 gboolean saw_sentinel = FALSE;
1425 if (!safe_read8 (cconv, ptr, end))
1426 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1429 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1431 if (allow_unmanaged) {
1432 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1433 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1434 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1435 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1437 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1438 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1440 if ((cconv & 0x10) && gparam_count == 0)
1441 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1443 if (allow_unmanaged && (cconv & 0x10))
1444 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1446 if (!safe_read_cint (param_count, ptr, end))
1447 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1449 if (!parse_return_type (ctx, &ptr, end))
1450 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1452 for (i = 0; i < param_count; ++i) {
1453 if (allow_sentinel) {
1454 if (!safe_read8 (type, ptr, end))
1455 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1457 if (type == MONO_TYPE_SENTINEL) {
1458 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1459 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1462 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1464 saw_sentinel = TRUE;
1470 if (!parse_param (ctx, &ptr, end))
1471 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1479 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1482 unsigned param_count = 0, i;
1483 const char *ptr = *_ptr;
1485 if (!safe_read8 (sig, ptr, end))
1486 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1488 if (sig != 0x08 && sig != 0x28)
1489 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1491 if (!safe_read_cint (param_count, ptr, end))
1492 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1494 if (!parse_custom_mods (ctx, &ptr, end))
1497 if (!parse_type (ctx, &ptr, end))
1498 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1500 for (i = 0; i < param_count; ++i) {
1501 if (!parse_type (ctx, &ptr, end))
1502 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1510 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1512 const char *ptr = *_ptr;
1513 unsigned signature = 0;
1515 if (!safe_read8 (signature, ptr, end))
1516 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1518 if (signature != 0x06)
1519 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1521 if (!parse_custom_mods (ctx, &ptr, end))
1524 if (safe_read8 (signature, ptr, end)) {
1525 if (signature != MONO_TYPE_BYREF)
1530 return parse_type (ctx, _ptr, end);
1534 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1537 unsigned locals_count = 0, i;
1538 const char *ptr = *_ptr;
1540 if (!safe_read8 (sig, ptr, end))
1541 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1544 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1546 if (!safe_read_cint (locals_count, ptr, end))
1547 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1549 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1550 if (locals_count == 0)
1551 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1554 for (i = 0; i < locals_count; ++i) {
1555 if (!safe_read8 (sig, ptr, end))
1556 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1558 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1559 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1560 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1561 if (!safe_read8 (sig, ptr, end))
1562 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1565 if (sig == MONO_TYPE_BYREF) {
1566 if (!safe_read8 (sig, ptr, end))
1567 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1568 if (sig == MONO_TYPE_TYPEDBYREF)
1569 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1572 if (sig == MONO_TYPE_TYPEDBYREF)
1577 if (!parse_type (ctx, &ptr, end))
1578 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1586 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1589 unsigned signature = 0;
1590 const char *ptr = NULL, *end;
1592 if (!decode_signature_header (ctx, offset, &size, &ptr))
1593 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1596 if (!safe_read8 (signature, ptr, end))
1597 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1600 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1603 return parse_field (ctx, &ptr, end);
1607 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1610 const char *ptr = NULL, *end;
1612 if (!decode_signature_header (ctx, offset, &size, &ptr))
1613 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1616 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1620 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1623 unsigned signature = 0;
1624 const char *ptr = NULL, *end;
1626 if (!decode_signature_header (ctx, offset, &size, &ptr))
1627 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1630 if (!safe_read8 (signature, ptr, end))
1631 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1634 if (signature == 0x06)
1635 return parse_field (ctx, &ptr, end);
1637 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1641 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1644 unsigned prolog = 0;
1645 const char *ptr = NULL, *end;
1650 if (!decode_signature_header (ctx, offset, &size, &ptr))
1651 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1654 if (!safe_read16 (prolog, ptr, end))
1655 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1658 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1664 is_valid_cattr_type (MonoType *type)
1668 if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1671 if (type->type == MONO_TYPE_VALUETYPE) {
1672 klass = mono_class_from_mono_type (type);
1673 return klass && klass->enumtype;
1676 if (type->type == MONO_TYPE_CLASS)
1677 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1683 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1686 const char *ptr = *_ptr;
1692 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1695 if (*ptr == (char)0xFF) {
1700 if (!safe_read_cint (size, ptr, end))
1701 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1703 if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1704 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1714 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1716 const char *dummy_str;
1718 return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1722 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1726 const char *str_start = NULL;
1727 const char *ptr = *_ptr;
1729 guint32 str_len = 0;
1731 if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1734 /*NULL or empty string*/
1735 if (str_start == NULL || str_len == 0) {
1736 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1740 enum_name = g_memdup (str_start, str_len + 1);
1741 enum_name [str_len] = 0;
1742 type = mono_reflection_type_from_name (enum_name, ctx->image);
1744 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1750 klass = mono_class_from_mono_type (type);
1751 if (!klass || !klass->enumtype) {
1752 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1761 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1764 const char *ptr = *_ptr;
1766 guint32 element_count, i;
1769 klass = mono_type->data.klass;
1770 type = mono_type->type;
1774 case MONO_TYPE_BOOLEAN:
1781 case MONO_TYPE_CHAR:
1795 case MONO_TYPE_STRING:
1797 return is_valid_ser_string (ctx, _ptr, end);
1799 case MONO_TYPE_OBJECT: {
1800 unsigned sub_type = 0;
1801 if (!safe_read8 (sub_type, ptr, end))
1802 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1804 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1808 if (sub_type == MONO_TYPE_ENUM) {
1809 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1813 klass = klass->element_class;
1814 type = klass->byval_arg.type;
1817 if (sub_type == 0x50) { /*Type*/
1819 return is_valid_ser_string (ctx, _ptr, end);
1821 if (sub_type == MONO_TYPE_SZARRAY) {
1822 MonoType simple_type = {{0}};
1824 if (!safe_read8 (etype, ptr, end))
1825 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1827 if (etype == MONO_TYPE_ENUM) {
1828 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1831 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1832 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
1833 klass = mono_class_from_mono_type (&simple_type);
1835 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1837 type = MONO_TYPE_SZARRAY;
1840 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1844 case MONO_TYPE_CLASS:
1845 if (klass != mono_defaults.systemtype_class)
1846 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1848 return is_valid_ser_string (ctx, _ptr, end);
1850 case MONO_TYPE_VALUETYPE:
1851 if (!klass || !klass->enumtype)
1852 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1854 klass = klass->element_class;
1855 type = klass->byval_arg.type;
1858 case MONO_TYPE_SZARRAY:
1859 mono_type = &klass->byval_arg;
1860 if (!is_valid_cattr_type (mono_type))
1861 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1862 if (!safe_read32 (element_count, ptr, end))
1863 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1864 if (element_count == 0xFFFFFFFFu) {
1868 for (i = 0; i < element_count; ++i) {
1869 if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1875 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1878 if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1879 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1880 *_ptr = ptr + elem_size;
1885 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1888 unsigned prolog = 0;
1890 MonoMethodSignature *sig;
1895 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1897 sig = mono_method_signature_checked (ctor, &error);
1898 if (!mono_error_ok (&error)) {
1899 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1900 mono_error_cleanup (&error);
1904 if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1905 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1909 if (!safe_read16 (prolog, ptr, end))
1910 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1913 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1915 args = sig->param_count;
1916 for (i = 0; i < args; ++i) {
1917 MonoType *arg_type = sig->params [i];
1918 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1922 if (!safe_read16 (num_named, ptr, end))
1923 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1925 for (i = 0; i < num_named; ++i) {
1926 MonoType *type, simple_type = {{0}};
1929 if (!safe_read8 (kind, ptr, end))
1930 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1931 if (kind != 0x53 && kind != 0x54)
1932 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1933 if (!safe_read8 (kind, ptr, end))
1934 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1936 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1937 simple_type.type = kind;
1938 type = &simple_type;
1939 } else if (kind == MONO_TYPE_ENUM) {
1940 MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1943 type = &klass->byval_arg;
1944 } else if (kind == 0x50) {
1945 type = &mono_defaults.systemtype_class->byval_arg;
1946 } else if (kind == 0x51) {
1947 type = &mono_defaults.object_class->byval_arg;
1948 } else if (kind == MONO_TYPE_SZARRAY) {
1951 if (!safe_read8 (etype, ptr, end))
1952 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1954 if (etype == MONO_TYPE_ENUM) {
1955 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1958 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1959 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : etype;
1960 klass = mono_class_from_mono_type (&simple_type);
1962 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1964 type = &mono_array_class_get (klass, 1)->byval_arg;
1966 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
1969 if (!is_valid_ser_string (ctx, &ptr, end))
1972 if (!is_valid_fixed_param (ctx, type, &ptr, end))
1981 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
1983 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1984 //TODO do proper verification
1985 return blob.size >= 1 && blob.size - 1 >= offset;
1989 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
1991 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1992 //TODO do proper verification
1993 return blob.size >= 1 && blob.size - 1 >= offset;
1997 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2000 unsigned signature = 0;
2001 const char *ptr = NULL, *end;
2003 if (!decode_signature_header (ctx, offset, &size, &ptr))
2004 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2007 if (!safe_read8 (signature, ptr, end))
2008 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2011 if (signature == 0x07)
2012 return parse_locals_signature (ctx, &ptr, end);
2014 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2015 if (signature == 0x06)
2016 return parse_field (ctx, &ptr, end);
2018 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2022 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2025 const char *ptr = NULL, *end;
2027 if (!decode_signature_header (ctx, offset, &size, &ptr))
2028 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2031 return parse_property_signature (ctx, &ptr, end);
2035 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2038 const char *ptr = NULL, *end;
2041 if (!decode_signature_header (ctx, offset, &size, &ptr))
2042 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2045 if (!parse_custom_mods (ctx, &ptr, end))
2048 if (!safe_read8 (type, ptr, end))
2049 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2051 if (type == MONO_TYPE_BYREF) {
2052 if (!safe_read8 (type, ptr, end))
2053 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2054 if (type == MONO_TYPE_TYPEDBYREF)
2055 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2058 if (type == MONO_TYPE_TYPEDBYREF)
2062 return parse_type (ctx, &ptr, end);
2066 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2069 const char *ptr = NULL, *end;
2071 unsigned count = 0, i;
2073 if (!decode_signature_header (ctx, offset, &size, &ptr))
2074 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2077 if (!safe_read8 (type, ptr, end))
2078 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2081 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2083 if (!safe_read_cint (count, ptr, end))
2084 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2087 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2089 for (i = 0; i < count; ++i) {
2090 if (!parse_type (ctx, &ptr, end))
2091 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2097 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2099 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2100 guint32 entry_size, bytes;
2102 if (blob.size < offset)
2105 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2108 if (entry_size < minsize)
2111 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2113 entry_size += bytes;
2115 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2119 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2121 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2122 guint32 size, entry_size, bytes;
2124 if (blob.size < offset)
2125 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2127 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2128 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2130 if (type == MONO_TYPE_STRING) {
2131 //String is encoded as: compressed_int:len len *bytes
2134 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2135 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
2141 case MONO_TYPE_BOOLEAN:
2146 case MONO_TYPE_CHAR:
2154 case MONO_TYPE_CLASS:
2164 g_assert_not_reached ();
2167 if (size != entry_size)
2168 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2172 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2173 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2175 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2176 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2180 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2181 //only 0x01, 0x40 and 0x80 are allowed
2182 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2185 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2187 unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2188 unsigned header = 0;
2189 unsigned fat_header = 0, size = 0, max_stack;
2190 const char *ptr = NULL, *end;
2194 if (offset == INVALID_ADDRESS)
2195 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2197 ptr = ctx->data + offset;
2198 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2200 if (!safe_read8 (header, ptr, end))
2201 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2203 switch (header & 0x3) {
2206 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2209 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
2210 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2215 if (!safe_read16 (fat_header, ptr, end))
2216 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2218 size = (fat_header >> 12) & 0xF;
2220 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2222 if (!safe_read16 (max_stack, ptr, end))
2223 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2225 if (!safe_read32 (code_size, ptr, end))
2226 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2228 if (!safe_read32 (local_vars_tok, ptr, end))
2229 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2231 if (local_vars_tok) {
2232 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2233 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2234 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
2235 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2236 *locals_token = local_vars_tok & 0xFFFFFF;
2239 if (fat_header & FAT_HEADER_INVALID_FLAGS)
2240 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2242 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2243 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2245 if (!(fat_header & 0x08))
2251 unsigned section_header = 0, section_size = 0;
2254 ptr = dword_align (ptr);
2255 if (!safe_read32 (section_header, ptr, end))
2256 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2258 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2259 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2261 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2262 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2264 if (section_size < 4)
2265 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2267 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2268 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2270 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2271 guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2273 LAMEIMPL: MS emits section_size without accounting for header size.
2274 Mono does as the spec says. section_size is header + section
2275 MS's peverify happily accepts both.
2277 if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2278 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)));
2280 /* only verify the class token is verified as the rest is done by the IL verifier*/
2281 for (i = 0; i < clauses; ++i) {
2282 unsigned flags = *(unsigned char*)ptr;
2283 unsigned class_token = 0;
2284 ptr += (is_fat ? 20 : 8);
2285 if (!safe_read32 (class_token, ptr, end))
2286 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2287 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2288 guint table = mono_metadata_token_table (class_token);
2289 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2290 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2291 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2292 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2297 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2304 verify_module_table (VerifyContext *ctx)
2306 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2307 guint32 data [MONO_MODULE_SIZE];
2309 if (table->rows != 1)
2310 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2312 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2314 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2315 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2317 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2318 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2320 if (data [MONO_MODULE_ENC] != 0)
2321 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2323 if (data [MONO_MODULE_ENCBASE] != 0)
2324 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2328 verify_typeref_table (VerifyContext *ctx)
2330 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2331 guint32 data [MONO_TYPEREF_SIZE];
2334 for (i = 0; i < table->rows; ++i) {
2335 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
2336 if (!is_valid_coded_index (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
2337 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i, data [MONO_TYPEREF_SCOPE]));
2339 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
2340 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i));
2342 if (!data [MONO_TYPEREF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAME]))
2343 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d name token 0x%08x", i, data [MONO_TYPEREF_NAME]));
2345 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2346 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d namespace token 0x%08x", i, data [MONO_TYPEREF_NAMESPACE]));
2350 /*bits 9,11,14,15,19,21,24-31 */
2351 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2353 verify_typedef_table (VerifyContext *ctx)
2355 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2356 guint32 data [MONO_TYPEDEF_SIZE];
2357 guint32 fieldlist = 1, methodlist = 1, visibility;
2360 if (table->rows == 0)
2361 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2363 for (i = 0; i < table->rows; ++i) {
2364 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2365 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2366 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2368 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2369 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2371 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2372 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2374 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2375 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2377 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2378 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2380 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2381 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2383 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2384 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2386 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2387 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2389 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2390 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2391 search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2392 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2394 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2395 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2397 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2398 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2400 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2401 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));
2403 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2404 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2406 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2407 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2409 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2410 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));
2412 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2413 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2418 verify_typedef_table_full (VerifyContext *ctx)
2420 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2421 guint32 data [MONO_TYPEDEF_SIZE];
2424 if (table->rows == 0)
2425 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2427 for (i = 0; i < table->rows; ++i) {
2428 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2431 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2432 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2433 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2438 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2439 if (data [MONO_TYPEDEF_EXTENDS])
2440 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2442 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2443 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2447 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2450 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2458 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2460 verify_field_table (VerifyContext *ctx)
2462 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2463 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2466 module_field_list = (guint32)-1;
2467 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2468 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2469 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2472 for (i = 0; i < table->rows; ++i) {
2473 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2474 flags = data [MONO_FIELD_FLAGS];
2476 if (flags & INVALID_FIELD_FLAG_BITS)
2477 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2479 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2480 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2482 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2483 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2485 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2486 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2488 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2489 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2491 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2492 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2493 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2495 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2496 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2497 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2499 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2500 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2501 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2503 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2504 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2505 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2507 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2508 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2510 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2511 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2513 //TODO verify contant flag
2515 if (i + 1 < module_field_list) {
2516 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2517 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2518 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2519 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2520 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2526 verify_field_table_full (VerifyContext *ctx)
2528 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2529 guint32 data [MONO_FIELD_SIZE];
2532 for (i = 0; i < table->rows; ++i) {
2533 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2535 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2536 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2540 /*bits 8,9,10,11,13,14,15*/
2541 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2543 verify_method_table (VerifyContext *ctx)
2545 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2546 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2547 guint32 paramlist = 1;
2548 gboolean is_ctor, is_cctor;
2552 module_method_list = (guint32)-1;
2553 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2554 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2555 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2558 for (i = 0; i < table->rows; ++i) {
2559 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2560 rva = data [MONO_METHOD_RVA];
2561 implflags = data [MONO_METHOD_IMPLFLAGS];
2562 flags = data [MONO_METHOD_FLAGS];
2563 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2564 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2567 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2568 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2571 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2573 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2574 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2576 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2577 is_ctor = !strcmp (".ctor", name);
2578 is_cctor = !strcmp (".cctor", name);
2580 if ((is_ctor || is_cctor) &&
2581 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2582 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2584 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2585 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2587 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2588 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2589 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2590 if (flags & METHOD_ATTRIBUTE_FINAL)
2591 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2592 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2593 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2596 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2597 ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2599 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2600 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2602 //XXX no checks against cas stuff 10,11,12,13)
2604 //TODO check iface with .ctor (15,16)
2606 if (i + 1 < module_method_list) {
2607 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2608 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2609 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2610 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2611 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2612 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2615 //TODO check valuetype for synchronized
2617 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2618 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2620 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2621 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2622 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2623 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2624 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2627 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2628 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2629 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2631 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2632 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2634 //TODO check signature contents
2637 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2638 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2639 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2640 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2642 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2643 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2646 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2648 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2649 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2650 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2652 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2653 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2655 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2656 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2658 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2659 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2661 if (data [MONO_METHOD_PARAMLIST] == 0)
2662 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2664 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2665 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));
2667 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2668 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2670 paramlist = data [MONO_METHOD_PARAMLIST];
2676 verify_method_table_full (VerifyContext *ctx)
2678 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2679 guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2682 for (i = 0; i < table->rows; ++i) {
2683 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2684 rva = data [MONO_METHOD_RVA];
2686 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2687 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2689 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2690 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2695 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2697 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2698 guint32 row = *current_method;
2699 guint32 paramlist, tmp;
2702 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2703 while (row < table->rows) {
2704 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2705 if (tmp > paramlist) {
2706 *current_method = row;
2707 return tmp - paramlist;
2712 /*no more methods, all params apply to the last one*/
2713 *current_method = table->rows;
2718 #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))
2720 verify_param_table (VerifyContext *ctx)
2722 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2723 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2724 gboolean first_param = TRUE;
2727 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2728 if (table->rows > 0)
2729 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2733 remaining_params = get_next_param_count (ctx, ¤t_method);
2735 for (i = 0; i < table->rows; ++i) {
2736 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2737 flags = data [MONO_PARAM_FLAGS];
2739 if (flags & INVALID_PARAM_FLAGS_BITS)
2740 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2742 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2743 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2744 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2746 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2747 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2750 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)
2751 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2753 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2754 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2756 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2757 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2759 first_param = FALSE;
2760 sequence = data [MONO_PARAM_SEQUENCE];
2761 if (--remaining_params == 0) {
2762 remaining_params = get_next_param_count (ctx, ¤t_method);
2769 verify_interfaceimpl_table (VerifyContext *ctx)
2771 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2772 guint32 data [MONO_INTERFACEIMPL_SIZE];
2775 for (i = 0; i < table->rows; ++i) {
2776 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2777 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2778 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2780 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2781 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2783 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2784 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2789 verify_memberref_table (VerifyContext *ctx)
2791 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2792 guint32 data [MONO_MEMBERREF_SIZE];
2795 for (i = 0; i < table->rows; ++i) {
2796 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2798 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2799 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2801 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2802 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2804 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2805 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2807 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2808 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2814 verify_memberref_table_full (VerifyContext *ctx)
2816 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2817 guint32 data [MONO_MEMBERREF_SIZE];
2820 for (i = 0; i < table->rows; ++i) {
2821 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2823 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2824 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2829 verify_constant_table (VerifyContext *ctx)
2831 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2832 guint32 data [MONO_CONSTANT_SIZE], type;
2835 for (i = 0; i < table->rows; ++i) {
2836 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2837 type = data [MONO_CONSTANT_TYPE];
2839 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2840 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2842 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2843 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2845 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2846 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2848 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2849 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2854 verify_cattr_table (VerifyContext *ctx)
2856 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2857 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2860 for (i = 0; i < table->rows; ++i) {
2861 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2863 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2864 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2866 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2867 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2869 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2870 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2875 verify_cattr_table_full (VerifyContext *ctx)
2877 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2880 guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2883 for (i = 0; i < table->rows; ++i) {
2884 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2886 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2887 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2889 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2890 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2891 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2892 mtoken |= MONO_TOKEN_METHOD_DEF;
2894 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2895 mtoken |= MONO_TOKEN_MEMBER_REF;
2898 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2901 ctor = mono_get_method (ctx->image, mtoken, NULL);
2903 /*This can't fail since this is checked in is_valid_cattr_blob*/
2904 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2906 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2907 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2912 verify_field_marshal_table (VerifyContext *ctx)
2914 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2915 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2918 for (i = 0; i < table->rows; ++i) {
2919 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2921 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2922 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2924 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2925 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2927 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2928 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2930 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2931 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2936 verify_field_marshal_table_full (VerifyContext *ctx)
2938 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2939 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2942 for (i = 0; i < table->rows; ++i) {
2943 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2945 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2946 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2951 verify_decl_security_table (VerifyContext *ctx)
2953 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2954 guint32 data [MONO_DECL_SECURITY_SIZE];
2957 for (i = 0; i < table->rows; ++i) {
2958 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2960 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2961 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2963 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2964 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
2966 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
2967 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
2972 verify_decl_security_table_full (VerifyContext *ctx)
2974 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2975 guint32 data [MONO_DECL_SECURITY_SIZE];
2978 for (i = 0; i < table->rows; ++i) {
2979 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2981 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
2982 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
2987 verify_class_layout_table (VerifyContext *ctx)
2989 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
2990 guint32 data [MONO_CLASS_LAYOUT_SIZE];
2993 for (i = 0; i < table->rows; ++i) {
2994 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
2996 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2997 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2999 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3011 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3017 verify_field_layout_table (VerifyContext *ctx)
3019 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3020 guint32 data [MONO_FIELD_LAYOUT_SIZE];
3023 for (i = 0; i < table->rows; ++i) {
3024 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3026 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3027 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3032 verify_standalonesig_table (VerifyContext *ctx)
3034 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3035 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3038 for (i = 0; i < table->rows; ++i) {
3039 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3041 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3042 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3047 verify_standalonesig_table_full (VerifyContext *ctx)
3049 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3050 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3053 for (i = 0; i < table->rows; ++i) {
3054 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3056 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3057 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3062 verify_eventmap_table (VerifyContext *ctx)
3064 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3065 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3068 for (i = 0; i < table->rows; ++i) {
3069 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3071 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3072 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3074 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3075 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3077 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3081 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3083 verify_event_table (VerifyContext *ctx)
3085 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3086 guint32 data [MONO_EVENT_SIZE];
3089 for (i = 0; i < table->rows; ++i) {
3090 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3092 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3093 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3095 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3096 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3098 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3099 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3104 verify_event_table_full (VerifyContext *ctx)
3106 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3107 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3108 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3109 gboolean found_add, found_remove;
3112 for (i = 0; i < table->rows; ++i) {
3113 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3115 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3116 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3118 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3120 //first we move to the first row for this event
3122 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3126 //now move forward looking for AddOn and RemoveOn rows
3127 found_add = found_remove = FALSE;
3128 while (idx < sema_table->rows) {
3129 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3130 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3132 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3134 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3135 found_remove = TRUE;
3136 if (found_add && found_remove)
3142 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3144 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3149 verify_propertymap_table (VerifyContext *ctx)
3151 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3152 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3155 for (i = 0; i < table->rows; ++i) {
3156 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3158 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3159 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3161 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3162 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3164 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3168 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3170 verify_property_table (VerifyContext *ctx)
3172 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3173 guint32 data [MONO_PROPERTY_SIZE];
3176 for (i = 0; i < table->rows; ++i) {
3177 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3179 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3180 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3182 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3183 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3185 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3186 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3188 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3189 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3190 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3196 verify_methodimpl_table (VerifyContext *ctx)
3198 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3199 guint32 data [MONO_METHODIMPL_SIZE];
3202 for (i = 0; i < table->rows; ++i) {
3203 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3205 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3206 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3208 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3209 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3211 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3212 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3214 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3215 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3217 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3218 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3223 verify_moduleref_table (VerifyContext *ctx)
3225 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3226 guint32 data [MONO_MODULEREF_SIZE];
3229 for (i = 0; i < table->rows; ++i) {
3230 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3232 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3233 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3238 verify_typespec_table (VerifyContext *ctx)
3240 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3241 guint32 data [MONO_TYPESPEC_SIZE];
3244 for (i = 0; i < table->rows; ++i) {
3245 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3247 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3248 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3253 verify_typespec_table_full (VerifyContext *ctx)
3255 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3256 guint32 data [MONO_TYPESPEC_SIZE];
3259 for (i = 0; i < table->rows; ++i) {
3260 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3261 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3262 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3263 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3268 #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))
3270 verify_implmap_table (VerifyContext *ctx)
3272 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3273 guint32 data [MONO_IMPLMAP_SIZE], cconv;
3276 for (i = 0; i < table->rows; ++i) {
3277 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3279 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3280 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3282 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3283 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3284 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3286 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3287 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3289 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3290 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3292 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3293 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3295 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3296 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3298 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows + 1)
3299 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3304 verify_fieldrva_table (VerifyContext *ctx)
3306 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3307 guint32 data [MONO_FIELD_RVA_SIZE];
3310 for (i = 0; i < table->rows; ++i) {
3311 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3313 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3314 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3316 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3317 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3321 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 8) | (1 << 14) | (1 << 15))
3323 verify_assembly_table (VerifyContext *ctx)
3325 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3326 guint32 data [MONO_ASSEMBLY_SIZE], hash;
3329 if (table->rows > 1)
3330 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3332 for (i = 0; i < table->rows; ++i) {
3333 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3335 hash = data [MONO_ASSEMBLY_HASH_ALG];
3336 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3337 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3339 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3340 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3342 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3343 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3345 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3346 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3348 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3349 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3353 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
3355 verify_assemblyref_table (VerifyContext *ctx)
3357 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3358 guint32 data [MONO_ASSEMBLYREF_SIZE];
3361 for (i = 0; i < table->rows; ++i) {
3362 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3364 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3365 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3367 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3368 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3370 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3371 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3373 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3374 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3376 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3377 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3381 #define INVALID_FILE_FLAGS_BITS ~(1)
3383 verify_file_table (VerifyContext *ctx)
3385 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3386 guint32 data [MONO_FILE_SIZE];
3389 for (i = 0; i < table->rows; ++i) {
3390 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3392 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3393 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3395 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3396 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3398 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3399 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3403 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3405 verify_exportedtype_table (VerifyContext *ctx)
3407 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3408 guint32 data [MONO_EXP_TYPE_SIZE];
3411 for (i = 0; i < table->rows; ++i) {
3412 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3414 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3415 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3417 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3418 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3420 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3421 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3423 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3424 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3426 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3427 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3429 /*nested type can't have a namespace*/
3430 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3431 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3435 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3437 verify_manifest_resource_table (VerifyContext *ctx)
3439 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3440 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3441 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3442 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3445 resources_size = ch->ch_resources.size;
3447 for (i = 0; i < table->rows; ++i) {
3448 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3450 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3451 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3453 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3454 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3456 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3457 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3459 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3460 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3462 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3463 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3465 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3466 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])));
3468 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3469 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3471 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3472 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3477 verify_nested_class_table (VerifyContext *ctx)
3479 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3480 guint32 data [MONO_NESTED_CLASS_SIZE];
3483 for (i = 0; i < table->rows; ++i) {
3484 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3486 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3487 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3488 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3489 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3490 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3491 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3495 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3497 verify_generic_param_table (VerifyContext *ctx)
3499 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3500 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3501 int i, param_number = 0;
3503 for (i = 0; i < table->rows; ++i) {
3504 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3506 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3507 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3509 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3510 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3512 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3513 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3515 token = data [MONO_GENERICPARAM_OWNER];
3517 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3518 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3520 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3521 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3523 if (token != last_token) {
3528 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3529 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));
3536 verify_method_spec_table (VerifyContext *ctx)
3538 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3539 guint32 data [MONO_METHODSPEC_SIZE];
3542 for (i = 0; i < table->rows; ++i) {
3543 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3545 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3546 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3548 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3549 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3551 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3552 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3557 verify_method_spec_table_full (VerifyContext *ctx)
3559 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3560 guint32 data [MONO_METHODSPEC_SIZE];
3563 for (i = 0; i < table->rows; ++i) {
3564 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3566 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3567 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3572 verify_generic_param_constraint_table (VerifyContext *ctx)
3574 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3575 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3578 for (i = 0; i < table->rows; ++i) {
3579 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3581 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3582 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_TABLE_GENERICPARAM]));
3584 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3585 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3587 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3588 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3595 const char *name_space;
3596 guint32 resolution_scope;
3600 typedef_hash (gconstpointer _key)
3602 const TypeDefUniqueId *key = _key;
3603 return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3607 typedef_equals (gconstpointer _a, gconstpointer _b)
3609 const TypeDefUniqueId *a = _a;
3610 const TypeDefUniqueId *b = _b;
3611 return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3615 verify_typedef_table_global_constraints (VerifyContext *ctx)
3618 guint32 data [MONO_TYPEDEF_SIZE];
3619 guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3620 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3621 MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3622 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3624 for (i = 0; i < table->rows; ++i) {
3626 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3627 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3629 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3630 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3631 type->resolution_scope = 0;
3633 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3634 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3635 int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3636 g_assert (res >= 0);
3638 mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3639 type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3642 if (g_hash_table_lookup (unique_types, type)) {
3643 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));
3644 g_hash_table_destroy (unique_types);
3648 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3651 g_hash_table_destroy (unique_types);
3655 verify_typeref_table_global_constraints (VerifyContext *ctx)
3658 guint32 data [MONO_TYPEREF_SIZE];
3659 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3660 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3662 for (i = 0; i < table->rows; ++i) {
3663 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3664 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3666 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3667 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3668 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3670 if (g_hash_table_lookup (unique_types, type)) {
3671 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));
3672 g_hash_table_destroy (unique_types);
3676 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3679 g_hash_table_destroy (unique_types);
3683 verify_tables_data_global_constraints (VerifyContext *ctx)
3685 verify_typedef_table_global_constraints (ctx);
3689 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3691 verify_typeref_table_global_constraints (ctx);
3695 verify_tables_data (VerifyContext *ctx)
3697 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3698 guint32 size = 0, tables_offset;
3701 for (i = 0; i < 0x2D; ++i) {
3702 MonoTableInfo *table = &ctx->image->tables [i];
3704 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3705 if (tmp_size < size) {
3713 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3715 tables_offset = ctx->image->tables_base - ctx->data;
3716 if (!bounds_check_offset (&tables_area, tables_offset, size))
3717 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)));
3719 verify_module_table (ctx);
3721 verify_typeref_table (ctx);
3723 verify_typedef_table (ctx);
3725 verify_field_table (ctx);
3727 verify_method_table (ctx);
3729 verify_param_table (ctx);
3731 verify_interfaceimpl_table (ctx);
3733 verify_memberref_table (ctx);
3735 verify_constant_table (ctx);
3737 verify_cattr_table (ctx);
3739 verify_field_marshal_table (ctx);
3741 verify_decl_security_table (ctx);
3743 verify_class_layout_table (ctx);
3745 verify_field_layout_table (ctx);
3747 verify_standalonesig_table (ctx);
3749 verify_eventmap_table (ctx);
3751 verify_event_table (ctx);
3753 verify_propertymap_table (ctx);
3755 verify_property_table (ctx);
3757 verify_methodimpl_table (ctx);
3759 verify_moduleref_table (ctx);
3761 verify_typespec_table (ctx);
3763 verify_implmap_table (ctx);
3765 verify_fieldrva_table (ctx);
3767 verify_assembly_table (ctx);
3769 verify_assemblyref_table (ctx);
3771 verify_file_table (ctx);
3773 verify_exportedtype_table (ctx);
3775 verify_manifest_resource_table (ctx);
3777 verify_nested_class_table (ctx);
3779 verify_generic_param_table (ctx);
3781 verify_method_spec_table (ctx);
3783 verify_generic_param_constraint_table (ctx);
3785 verify_tables_data_global_constraints (ctx);
3789 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3791 memset (ctx, 0, sizeof (VerifyContext));
3793 ctx->report_error = report_error;
3794 ctx->report_warning = FALSE; //export this setting in the API
3796 ctx->size = image->raw_data_len;
3797 ctx->data = image->raw_data;
3801 cleanup_context (VerifyContext *ctx, GSList **error_list)
3803 g_free (ctx->sections);
3805 *error_list = ctx->errors;
3807 mono_free_verify_list (ctx->errors);
3812 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3814 g_free (ctx->sections);
3816 MonoVerifyInfo *info = ctx->errors->data;
3817 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3818 mono_free_verify_list (ctx->errors);
3824 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3828 if (!mono_verifier_is_enabled_for_image (image))
3831 init_verify_context (&ctx, image, error_list != NULL);
3832 ctx.stage = STAGE_PE;
3834 verify_msdos_header (&ctx);
3836 verify_pe_header (&ctx);
3838 verify_pe_optional_header (&ctx);
3840 load_section_table (&ctx);
3842 load_data_directories (&ctx);
3844 verify_import_table (&ctx);
3846 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3847 verify_resources_table (&ctx);
3850 return cleanup_context (&ctx, error_list);
3854 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3858 if (!mono_verifier_is_enabled_for_image (image))
3861 init_verify_context (&ctx, image, error_list != NULL);
3862 ctx.stage = STAGE_CLI;
3864 verify_cli_header (&ctx);
3866 verify_metadata_header (&ctx);
3868 verify_tables_schema (&ctx);
3871 return cleanup_context (&ctx, error_list);
3876 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3877 * Other verification checks are meant to be done lazily by the runtime. Those include:
3878 * blob items (signatures, method headers, custom attributes, etc)
3879 * type semantics related
3881 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3883 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3884 * operation still need more checking.
3887 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3891 if (!mono_verifier_is_enabled_for_image (image))
3894 init_verify_context (&ctx, image, error_list != NULL);
3895 ctx.stage = STAGE_TABLES;
3897 verify_tables_data (&ctx);
3899 return cleanup_context (&ctx, error_list);
3904 * Verifies all other constraints.
3907 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3911 if (!mono_verifier_is_enabled_for_image (image))
3914 init_verify_context (&ctx, image, error_list != NULL);
3915 ctx.stage = STAGE_TABLES;
3917 verify_typedef_table_full (&ctx);
3919 verify_field_table_full (&ctx);
3921 verify_method_table_full (&ctx);
3923 verify_memberref_table_full (&ctx);
3925 verify_cattr_table_full (&ctx);
3927 verify_field_marshal_table_full (&ctx);
3929 verify_decl_security_table_full (&ctx);
3931 verify_standalonesig_table_full (&ctx);
3933 verify_event_table_full (&ctx);
3935 verify_typespec_table_full (&ctx);
3937 verify_method_spec_table_full (&ctx);
3939 verify_tables_data_global_constraints_full (&ctx);
3942 return cleanup_context (&ctx, error_list);
3946 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3950 if (!mono_verifier_is_enabled_for_image (image))
3953 init_verify_context (&ctx, image, error_list != NULL);
3954 ctx.stage = STAGE_TABLES;
3956 is_valid_field_signature (&ctx, offset);
3957 return cleanup_context (&ctx, error_list);
3961 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3964 guint32 locals_token;
3966 if (!mono_verifier_is_enabled_for_image (image))
3969 init_verify_context (&ctx, image, error_list != NULL);
3970 ctx.stage = STAGE_TABLES;
3972 is_valid_method_header (&ctx, offset, &locals_token);
3974 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
3975 is_valid_standalonesig_blob (&ctx, sig_offset);
3978 return cleanup_context (&ctx, error_list);
3982 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
3986 mono_error_init (error);
3988 if (!mono_verifier_is_enabled_for_image (image))
3991 init_verify_context (&ctx, image, TRUE);
3992 ctx.stage = STAGE_TABLES;
3994 is_valid_method_signature (&ctx, offset);
3995 /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
3996 return cleanup_context_checked (&ctx, error);
4000 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
4004 if (!mono_verifier_is_enabled_for_image (image))
4007 init_verify_context (&ctx, image, error_list != NULL);
4008 ctx.stage = STAGE_TABLES;
4010 is_valid_method_or_field_signature (&ctx, offset);
4011 return cleanup_context (&ctx, error_list);
4015 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4019 if (!mono_verifier_is_enabled_for_image (image))
4022 init_verify_context (&ctx, image, error_list != NULL);
4023 ctx.stage = STAGE_TABLES;
4025 is_valid_standalonesig_blob (&ctx, offset);
4026 return cleanup_context (&ctx, error_list);
4030 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4034 if (!mono_verifier_is_enabled_for_image (image))
4037 init_verify_context (&ctx, image, error_list != NULL);
4038 ctx.stage = STAGE_TABLES;
4041 is_valid_typespec_blob (&ctx, offset);
4042 return cleanup_context (&ctx, error_list);
4046 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4050 if (!mono_verifier_is_enabled_for_image (image))
4053 init_verify_context (&ctx, image, error_list != NULL);
4054 ctx.stage = STAGE_TABLES;
4056 is_valid_methodspec_blob (&ctx, offset);
4057 return cleanup_context (&ctx, error_list);
4061 verify_user_string (VerifyContext *ctx, guint32 offset)
4063 OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4064 guint32 entry_size, bytes;
4066 if (heap_us.size < offset)
4067 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4069 if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4070 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4072 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4073 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4075 entry_size += bytes;
4077 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4078 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4082 mono_verifier_verify_string_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 verify_user_string (&ctx, offset);
4094 return cleanup_context (&ctx, error_list);
4098 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4102 if (!mono_verifier_is_enabled_for_image (image))
4105 init_verify_context (&ctx, image, error_list != NULL);
4106 ctx.stage = STAGE_TABLES;
4108 is_valid_cattr_blob (&ctx, offset);
4110 return cleanup_context (&ctx, error_list);
4114 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4118 if (!mono_verifier_is_enabled_for_image (image))
4121 init_verify_context (&ctx, image, error_list != NULL);
4122 ctx.stage = STAGE_TABLES;
4124 is_valid_cattr_content (&ctx, ctor, (const char*)data, size);
4126 return cleanup_context (&ctx, error_list);
4130 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4132 MonoMethodSignature *original_sig;
4133 if (!mono_verifier_is_enabled_for_image (image))
4136 original_sig = mono_method_signature (method);
4137 if (original_sig->call_convention == MONO_CALL_VARARG) {
4138 if (original_sig->hasthis != signature->hasthis)
4140 if (original_sig->call_convention != signature->call_convention)
4142 if (original_sig->explicit_this != signature->explicit_this)
4144 if (original_sig->call_convention != signature->call_convention)
4146 if (original_sig->pinvoke != signature->pinvoke)
4148 if (original_sig->sentinelpos != signature->sentinelpos)
4150 } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4159 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4165 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4171 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4177 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4183 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4189 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4195 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4197 mono_error_init (error);
4202 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
4208 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4214 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4220 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4226 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4232 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4238 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4244 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4250 #endif /* DISABLE_VERIFIER */