3 * Metadata verfication support
6 * Mono Project (http://www.mono-project.com)
8 * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11 #include <mono/metadata/object-internals.h>
12 #include <mono/metadata/verify.h>
13 #include <mono/metadata/verify-internals.h>
14 #include <mono/metadata/opcodes.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/reflection.h>
17 #include <mono/metadata/debug-helpers.h>
18 #include <mono/metadata/mono-endian.h>
19 #include <mono/metadata/metadata.h>
20 #include <mono/metadata/metadata-internals.h>
21 #include <mono/metadata/class-internals.h>
22 #include <mono/metadata/tokentype.h>
23 #include <mono/metadata/security-manager.h>
24 #include <mono/metadata/security-core-clr.h>
25 #include <mono/metadata/cil-coff.h>
26 #include <mono/metadata/attrdefs.h>
27 #include <mono/utils/strenc.h>
28 #include <mono/utils/mono-error-internals.h>
29 #include <mono/utils/bsearch.h>
34 #ifndef DISABLE_VERIFIER
36 TODO add fail fast mode
37 TODO add PE32+ support
38 TODO verify the entry point RVA and content.
39 TODO load_section_table and load_data_directories must take PE32+ into account
40 TODO add section relocation support
41 TODO verify the relocation table, since we really don't use, no need so far.
42 TODO do full PECOFF resources verification
43 TODO verify in the CLI header entry point and resources
44 TODO implement null token typeref validation
45 TODO verify table wide invariants for typedef (sorting and uniqueness)
46 TODO implement proper authenticode data directory validation
47 TODO verify properties that require multiple tables to be valid
48 FIXME use subtraction based bounds checking to avoid overflows
49 FIXME get rid of metadata_streams and other fields from VerifyContext
52 #ifdef MONO_VERIFIER_DEBUG
53 #define VERIFIER_DEBUG(code) do { code; } while (0)
55 #define VERIFIER_DEBUG(code)
58 #define INVALID_OFFSET ((guint32)-1)
59 #define INVALID_ADDRESS 0xffffffff
69 RESOURCE_TABLE_IDX = 2,
70 CERTIFICATE_TABLE_IDX = 4,
71 RELOCATION_TABLE_IDX = 5,
85 #define INVALID_TABLE (0xFF)
86 /*format: number of bits, number of tables, tables{n. tables} */
87 const static unsigned char coded_index_desc[] = {
88 #define TYPEDEF_OR_REF_DESC (0)
95 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
102 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
110 MONO_TABLE_INTERFACEIMPL,
111 MONO_TABLE_MEMBERREF,
113 MONO_TABLE_DECLSECURITY,
116 MONO_TABLE_STANDALONESIG,
117 MONO_TABLE_MODULEREF,
120 MONO_TABLE_ASSEMBLYREF,
122 MONO_TABLE_EXPORTEDTYPE,
123 MONO_TABLE_MANIFESTRESOURCE,
124 MONO_TABLE_GENERICPARAM,
126 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
132 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
139 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
144 MONO_TABLE_MODULEREF,
148 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
154 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
158 MONO_TABLE_MEMBERREF,
160 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
166 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
170 MONO_TABLE_ASSEMBLYREF,
171 MONO_TABLE_EXPORTEDTYPE,
173 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
179 MONO_TABLE_MEMBERREF,
182 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
186 MONO_TABLE_MODULEREF,
187 MONO_TABLE_ASSEMBLYREF,
190 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
200 guint32 translated_offset;
212 guint32 rellocationsRVA;
213 guint16 numberOfRelocations;
228 gboolean report_error;
229 gboolean report_warning;
232 DataDirectory data_directories [16];
233 guint32 section_count;
234 SectionHeader *sections;
236 OffsetAndSize metadata_streams [5]; //offset from begin of the image
239 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
241 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
242 vinfo->info.status = __status; \
243 vinfo->info.message = ( __msg); \
244 vinfo->exception_type = (__exception); \
245 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
248 #define ADD_WARNING(__ctx, __msg) \
250 if ((__ctx)->report_warning) { \
251 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
252 (__ctx)->valid = 0; \
257 #define ADD_ERROR_NO_RETURN(__ctx, __msg) \
259 if ((__ctx)->report_error) \
260 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
261 (__ctx)->valid = 0; \
264 #define ADD_ERROR(__ctx, __msg) \
266 if ((__ctx)->report_error) \
267 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
268 (__ctx)->valid = 0; \
272 #define FAIL(__ctx, __msg) \
274 if ((__ctx)->report_error) \
275 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
276 (__ctx)->valid = 0; \
280 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
282 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
284 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
285 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
287 #if SIZEOF_VOID_P == 4
288 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
290 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
293 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
294 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
297 dword_align (const char *ptr)
299 #if SIZEOF_VOID_P == 8
300 return (const char *) (((guint64) (ptr + 3)) & ~3);
302 return (const char *) (((guint32) (ptr + 3)) & ~3);
307 add_from_mono_error (VerifyContext *ctx, MonoError *error)
309 if (mono_error_ok (error))
312 ADD_ERROR (ctx, g_strdup (mono_error_get_message (error)));
313 mono_error_cleanup (error);
317 pe_signature_offset (VerifyContext *ctx)
319 return read32 (ctx->data + 0x3c);
323 pe_header_offset (VerifyContext *ctx)
325 return read32 (ctx->data + 0x3c) + 4;
329 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
333 if (rva + size < rva) //overflow
336 if (ctx->stage > STAGE_PE) {
337 MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
338 const int top = iinfo->cli_section_count;
339 MonoSectionTable *tables = iinfo->cli_section_tables;
342 for (i = 0; i < top; i++) {
343 guint32 base = tables->st_virtual_address;
344 guint32 end = base + tables->st_raw_data_size;
346 if (rva >= base && rva + size <= end)
349 /*if ((addr >= tables->st_virtual_address) &&
350 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
352 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
362 for (i = 0; i < ctx->section_count; ++i) {
363 guint32 base = ctx->sections [i].baseRVA;
364 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
365 if (rva >= base && rva + size <= end)
372 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
374 if (dir->translated_offset > offset)
376 if (dir->size < size)
378 return offset + size <= dir->translated_offset + dir->size;
382 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
384 if (off->offset > offset)
387 if (off->size < size)
390 return offset + size <= off->offset + off->size;
394 translate_rva (VerifyContext *ctx, guint32 rva)
398 if (ctx->stage > STAGE_PE)
399 return mono_cli_rva_image_map (ctx->image, rva);
404 for (i = 0; i < ctx->section_count; ++i) {
405 guint32 base = ctx->sections [i].baseRVA;
406 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
407 if (rva >= base && rva <= end) {
408 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
410 return res >= ctx->size ? INVALID_OFFSET : res;
414 return INVALID_OFFSET;
418 verify_msdos_header (VerifyContext *ctx)
422 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
423 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
424 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
425 lfanew = pe_signature_offset (ctx);
426 if (lfanew > ctx->size - 4)
427 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
431 verify_pe_header (VerifyContext *ctx)
433 guint32 offset = pe_signature_offset (ctx);
434 const char *pe_header = ctx->data + offset;
435 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
436 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
440 if (offset > ctx->size - 20)
441 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
442 if (read16 (pe_header) != 0x14c)
443 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
447 verify_pe_optional_header (VerifyContext *ctx)
449 guint32 offset = pe_header_offset (ctx);
450 guint32 header_size, file_alignment;
451 const char *pe_header = ctx->data + offset;
452 const char *pe_optional_header = pe_header + 20;
454 header_size = read16 (pe_header + 16);
457 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
458 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
460 if (offset > ctx->size - header_size || header_size > ctx->size)
461 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
463 if (read16 (pe_optional_header) == 0x10b) {
464 if (header_size != 224)
465 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
467 /* LAMESPEC MS plays around this value and ignore it during validation
468 if (read32 (pe_optional_header + 28) != 0x400000)
469 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
470 if (read32 (pe_optional_header + 32) != 0x2000)
471 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
472 file_alignment = read32 (pe_optional_header + 36);
473 if (file_alignment != 0x200 && file_alignment != 0x1000)
474 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
475 /* All the junk in the middle is irrelevant, specially for mono. */
476 if (read32 (pe_optional_header + 92) > 0x10)
477 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
479 if (read16 (pe_optional_header) == 0x20B)
480 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
482 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
487 load_section_table (VerifyContext *ctx)
490 SectionHeader *sections;
491 guint32 offset = pe_header_offset (ctx);
492 const char *ptr = ctx->data + offset;
493 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
495 offset += 244;/*FIXME, this constant is different under PE32+*/
498 if (num_sections * 40 > ctx->size - offset)
499 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
501 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
502 for (i = 0; i < num_sections; ++i) {
503 sections [i].size = read32 (ptr + 8);
504 sections [i].baseRVA = read32 (ptr + 12);
505 sections [i].baseOffset = read32 (ptr + 20);
506 sections [i].rellocationsRVA = read32 (ptr + 24);
507 sections [i].numberOfRelocations = read16 (ptr + 32);
511 ptr = ctx->data + offset; /*reset it to the beggining*/
512 for (i = 0; i < num_sections; ++i) {
513 guint32 raw_size, flags;
514 if (sections [i].baseOffset == 0)
515 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
516 if (sections [i].baseOffset >= ctx->size)
517 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
518 if (sections [i].size > ctx->size - sections [i].baseOffset)
519 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
521 raw_size = read32 (ptr + 16);
522 if (raw_size < sections [i].size)
523 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
525 if (raw_size > ctx->size - sections [i].baseOffset)
526 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
528 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
529 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
531 flags = read32 (ptr + 36);
532 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
533 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
534 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
541 is_valid_data_directory (int i)
543 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
544 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
548 load_data_directories (VerifyContext *ctx)
550 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
551 const char *ptr = ctx->data + offset;
554 for (i = 0; i < 16; ++i) {
555 guint32 rva = read32 (ptr);
556 guint32 size = read32 (ptr + 4);
558 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
559 if (i == CERTIFICATE_TABLE_IDX) {
563 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
564 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
566 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
567 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
569 ctx->data_directories [i].rva = rva;
570 ctx->data_directories [i].size = size;
571 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
577 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
579 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
582 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
585 guint32 hint_table_rva;
587 import_rva = translate_rva (ctx, import_rva);
588 g_assert (import_rva != INVALID_OFFSET);
590 hint_table_rva = read32 (ctx->data + import_rva);
591 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
592 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
594 hint_table_rva = translate_rva (ctx, hint_table_rva);
595 g_assert (hint_table_rva != INVALID_OFFSET);
596 ptr = ctx->data + hint_table_rva + 2;
598 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
599 char name[SIZE_OF_CORMAIN];
600 memcpy (name, ptr, SIZE_OF_CORMAIN);
601 name [SIZE_OF_CORMAIN - 1] = 0;
602 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
607 verify_import_table (VerifyContext *ctx)
609 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
610 guint32 offset = it.translated_offset;
611 const char *ptr = ctx->data + offset;
612 guint32 name_rva, ilt_rva, iat_rva;
614 g_assert (offset != INVALID_OFFSET);
617 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
619 ilt_rva = read32 (ptr);
620 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
621 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
623 name_rva = read32 (ptr + 12);
624 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
625 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
627 iat_rva = read32 (ptr + 16);
629 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
630 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
632 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
633 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));
637 name_rva = translate_rva (ctx, name_rva);
638 g_assert (name_rva != INVALID_OFFSET);
639 ptr = ctx->data + name_rva;
641 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
642 char name[SIZE_OF_MSCOREE];
643 memcpy (name, ptr, SIZE_OF_MSCOREE);
644 name [SIZE_OF_MSCOREE - 1] = 0;
645 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
650 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
655 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
659 verify_resources_table (VerifyContext *ctx)
661 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
663 guint16 named_entries, id_entries;
670 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));
672 offset = it.translated_offset;
673 ptr = ctx->data + offset;
675 g_assert (offset != INVALID_OFFSET);
677 named_entries = read16 (ptr + 12);
678 id_entries = read16 (ptr + 14);
680 if ((named_entries + id_entries) * 8 + 16 > it.size)
681 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));
683 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
684 if (named_entries || id_entries)
685 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
689 /*----------nothing from here on can use data_directory---*/
692 get_data_dir (VerifyContext *ctx, int idx)
694 MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
695 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
699 res.rva = entry->rva;
700 res.size = entry->size;
701 res.translated_offset = translate_rva (ctx, res.rva);
706 verify_cli_header (VerifyContext *ctx)
708 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
714 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
717 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
719 offset = it.translated_offset;
720 ptr = ctx->data + offset;
722 g_assert (offset != INVALID_OFFSET);
724 if (read16 (ptr) != 72)
725 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
727 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
728 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
731 if (!read32 (ptr + 8) || !read32 (ptr + 12))
732 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
734 if ((read32 (ptr + 16) & ~0x0003000B) != 0)
735 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
738 for (i = 0; i < 6; ++i) {
739 guint32 rva = read32 (ptr);
740 guint32 size = read32 (ptr + 4);
742 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
743 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
748 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
753 pad4 (guint32 offset)
755 if (offset & 0x3) //pad to the next 4 byte boundary
756 offset = (offset & ~0x3) + 4;
761 verify_metadata_header (VerifyContext *ctx)
764 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
765 guint32 offset, section_count;
768 offset = it.translated_offset;
769 ptr = ctx->data + offset;
770 g_assert (offset != INVALID_OFFSET);
772 //build a directory entry for the metadata root
774 it.rva = read32 (ptr);
776 it.size = read32 (ptr);
777 it.translated_offset = offset = translate_rva (ctx, it.rva);
779 ptr = ctx->data + offset;
780 g_assert (offset != INVALID_OFFSET);
783 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
785 if (read32 (ptr) != 0x424A5342)
786 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
788 offset = pad4 (offset + 16 + read32 (ptr + 12));
790 if (!bounds_check_datadir (&it, offset, 4))
791 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));
793 ptr = ctx->data + offset; //move to streams header
795 section_count = read16 (ptr + 2);
796 if (section_count < 2)
797 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
802 for (i = 0; i < section_count; ++i) {
803 guint32 stream_off, stream_size;
804 int string_size, stream_idx;
806 if (!bounds_check_datadir (&it, offset, 8))
807 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));
809 stream_off = it.translated_offset + read32 (ptr);
810 stream_size = read32 (ptr + 4);
812 if (!bounds_check_datadir (&it, stream_off, stream_size))
813 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
818 for (string_size = 0; string_size < 32; ++string_size) {
819 if (!bounds_check_datadir (&it, offset++, 1))
820 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
821 if (!ptr [string_size])
825 if (ptr [string_size])
826 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
828 if (!strncmp ("#Strings", ptr, 9))
829 stream_idx = STRINGS_STREAM;
830 else if (!strncmp ("#US", ptr, 4))
831 stream_idx = USER_STRINGS_STREAM;
832 else if (!strncmp ("#Blob", ptr, 6))
833 stream_idx = BLOB_STREAM;
834 else if (!strncmp ("#GUID", ptr, 6))
835 stream_idx = GUID_STREAM;
836 else if (!strncmp ("#~", ptr, 3))
837 stream_idx = TILDE_STREAM;
839 ADD_WARNING (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
840 offset = pad4 (offset);
841 ptr = ctx->data + offset;
845 if (ctx->metadata_streams [stream_idx].offset != 0)
846 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
848 ctx->metadata_streams [stream_idx].offset = stream_off;
849 ctx->metadata_streams [stream_idx].size = stream_size;
851 offset = pad4 (offset);
852 ptr = ctx->data + offset;
855 if (!ctx->metadata_streams [TILDE_STREAM].size)
856 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
857 if (!ctx->metadata_streams [GUID_STREAM].size)
858 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
862 verify_tables_schema (VerifyContext *ctx)
864 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
865 unsigned offset = tables_area.offset;
866 const char *ptr = ctx->data + offset;
867 guint64 valid_tables;
871 if (tables_area.size < 24)
872 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
874 if (ptr [4] != 2 && ptr [4] != 1)
875 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
877 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
879 if ((ptr [6] & ~0x7) != 0)
880 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]));
882 valid_tables = read64 (ptr + 8);
884 for (i = 0; i < 64; ++i) {
885 if (!(valid_tables & ((guint64)1 << i)))
888 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
889 Unused: 0x1E 0x1F 0x2D-0x3F
890 We don't care about the MS extensions.*/
891 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
892 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i));
893 if (i == 0x1E || i == 0x1F || i >= 0x2D)
894 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
898 if (tables_area.size < 24 + count * 4)
899 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));
902 for (i = 0; i < 64; ++i) {
903 if (valid_tables & ((guint64)1 << i)) {
904 guint32 row_count = read32 (ptr);
905 if (row_count > (1 << 24) - 1)
906 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
912 /*----------nothing from here on can use data_directory or metadata_streams ---*/
915 get_col_offset (VerifyContext *ctx, int table, int column)
917 guint32 bitfield = ctx->image->tables [table].size_bitfield;
921 offset += mono_metadata_table_size (bitfield, column);
927 get_col_size (VerifyContext *ctx, int table, int column)
929 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
933 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
936 res.offset = header->data - ctx->data;
937 res.size = header->size;
943 is_valid_string_full_with_image (MonoImage *image, guint32 offset, gboolean allow_empty)
945 guint32 heap_offset = (char*)image->heap_strings.data - image->raw_data;
946 guint32 heap_size = image->heap_strings.size;
949 const char *data = image->raw_data + heap_offset;
951 if (offset >= heap_size)
953 if (CHECK_ADDP_OVERFLOW_UN (data, offset))
956 if (!mono_utf8_validate_and_len_with_bounds (data + offset, heap_size - offset, &length, NULL))
958 return allow_empty || length > 0;
963 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
965 return is_valid_string_full_with_image (ctx->image, offset, allow_empty);
969 is_valid_string (VerifyContext *ctx, guint32 offset)
971 return is_valid_string_full (ctx, offset, TRUE);
975 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
977 return is_valid_string_full (ctx, offset, FALSE);
981 is_valid_guid (VerifyContext *ctx, guint32 offset)
983 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
984 return guids.size >= 8 && guids.size - 8 >= offset;
988 get_coded_index_token (int token_kind, guint32 coded_token)
990 guint32 bits = coded_index_desc [token_kind];
991 return coded_token >> bits;
995 get_coded_index_table (int kind, guint32 coded_token)
997 guint32 idx, bits = coded_index_desc [kind];
999 idx = coded_token & ((1 << bits) - 1);
1000 return coded_index_desc [kind + idx];
1004 make_coded_token (int kind, guint32 table, guint32 table_idx)
1006 guint32 bits = coded_index_desc [kind++];
1007 guint32 tables = coded_index_desc [kind++];
1009 for (i = 0; i < tables; ++i) {
1010 if (coded_index_desc [kind++] == table)
1011 return ((table_idx + 1) << bits) | i;
1013 g_assert_not_reached ();
1018 is_valid_coded_index_with_image (MonoImage *image, int token_kind, guint32 coded_token)
1020 guint32 bits = coded_index_desc [token_kind++];
1021 guint32 table_count = coded_index_desc [token_kind++];
1022 guint32 table = coded_token & ((1 << bits) - 1);
1023 guint32 token = coded_token >> bits;
1025 if (table >= table_count)
1028 /*token_kind points to the first table idx*/
1029 table = coded_index_desc [token_kind + table];
1031 if (table == INVALID_TABLE)
1033 return token <= image->tables [table].rows;
1037 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
1039 return is_valid_coded_index_with_image (ctx->image, token_kind, coded_token);
1046 MonoTableInfo *table;
1050 token_locator (const void *a, const void *b)
1052 RowLocator *loc = (RowLocator *)a;
1053 unsigned const char *row = (unsigned const char *)b;
1054 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1056 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1057 return (int)loc->token - (int)token;
1061 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1063 MonoTableInfo *tinfo = &ctx->image->tables [table];
1065 const char *res, *base;
1066 locator.token = coded_token;
1067 locator.col_offset = get_col_offset (ctx, table, column);
1068 locator.col_size = get_col_size (ctx, table, column);
1069 locator.table = tinfo;
1073 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) );
1074 res = (const char *)mono_binary_search (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1078 return (res - base) / tinfo->row_size;
1081 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1083 get_string_ptr (VerifyContext *ctx, guint offset)
1085 return ctx->image->heap_strings.data + offset;
1088 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1090 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1093 return strcmp (str, "");
1095 return strcmp (str, get_string_ptr (ctx, offset));
1099 mono_verifier_is_corlib (MonoImage *image)
1101 gboolean trusted_location = !mono_security_core_clr_enabled () ?
1102 TRUE : mono_security_core_clr_is_platform_image (image);
1104 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1108 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1110 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1114 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1117 const unsigned char *ptr = (const unsigned char *)_ptr;
1125 if ((b & 0x80) == 0) {
1128 } else if ((b & 0x40) == 0) {
1132 *value = ((b & 0x3f) << 8 | ptr [1]);
1137 *value = ((b & 0x1f) << 24) |
1147 decode_signature_header (VerifyContext *ctx, guint32 offset, guint32 *size, const char **first_byte)
1149 MonoStreamHeader blob = ctx->image->heap_blob;
1150 guint32 value, enc_size;
1152 if (offset >= blob.size)
1155 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1158 if (CHECK_ADD4_OVERFLOW_UN (offset, enc_size))
1163 if (ADD_IS_GREATER_OR_OVF (offset, value, blob.size))
1167 *first_byte = blob.data + offset;
1172 safe_read (const char **_ptr, const char *limit, unsigned *dest, int size)
1174 const char *ptr = *_ptr;
1175 if (ptr + size > limit)
1179 *dest = *((guint8*)ptr);
1183 *dest = read16 (ptr);
1187 *dest = read32 (ptr);
1196 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1199 const char *ptr = *_ptr;
1200 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1205 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1206 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1207 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1208 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1211 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1214 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1217 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1219 const char *ptr = *_ptr;
1224 if (!safe_read8 (type, ptr, end))
1225 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1227 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1232 if (!safe_read_cint (token, ptr, end))
1233 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1235 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1236 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1244 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1246 const char *ptr = *_ptr;
1248 unsigned size, num, i;
1250 if (!safe_read8 (val, ptr, end))
1251 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1254 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1256 if (!safe_read_cint (size, ptr, end))
1257 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1259 for (i = 0; i < size; ++i) {
1260 if (!safe_read_cint (num, ptr, end))
1261 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1264 if (!safe_read_cint (size, ptr, end))
1265 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1267 for (i = 0; i < size; ++i) {
1268 if (!safe_read_cint (num, ptr, end))
1269 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1277 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1279 const char *ptr = *_ptr;
1281 unsigned count, token, i;
1283 if (!safe_read8 (type, ptr, end))
1284 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1286 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1287 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1289 if (!safe_read_cint (token, ptr, end))
1290 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1292 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1293 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1296 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1297 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1298 FAIL (ctx, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx->token));
1301 if (!safe_read_cint (count, ptr, end))
1302 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1305 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1307 for (i = 0; i < count; ++i) {
1308 if (!parse_custom_mods (ctx, &ptr, end))
1309 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1311 if (!parse_type (ctx, &ptr, end))
1312 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1319 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1321 const char *ptr = *_ptr;
1325 if (!safe_read8 (type, ptr, end))
1326 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1328 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1329 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1330 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1331 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1332 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1336 if (!parse_custom_mods (ctx, &ptr, end))
1337 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1339 if (!safe_read8 (type, ptr, end))
1340 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1342 if (type != MONO_TYPE_VOID) {
1344 if (!parse_type (ctx, &ptr, end))
1345 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1349 case MONO_TYPE_VALUETYPE:
1350 case MONO_TYPE_CLASS:
1351 if (!safe_read_cint (token, ptr, end))
1352 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1354 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token) || !get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1355 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1357 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, token))
1358 FAIL (ctx, g_strdup_printf ("Type: zero TypeDefOrRef token %x", token));
1360 if (mono_metadata_token_index (ctx->token) == get_coded_index_token (TYPEDEF_OR_REF_DESC, token) &&
1361 mono_metadata_token_table (ctx->token) == get_coded_index_table (TYPEDEF_OR_REF_DESC, token))
1362 FAIL (ctx, g_strdup_printf ("Type: Recursive type specification (%x). A type signature can't reference itself", ctx->token));
1367 case MONO_TYPE_MVAR:
1368 if (!safe_read_cint (token, ptr, end))
1369 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1372 case MONO_TYPE_ARRAY:
1373 if (!parse_type (ctx, &ptr, end))
1374 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1375 if (!parse_array_shape (ctx, &ptr, end))
1376 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1379 case MONO_TYPE_GENERICINST:
1380 if (!parse_generic_inst (ctx, &ptr, end))
1381 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1384 case MONO_TYPE_FNPTR:
1385 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1386 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1389 case MONO_TYPE_SZARRAY:
1390 if (!parse_custom_mods (ctx, &ptr, end))
1391 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1392 if (!parse_type (ctx, &ptr, end))
1393 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1401 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1406 if (!parse_custom_mods (ctx, _ptr, end))
1410 if (!safe_read8 (type, ptr, end))
1411 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1413 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1418 //it's a byref, update the cursor ptr
1419 if (type == MONO_TYPE_BYREF)
1422 return parse_type (ctx, _ptr, end);
1426 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1431 if (!parse_custom_mods (ctx, _ptr, end))
1435 if (!safe_read8 (type, ptr, end))
1436 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1438 if (type == MONO_TYPE_TYPEDBYREF) {
1443 //it's a byref, update the cursor ptr
1444 if (type == MONO_TYPE_BYREF) {
1446 if (!parse_custom_mods (ctx, _ptr, end))
1450 return parse_type (ctx, _ptr, end);
1454 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1457 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1458 const char *ptr = *_ptr;
1459 gboolean saw_sentinel = FALSE;
1461 if (!safe_read8 (cconv, ptr, end))
1462 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1465 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1467 if (allow_unmanaged) {
1468 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1469 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1470 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1471 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1473 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1474 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1476 if ((cconv & 0x10) && gparam_count == 0)
1477 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1479 if (allow_unmanaged && (cconv & 0x10))
1480 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1482 if (!safe_read_cint (param_count, ptr, end))
1483 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1485 if (!parse_return_type (ctx, &ptr, end))
1486 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1488 for (i = 0; i < param_count; ++i) {
1489 if (allow_sentinel) {
1490 if (!safe_read8 (type, ptr, end))
1491 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1493 if (type == MONO_TYPE_SENTINEL) {
1494 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1495 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1498 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1500 saw_sentinel = TRUE;
1506 if (!parse_param (ctx, &ptr, end))
1507 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1515 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1518 unsigned param_count = 0, i;
1519 const char *ptr = *_ptr;
1521 if (!safe_read8 (sig, ptr, end))
1522 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1524 if (sig != 0x08 && sig != 0x28)
1525 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1527 if (!safe_read_cint (param_count, ptr, end))
1528 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1530 if (!parse_custom_mods (ctx, &ptr, end))
1533 if (!parse_type (ctx, &ptr, end))
1534 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1536 for (i = 0; i < param_count; ++i) {
1537 if (!parse_custom_mods (ctx, &ptr, end))
1538 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1539 if (!parse_type (ctx, &ptr, end))
1540 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1548 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1550 const char *ptr = *_ptr;
1551 unsigned signature = 0;
1553 if (!safe_read8 (signature, ptr, end))
1554 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1556 if (signature != 0x06)
1557 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1559 if (!parse_custom_mods (ctx, &ptr, end))
1562 if (safe_read8 (signature, ptr, end)) {
1563 if (signature != MONO_TYPE_BYREF)
1568 return parse_type (ctx, _ptr, end);
1572 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1575 unsigned locals_count = 0, i;
1576 const char *ptr = *_ptr;
1578 if (!safe_read8 (sig, ptr, end))
1579 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1582 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1584 if (!safe_read_cint (locals_count, ptr, end))
1585 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1587 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1588 if (locals_count == 0)
1589 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1592 for (i = 0; i < locals_count; ++i) {
1593 if (!safe_read8 (sig, ptr, end))
1594 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1596 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1597 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1598 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1599 if (!safe_read8 (sig, ptr, end))
1600 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1603 if (sig == MONO_TYPE_BYREF) {
1604 if (!safe_read8 (sig, ptr, end))
1605 FAIL (ctx, g_strdup_printf ("Type: Not enough room for byref type for local %d", i));
1606 if (sig == MONO_TYPE_TYPEDBYREF)
1607 FAIL (ctx, g_strdup_printf ("Type: Invalid type typedref& for local %d", i));
1610 if (sig == MONO_TYPE_TYPEDBYREF)
1615 if (!parse_type (ctx, &ptr, end))
1616 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1624 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1627 unsigned signature = 0;
1628 const char *ptr = NULL, *end;
1630 if (!decode_signature_header (ctx, offset, &size, &ptr))
1631 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1634 if (!safe_read8 (signature, ptr, end))
1635 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1638 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1641 return parse_field (ctx, &ptr, end);
1645 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1648 const char *ptr = NULL, *end;
1650 if (!decode_signature_header (ctx, offset, &size, &ptr))
1651 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1654 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1658 is_valid_memberref_method_signature (VerifyContext *ctx, guint32 offset)
1661 const char *ptr = NULL, *end;
1663 if (!decode_signature_header (ctx, offset, &size, &ptr))
1664 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1667 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1672 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1675 unsigned signature = 0;
1676 const char *ptr = NULL, *end;
1678 if (!decode_signature_header (ctx, offset, &size, &ptr))
1679 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1682 if (!safe_read8 (signature, ptr, end))
1683 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1686 if (signature == 0x06)
1687 return parse_field (ctx, &ptr, end);
1689 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1693 is_valid_cattr_blob (VerifyContext *ctx, guint32 offset)
1696 unsigned prolog = 0;
1697 const char *ptr = NULL, *end;
1702 if (!decode_signature_header (ctx, offset, &size, &ptr))
1703 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1706 if (!safe_read16 (prolog, ptr, end))
1707 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1710 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1716 is_valid_cattr_type (MonoType *type)
1720 if (type->type == MONO_TYPE_OBJECT || (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_STRING))
1723 if (type->type == MONO_TYPE_VALUETYPE) {
1724 klass = mono_class_from_mono_type (type);
1725 return klass && klass->enumtype;
1728 if (type->type == MONO_TYPE_CLASS)
1729 return mono_class_from_mono_type (type) == mono_defaults.systemtype_class;
1735 is_valid_ser_string_full (VerifyContext *ctx, const char **str_start, guint32 *str_len, const char **_ptr, const char *end)
1738 const char *ptr = *_ptr;
1744 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1747 if (*ptr == (char)0xFF) {
1752 if (!safe_read_cint (size, ptr, end))
1753 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string size"));
1755 if (ADDP_IS_GREATER_OR_OVF (ptr, size, end))
1756 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for string"));
1766 is_valid_ser_string (VerifyContext *ctx, const char **_ptr, const char *end)
1768 const char *dummy_str;
1770 return is_valid_ser_string_full (ctx, &dummy_str, &dummy_int, _ptr, end);
1774 get_enum_by_encoded_name (VerifyContext *ctx, const char **_ptr, const char *end)
1778 const char *str_start = NULL;
1779 const char *ptr = *_ptr;
1781 guint32 str_len = 0;
1783 if (!is_valid_ser_string_full (ctx, &str_start, &str_len, &ptr, end))
1786 /*NULL or empty string*/
1787 if (str_start == NULL || str_len == 0) {
1788 ADD_ERROR_NO_RETURN (ctx, g_strdup ("CustomAttribute: Null or empty enum name"));
1792 enum_name = (char *)g_memdup (str_start, str_len + 1);
1793 enum_name [str_len] = 0;
1794 type = mono_reflection_type_from_name (enum_name, ctx->image);
1796 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name));
1802 klass = mono_class_from_mono_type (type);
1803 if (!klass || !klass->enumtype) {
1804 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass->name_space, klass->name));
1813 is_valid_fixed_param (VerifyContext *ctx, MonoType *mono_type, const char **_ptr, const char *end)
1816 const char *ptr = *_ptr;
1818 guint32 element_count, i;
1821 klass = mono_type->data.klass;
1822 type = mono_type->type;
1826 case MONO_TYPE_BOOLEAN:
1833 case MONO_TYPE_CHAR:
1847 case MONO_TYPE_STRING:
1849 return is_valid_ser_string (ctx, _ptr, end);
1851 case MONO_TYPE_OBJECT: {
1852 unsigned sub_type = 0;
1853 if (!safe_read8 (sub_type, ptr, end))
1854 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array type"));
1856 if (sub_type >= MONO_TYPE_BOOLEAN && sub_type <= MONO_TYPE_STRING) {
1860 if (sub_type == MONO_TYPE_ENUM) {
1861 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1865 klass = klass->element_class;
1866 type = klass->byval_arg.type;
1869 if (sub_type == 0x50) { /*Type*/
1871 return is_valid_ser_string (ctx, _ptr, end);
1873 if (sub_type == MONO_TYPE_SZARRAY) {
1874 MonoType simple_type = {{0}};
1876 if (!safe_read8 (etype, ptr, end))
1877 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
1879 if (etype == MONO_TYPE_ENUM) {
1880 klass = get_enum_by_encoded_name (ctx, &ptr, end);
1883 } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
1884 klass = mono_defaults.systemtype_class;
1885 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
1886 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : (MonoTypeEnum)etype;
1887 klass = mono_class_from_mono_type (&simple_type);
1889 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
1891 type = MONO_TYPE_SZARRAY;
1894 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type));
1898 case MONO_TYPE_CLASS:
1899 if (klass != mono_defaults.systemtype_class)
1900 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1902 return is_valid_ser_string (ctx, _ptr, end);
1904 case MONO_TYPE_VALUETYPE:
1905 if (!klass || !klass->enumtype)
1906 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass->name_space, klass->name));
1908 klass = klass->element_class;
1909 type = klass->byval_arg.type;
1912 case MONO_TYPE_SZARRAY:
1913 mono_type = &klass->byval_arg;
1914 if (!is_valid_cattr_type (mono_type))
1915 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass->name_space, klass->name));
1916 if (!safe_read32 (element_count, ptr, end))
1917 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass->name_space, klass->name));
1918 if (element_count == 0xFFFFFFFFu) {
1922 for (i = 0; i < element_count; ++i) {
1923 if (!is_valid_fixed_param (ctx, mono_type, &ptr, end))
1929 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type));
1932 if (ADDP_IS_GREATER_OR_OVF (ptr, elem_size, end))
1933 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for element"));
1934 *_ptr = ptr + elem_size;
1939 is_valid_cattr_content (VerifyContext *ctx, MonoMethod *ctor, const char *ptr, guint32 size)
1942 unsigned prolog = 0;
1944 MonoMethodSignature *sig;
1949 FAIL (ctx, g_strdup ("CustomAttribute: Invalid constructor"));
1951 sig = mono_method_signature_checked (ctor, &error);
1952 if (!mono_error_ok (&error)) {
1953 ADD_ERROR_NO_RETURN (ctx, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error)));
1954 mono_error_cleanup (&error);
1958 if (sig->sentinelpos != -1 || sig->call_convention == MONO_CALL_VARARG)
1959 FAIL (ctx, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1963 if (!safe_read16 (prolog, ptr, end))
1964 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1967 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1969 args = sig->param_count;
1970 for (i = 0; i < args; ++i) {
1971 MonoType *arg_type = sig->params [i];
1972 if (!is_valid_fixed_param (ctx, arg_type, &ptr, end))
1976 if (!safe_read16 (num_named, ptr, end))
1977 FAIL (ctx, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1979 for (i = 0; i < num_named; ++i) {
1980 MonoType *type, simple_type = {{0}};
1983 if (!safe_read8 (kind, ptr, end))
1984 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i));
1985 if (kind != 0x53 && kind != 0x54)
1986 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i, kind));
1987 if (!safe_read8 (kind, ptr, end))
1988 FAIL (ctx, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i));
1990 if (kind >= MONO_TYPE_BOOLEAN && kind <= MONO_TYPE_STRING) {
1991 simple_type.type = (MonoTypeEnum)kind;
1992 type = &simple_type;
1993 } else if (kind == MONO_TYPE_ENUM) {
1994 MonoClass *klass = get_enum_by_encoded_name (ctx, &ptr, end);
1997 type = &klass->byval_arg;
1998 } else if (kind == 0x50) {
1999 type = &mono_defaults.systemtype_class->byval_arg;
2000 } else if (kind == 0x51) {
2001 type = &mono_defaults.object_class->byval_arg;
2002 } else if (kind == MONO_TYPE_SZARRAY) {
2005 if (!safe_read8 (etype, ptr, end))
2006 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for array element type"));
2008 if (etype == MONO_TYPE_ENUM) {
2009 klass = get_enum_by_encoded_name (ctx, &ptr, end);
2012 } else if (etype == 0x50 || etype == MONO_TYPE_CLASS) {
2013 klass = mono_defaults.systemtype_class;
2014 } else if ((etype >= MONO_TYPE_BOOLEAN && etype <= MONO_TYPE_STRING) || etype == 0x51) {
2015 simple_type.type = etype == 0x51 ? MONO_TYPE_OBJECT : (MonoTypeEnum)etype;
2016 klass = mono_class_from_mono_type (&simple_type);
2018 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype));
2020 type = &mono_array_class_get (klass, 1)->byval_arg;
2022 FAIL (ctx, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind));
2025 if (!is_valid_ser_string (ctx, &ptr, end))
2028 if (!is_valid_fixed_param (ctx, type, &ptr, end))
2037 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
2039 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2040 //TODO do proper verification
2041 return blob.size >= 1 && blob.size - 1 >= offset;
2045 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
2047 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2048 //TODO do proper verification
2049 return blob.size >= 1 && blob.size - 1 >= offset;
2053 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
2056 unsigned signature = 0;
2057 const char *ptr = NULL, *end;
2059 if (!decode_signature_header (ctx, offset, &size, &ptr))
2060 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
2063 if (!safe_read8 (signature, ptr, end))
2064 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2067 if (signature == 0x07)
2068 return parse_locals_signature (ctx, &ptr, end);
2070 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2071 if (signature == 0x06)
2072 return parse_field (ctx, &ptr, end);
2074 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
2078 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
2081 const char *ptr = NULL, *end;
2083 if (!decode_signature_header (ctx, offset, &size, &ptr))
2084 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
2087 return parse_property_signature (ctx, &ptr, end);
2091 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
2094 const char *ptr = NULL, *end;
2097 if (!decode_signature_header (ctx, offset, &size, &ptr))
2098 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
2101 if (!parse_custom_mods (ctx, &ptr, end))
2104 if (!safe_read8 (type, ptr, end))
2105 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
2107 if (type == MONO_TYPE_BYREF) {
2108 if (!safe_read8 (type, ptr, end))
2109 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for byref type"));
2110 if (type == MONO_TYPE_TYPEDBYREF)
2111 FAIL (ctx, g_strdup ("TypeSpec: Invalid type typedref&"));
2114 if (type == MONO_TYPE_TYPEDBYREF)
2118 return parse_type (ctx, &ptr, end);
2122 is_valid_methodspec_blob (VerifyContext *ctx, guint32 offset)
2125 const char *ptr = NULL, *end;
2127 unsigned count = 0, i;
2129 if (!decode_signature_header (ctx, offset, &size, &ptr))
2130 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
2133 if (!safe_read8 (type, ptr, end))
2134 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
2137 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
2139 if (!safe_read_cint (count, ptr, end))
2140 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
2143 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
2145 for (i = 0; i < count; ++i) {
2146 if (!parse_custom_mods (ctx, &ptr, end))
2148 if (!parse_type (ctx, &ptr, end))
2149 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
2155 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
2157 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2158 guint32 entry_size, bytes;
2160 if (blob.size < offset)
2163 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2166 if (entry_size < minsize)
2169 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
2171 entry_size += bytes;
2173 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
2177 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
2179 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
2180 guint32 size, entry_size, bytes;
2182 if (blob.size < offset)
2183 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
2185 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
2186 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
2188 if (type == MONO_TYPE_STRING) {
2189 //String is encoded as: compressed_int:len len *bytes
2192 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
2193 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
2199 case MONO_TYPE_BOOLEAN:
2204 case MONO_TYPE_CHAR:
2212 case MONO_TYPE_CLASS:
2222 g_assert_not_reached ();
2225 if (size != entry_size)
2226 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
2230 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
2231 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
2233 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
2234 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2238 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2239 //only 0x01, 0x40 and 0x80 are allowed
2240 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2243 is_valid_method_header (VerifyContext *ctx, guint32 rva, guint32 *locals_token)
2245 unsigned local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
2246 unsigned header = 0;
2247 unsigned fat_header = 0, size = 0, max_stack;
2248 const char *ptr = NULL, *end;
2252 if (offset == INVALID_ADDRESS)
2253 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
2255 ptr = ctx->data + offset;
2256 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
2258 if (!safe_read8 (header, ptr, end))
2259 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
2261 switch (header & 0x3) {
2264 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
2267 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
2268 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
2273 if (!safe_read16 (fat_header, ptr, end))
2274 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
2276 size = (fat_header >> 12) & 0xF;
2278 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
2280 if (!safe_read16 (max_stack, ptr, end))
2281 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
2283 if (!safe_read32 (code_size, ptr, end))
2284 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
2286 if (!safe_read32 (local_vars_tok, ptr, end))
2287 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2289 if (local_vars_tok) {
2290 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
2291 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
2292 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
2293 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
2294 if (!(local_vars_tok & 0xFFFFFF))
2295 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature with zero index"));
2296 *locals_token = local_vars_tok & 0xFFFFFF;
2299 if (fat_header & FAT_HEADER_INVALID_FLAGS)
2300 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
2302 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
2303 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
2305 if (!(fat_header & 0x08))
2311 unsigned section_header = 0, section_size = 0;
2314 ptr = dword_align (ptr);
2315 if (!safe_read32 (section_header, ptr, end))
2316 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
2318 if (section_header & SECTION_HEADER_INVALID_FLAGS)
2319 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
2321 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
2322 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
2324 if (section_size < 4)
2325 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
2327 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2328 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
2330 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
2331 guint32 i, clauses = section_size / (is_fat ? 24 : 12);
2333 LAMEIMPL: MS emits section_size without accounting for header size.
2334 Mono does as the spec says. section_size is header + section
2335 MS's peverify happily accepts both.
2337 if ((clauses * (is_fat ? 24 : 12) != section_size) && (clauses * (is_fat ? 24 : 12) + 4 != section_size))
2338 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)));
2340 /* only verify the class token is verified as the rest is done by the IL verifier*/
2341 for (i = 0; i < clauses; ++i) {
2342 unsigned flags = *(unsigned char*)ptr;
2343 unsigned class_token = 0;
2344 ptr += (is_fat ? 20 : 8);
2345 if (!safe_read32 (class_token, ptr, end))
2346 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
2347 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
2348 guint table = mono_metadata_token_table (class_token);
2349 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
2350 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
2351 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
2352 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
2357 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
2364 verify_module_table (VerifyContext *ctx)
2366 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
2367 guint32 data [MONO_MODULE_SIZE];
2369 if (table->rows != 1)
2370 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
2372 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
2374 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
2375 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
2377 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
2378 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
2380 if (data [MONO_MODULE_ENC] != 0)
2381 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
2383 if (data [MONO_MODULE_ENCBASE] != 0)
2384 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
2388 verify_typeref_table (VerifyContext *ctx)
2390 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
2394 for (i = 0; i < table->rows; ++i) {
2395 mono_verifier_verify_typeref_row (ctx->image, i, &error);
2396 add_from_mono_error (ctx, &error);
2400 /*bits 9,11,14,15,19,21,24-31 */
2401 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2403 verify_typedef_table (VerifyContext *ctx)
2405 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2406 guint32 data [MONO_TYPEDEF_SIZE];
2407 guint32 fieldlist = 1, methodlist = 1, visibility;
2410 if (table->rows == 0)
2411 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2413 for (i = 0; i < table->rows; ++i) {
2414 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2415 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
2416 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
2418 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
2419 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
2421 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
2422 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2424 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
2425 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
2427 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
2428 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
2430 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
2431 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2433 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2434 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2436 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2437 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2439 if (data [MONO_TYPEDEF_EXTENDS] && !get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2440 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d zero coded extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2442 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2443 if ((visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) &&
2444 search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1) == -1)
2445 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i));
2447 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2448 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2450 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2451 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2453 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2454 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));
2456 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2457 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2459 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2460 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2462 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2463 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));
2465 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2466 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2471 verify_typedef_table_full (VerifyContext *ctx)
2473 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2474 guint32 data [MONO_TYPEDEF_SIZE];
2477 if (table->rows == 0)
2478 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2480 for (i = 0; i < table->rows; ++i) {
2481 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2484 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2485 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2486 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2491 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2492 if (data [MONO_TYPEDEF_EXTENDS])
2493 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2495 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2496 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2500 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2503 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2511 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2513 verify_field_table (VerifyContext *ctx)
2515 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2516 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2519 module_field_list = (guint32)-1;
2520 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2521 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2522 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2525 for (i = 0; i < table->rows; ++i) {
2526 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2527 flags = data [MONO_FIELD_FLAGS];
2529 if (flags & INVALID_FIELD_FLAG_BITS)
2530 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2532 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2533 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2535 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2536 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2538 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2539 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2541 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2542 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2544 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2545 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2546 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2548 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2549 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2550 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2552 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2553 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2554 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2556 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2557 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2558 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2560 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2561 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2563 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2564 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2566 //TODO verify contant flag
2568 if (i + 1 < module_field_list) {
2569 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2570 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2571 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2572 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2573 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2579 verify_field_table_full (VerifyContext *ctx)
2581 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2582 guint32 data [MONO_FIELD_SIZE];
2585 for (i = 0; i < table->rows; ++i) {
2586 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2588 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2589 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2593 /*bits 8,9,10,11,13,14,15*/
2594 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2596 verify_method_table (VerifyContext *ctx)
2598 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2599 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2600 guint32 paramlist = 1;
2601 gboolean is_ctor, is_cctor;
2605 module_method_list = (guint32)-1;
2606 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2607 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2608 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2611 for (i = 0; i < table->rows; ++i) {
2612 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2613 rva = data [MONO_METHOD_RVA];
2614 implflags = data [MONO_METHOD_IMPLFLAGS];
2615 flags = data [MONO_METHOD_FLAGS];
2616 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2617 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2620 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2621 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2624 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2626 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2627 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2629 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2630 is_ctor = !strcmp (".ctor", name);
2631 is_cctor = !strcmp (".cctor", name);
2633 if ((is_ctor || is_cctor) &&
2634 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2635 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2637 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2638 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2640 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2641 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2642 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2643 if (flags & METHOD_ATTRIBUTE_FINAL)
2644 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and Final", i));
2645 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2646 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2649 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2650 ADD_WARNING (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2652 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2653 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2655 //XXX no checks against cas stuff 10,11,12,13)
2657 //TODO check iface with .ctor (15,16)
2659 if (i + 1 < module_method_list) {
2660 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2661 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2662 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2663 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2664 if (access == METHOD_ATTRIBUTE_FAMILY || access == METHOD_ATTRIBUTE_FAM_AND_ASSEM || access == METHOD_ATTRIBUTE_FAM_OR_ASSEM)
2665 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public, Private or Assembly", i));
2668 //TODO check valuetype for synchronized
2670 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2671 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2673 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2674 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
2675 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2676 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2677 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i));
2680 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2681 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2682 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2684 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2685 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2687 //TODO check signature contents
2690 if ((flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) || (implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2691 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is either Abstract, InternalCall or PinvokeImpl", i));
2692 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2693 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2695 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2696 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2699 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2701 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2702 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2703 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2705 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2706 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2708 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2709 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2711 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2712 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2714 if (data [MONO_METHOD_PARAMLIST] == 0)
2715 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2717 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2718 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));
2720 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2721 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2723 paramlist = data [MONO_METHOD_PARAMLIST];
2729 verify_method_table_full (VerifyContext *ctx)
2731 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2732 guint32 data [MONO_METHOD_SIZE], rva, locals_token;
2735 for (i = 0; i < table->rows; ++i) {
2736 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2737 rva = data [MONO_METHOD_RVA];
2739 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2740 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2742 if (rva && !is_valid_method_header (ctx, rva, &locals_token))
2743 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2748 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2750 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2751 guint32 row = *current_method;
2752 guint32 paramlist, tmp;
2755 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2756 while (row < table->rows) {
2757 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2758 if (tmp > paramlist) {
2759 *current_method = row;
2760 return tmp - paramlist;
2765 /*no more methods, all params apply to the last one*/
2766 *current_method = table->rows;
2771 #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))
2773 verify_param_table (VerifyContext *ctx)
2775 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2776 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2777 gboolean first_param = TRUE;
2780 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2781 if (table->rows > 0)
2782 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2786 remaining_params = get_next_param_count (ctx, ¤t_method);
2788 for (i = 0; i < table->rows; ++i) {
2789 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2790 flags = data [MONO_PARAM_FLAGS];
2792 if (flags & INVALID_PARAM_FLAGS_BITS)
2793 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2795 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2796 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2797 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2799 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2800 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2803 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)
2804 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2806 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2807 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2809 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2810 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2812 first_param = FALSE;
2813 sequence = data [MONO_PARAM_SEQUENCE];
2814 if (--remaining_params == 0) {
2815 remaining_params = get_next_param_count (ctx, ¤t_method);
2822 verify_interfaceimpl_table (VerifyContext *ctx)
2824 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2825 guint32 data [MONO_INTERFACEIMPL_SIZE];
2828 for (i = 0; i < table->rows; ++i) {
2829 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2830 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2831 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_INTERFACEIMPL_CLASS]));
2833 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2834 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2836 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2837 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2842 verify_memberref_table (VerifyContext *ctx)
2844 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2845 guint32 data [MONO_MEMBERREF_SIZE];
2848 for (i = 0; i < table->rows; ++i) {
2849 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2851 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2852 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2854 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2855 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2857 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2858 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2860 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2861 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2867 verify_memberref_table_full (VerifyContext *ctx)
2869 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2870 guint32 data [MONO_MEMBERREF_SIZE];
2873 for (i = 0; i < table->rows; ++i) {
2874 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2876 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2877 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2882 verify_constant_table (VerifyContext *ctx)
2884 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2885 guint32 data [MONO_CONSTANT_SIZE], type;
2888 for (i = 0; i < table->rows; ++i) {
2889 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2890 type = data [MONO_CONSTANT_TYPE];
2892 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2893 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2895 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2896 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2898 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2899 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2901 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2902 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2907 verify_cattr_table (VerifyContext *ctx)
2909 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2910 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2913 for (i = 0; i < table->rows; ++i) {
2914 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2916 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2917 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2919 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]) || !get_coded_index_token (CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2920 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Type field 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2922 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2923 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2928 verify_cattr_table_full (VerifyContext *ctx)
2931 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2934 guint32 data [MONO_CUSTOM_ATTR_SIZE], mtoken, size;
2937 for (i = 0; i < table->rows; ++i) {
2938 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2940 if (!is_valid_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2941 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2943 mtoken = data [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2944 switch (data [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2945 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2946 mtoken |= MONO_TOKEN_METHOD_DEF;
2948 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2949 mtoken |= MONO_TOKEN_MEMBER_REF;
2952 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i, data [MONO_CUSTOM_ATTR_TYPE]));
2955 ctor = mono_get_method_checked (ctx->image, mtoken, NULL, NULL, &error);
2958 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Could not load ctor due to %s", i, mono_error_get_message (&error)));
2959 mono_error_cleanup (&error);
2962 /*This can't fail since this is checked in is_valid_cattr_blob*/
2963 g_assert (decode_signature_header (ctx, data [MONO_CUSTOM_ATTR_VALUE], &size, &ptr));
2965 if (!is_valid_cattr_content (ctx, ctor, ptr, size))
2966 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2971 verify_field_marshal_table (VerifyContext *ctx)
2973 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2974 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2977 for (i = 0; i < table->rows; ++i) {
2978 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2980 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2981 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2983 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2984 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2986 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2987 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2989 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2990 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2995 verify_field_marshal_table_full (VerifyContext *ctx)
2997 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2998 guint32 data [MONO_FIELD_MARSHAL_SIZE];
3001 for (i = 0; i < table->rows; ++i) {
3002 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
3004 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
3005 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
3010 verify_decl_security_table (VerifyContext *ctx)
3012 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3013 guint32 data [MONO_DECL_SECURITY_SIZE];
3016 for (i = 0; i < table->rows; ++i) {
3017 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3019 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3020 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
3022 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
3023 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
3025 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
3026 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
3031 verify_decl_security_table_full (VerifyContext *ctx)
3033 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
3034 guint32 data [MONO_DECL_SECURITY_SIZE];
3037 for (i = 0; i < table->rows; ++i) {
3038 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
3040 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
3041 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
3046 verify_class_layout_table (VerifyContext *ctx)
3048 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
3049 guint32 data [MONO_CLASS_LAYOUT_SIZE];
3052 for (i = 0; i < table->rows; ++i) {
3053 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
3055 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3056 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
3058 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
3070 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
3076 verify_field_layout_table (VerifyContext *ctx)
3078 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
3079 guint32 data [MONO_FIELD_LAYOUT_SIZE];
3082 for (i = 0; i < table->rows; ++i) {
3083 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
3085 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3086 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
3091 verify_standalonesig_table (VerifyContext *ctx)
3093 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3094 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3097 for (i = 0; i < table->rows; ++i) {
3098 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3100 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
3101 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3106 verify_standalonesig_table_full (VerifyContext *ctx)
3108 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
3109 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
3112 for (i = 0; i < table->rows; ++i) {
3113 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
3115 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
3116 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
3121 verify_eventmap_table (VerifyContext *ctx)
3123 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
3124 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
3127 for (i = 0; i < table->rows; ++i) {
3128 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
3130 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3131 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
3133 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
3134 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
3136 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
3140 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3142 verify_event_table (VerifyContext *ctx)
3144 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3145 guint32 data [MONO_EVENT_SIZE];
3148 for (i = 0; i < table->rows; ++i) {
3149 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3151 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
3152 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
3154 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
3155 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
3157 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
3158 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
3163 verify_event_table_full (VerifyContext *ctx)
3165 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
3166 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
3167 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
3168 gboolean found_add, found_remove;
3171 for (i = 0; i < table->rows; ++i) {
3172 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
3174 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
3175 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
3177 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
3179 //first we move to the first row for this event
3181 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
3185 //now move forward looking for AddOn and RemoveOn rows
3186 found_add = found_remove = FALSE;
3187 while (idx < sema_table->rows) {
3188 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
3189 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
3191 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
3193 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
3194 found_remove = TRUE;
3195 if (found_add && found_remove)
3201 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
3203 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no RemoveOn associated method", i));
3208 verify_propertymap_table (VerifyContext *ctx)
3210 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
3211 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
3214 for (i = 0; i < table->rows; ++i) {
3215 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
3217 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3218 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
3220 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
3221 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
3223 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
3227 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3229 verify_property_table (VerifyContext *ctx)
3231 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
3232 guint32 data [MONO_PROPERTY_SIZE];
3235 for (i = 0; i < table->rows; ++i) {
3236 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
3238 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
3239 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
3241 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
3242 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
3244 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
3245 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
3247 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
3248 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
3249 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
3255 verify_methodimpl_table (VerifyContext *ctx)
3257 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
3258 guint32 data [MONO_METHODIMPL_SIZE];
3261 for (i = 0; i < table->rows; ++i) {
3262 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
3264 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
3265 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
3267 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3268 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3270 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
3271 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
3273 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3274 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3276 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
3277 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
3282 verify_moduleref_table (VerifyContext *ctx)
3284 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
3285 guint32 data [MONO_MODULEREF_SIZE];
3288 for (i = 0; i < table->rows; ++i) {
3289 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
3291 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
3292 ADD_ERROR (ctx, g_strdup_printf ("Invalid ModuleRef row %d name field %08x", i, data [MONO_MODULEREF_NAME]));
3297 verify_typespec_table (VerifyContext *ctx)
3299 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3300 guint32 data [MONO_TYPESPEC_SIZE];
3303 for (i = 0; i < table->rows; ++i) {
3304 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3306 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
3307 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3312 verify_typespec_table_full (VerifyContext *ctx)
3314 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
3315 guint32 data [MONO_TYPESPEC_SIZE];
3318 for (i = 0; i < table->rows; ++i) {
3319 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
3320 ctx->token = (i + 1) | MONO_TOKEN_TYPE_SPEC;
3321 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
3322 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
3327 #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))
3329 verify_implmap_table (VerifyContext *ctx)
3331 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
3332 guint32 data [MONO_IMPLMAP_SIZE], cconv;
3335 for (i = 0; i < table->rows; ++i) {
3336 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
3338 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
3339 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
3341 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
3342 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
3343 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
3345 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3346 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
3348 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
3349 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
3351 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
3352 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
3354 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
3355 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
3357 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows)
3358 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
3363 verify_fieldrva_table (VerifyContext *ctx)
3365 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
3366 guint32 data [MONO_FIELD_RVA_SIZE];
3369 for (i = 0; i < table->rows; ++i) {
3370 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
3372 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
3373 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
3375 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
3376 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
3380 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 14) | (1 << 15))
3382 verify_assembly_table (VerifyContext *ctx)
3384 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
3385 guint32 data [MONO_ASSEMBLY_SIZE], hash;
3388 if (table->rows > 1)
3389 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
3391 for (i = 0; i < table->rows; ++i) {
3392 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
3394 hash = data [MONO_ASSEMBLY_HASH_ALG];
3395 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
3396 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
3398 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
3399 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3401 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
3402 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
3404 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
3405 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
3407 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
3408 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
3412 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
3414 verify_assemblyref_table (VerifyContext *ctx)
3416 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
3417 guint32 data [MONO_ASSEMBLYREF_SIZE];
3420 for (i = 0; i < table->rows; ++i) {
3421 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
3423 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
3424 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
3426 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
3427 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
3429 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
3430 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
3432 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
3433 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
3435 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
3436 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
3440 #define INVALID_FILE_FLAGS_BITS ~(1)
3442 verify_file_table (VerifyContext *ctx)
3444 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
3445 guint32 data [MONO_FILE_SIZE];
3448 for (i = 0; i < table->rows; ++i) {
3449 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
3451 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
3452 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
3454 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
3455 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
3457 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
3458 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
3462 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3464 verify_exportedtype_table (VerifyContext *ctx)
3466 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
3467 guint32 data [MONO_EXP_TYPE_SIZE];
3470 for (i = 0; i < table->rows; ++i) {
3471 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
3473 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
3474 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
3476 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
3477 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3479 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3480 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3482 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3483 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3485 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3486 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3488 /*nested type can't have a namespace*/
3489 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3490 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3494 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3496 verify_manifest_resource_table (VerifyContext *ctx)
3498 MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)ctx->image->image_info;
3499 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3500 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3501 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3504 resources_size = ch->ch_resources.size;
3506 for (i = 0; i < table->rows; ++i) {
3507 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3509 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3510 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3512 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3513 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3515 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3516 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3518 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3519 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3521 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3522 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3524 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3525 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])));
3527 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3528 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3530 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3531 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3536 verify_nested_class_table (VerifyContext *ctx)
3538 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3539 guint32 data [MONO_NESTED_CLASS_SIZE];
3542 for (i = 0; i < table->rows; ++i) {
3543 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3545 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3546 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3547 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3548 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3549 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3550 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3554 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3556 verify_generic_param_table (VerifyContext *ctx)
3558 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3559 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3560 int i, param_number = 0;
3562 for (i = 0; i < table->rows; ++i) {
3563 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3565 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3566 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3568 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3569 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3571 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3572 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3574 token = data [MONO_GENERICPARAM_OWNER];
3576 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3577 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3579 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3580 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3582 if (token != last_token) {
3587 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3588 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));
3595 verify_method_spec_table (VerifyContext *ctx)
3597 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3598 guint32 data [MONO_METHODSPEC_SIZE];
3601 for (i = 0; i < table->rows; ++i) {
3602 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3604 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3605 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3607 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3608 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3610 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3611 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3616 verify_method_spec_table_full (VerifyContext *ctx)
3618 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3619 guint32 data [MONO_METHODSPEC_SIZE];
3622 for (i = 0; i < table->rows; ++i) {
3623 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3625 if (!is_valid_methodspec_blob (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3626 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3631 verify_generic_param_constraint_table (VerifyContext *ctx)
3633 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3634 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3636 guint32 last_owner = 0, last_constraint = 0;
3638 for (i = 0; i < table->rows; ++i) {
3639 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3641 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3642 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3644 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3645 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3647 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3648 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3650 if (last_owner > data [MONO_GENPARCONSTRAINT_GENERICPAR])
3651 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d is not properly sorted. Previous value of the owner column is 0x%08x current value is 0x%08x", i, last_owner, data [MONO_GENPARCONSTRAINT_GENERICPAR]));
3653 if (last_owner == data [MONO_GENPARCONSTRAINT_GENERICPAR]) {
3654 if (last_constraint == data [MONO_GENPARCONSTRAINT_CONSTRAINT])
3655 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has duplicate constraint 0x%08x", i, last_constraint));
3657 last_owner = data [MONO_GENPARCONSTRAINT_GENERICPAR];
3659 last_constraint = data [MONO_GENPARCONSTRAINT_CONSTRAINT];
3666 const char *name_space;
3667 guint32 resolution_scope;
3671 typedef_hash (gconstpointer _key)
3673 const TypeDefUniqueId *key = (const TypeDefUniqueId *)_key;
3674 return g_str_hash (key->name) ^ g_str_hash (key->name_space) ^ key->resolution_scope; /*XXX better salt the int key*/
3678 typedef_equals (gconstpointer _a, gconstpointer _b)
3680 const TypeDefUniqueId *a = (const TypeDefUniqueId *)_a;
3681 const TypeDefUniqueId *b = (const TypeDefUniqueId *)_b;
3682 return !strcmp (a->name, b->name) && !strcmp (a->name_space, b->name_space) && a->resolution_scope == b->resolution_scope;
3686 verify_typedef_table_global_constraints (VerifyContext *ctx)
3689 guint32 data [MONO_TYPEDEF_SIZE];
3690 guint32 nested_data [MONO_NESTED_CLASS_SIZE];
3691 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
3692 MonoTableInfo *nested_table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3693 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3695 for (i = 0; i < table->rows; ++i) {
3697 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3698 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
3700 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAME]);
3701 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEDEF_NAMESPACE]);
3702 type->resolution_scope = 0;
3704 visibility = data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3705 if (visibility >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visibility <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM) {
3706 int res = search_sorted_table (ctx, MONO_TABLE_NESTEDCLASS, MONO_NESTED_CLASS_NESTED, i + 1);
3707 g_assert (res >= 0);
3709 mono_metadata_decode_row (nested_table, res, nested_data, MONO_NESTED_CLASS_SIZE);
3710 type->resolution_scope = nested_data [MONO_NESTED_CLASS_ENCLOSING];
3713 if (g_hash_table_lookup (unique_types, type)) {
3714 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));
3715 g_hash_table_destroy (unique_types);
3719 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3722 g_hash_table_destroy (unique_types);
3726 verify_typeref_table_global_constraints (VerifyContext *ctx)
3729 guint32 data [MONO_TYPEREF_SIZE];
3730 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
3731 GHashTable *unique_types = g_hash_table_new_full (&typedef_hash, &typedef_equals, g_free, NULL);
3733 for (i = 0; i < table->rows; ++i) {
3734 TypeDefUniqueId *type = g_new (TypeDefUniqueId, 1);
3735 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
3737 type->resolution_scope = data [MONO_TYPEREF_SCOPE];
3738 type->name = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAME]);
3739 type->name_space = mono_metadata_string_heap (ctx->image, data [MONO_TYPEREF_NAMESPACE]);
3741 if (g_hash_table_lookup (unique_types, type)) {
3742 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));
3743 g_hash_table_destroy (unique_types);
3747 g_hash_table_insert (unique_types, type, GUINT_TO_POINTER (1));
3750 g_hash_table_destroy (unique_types);
3754 verify_tables_data_global_constraints (VerifyContext *ctx)
3756 verify_typedef_table_global_constraints (ctx);
3760 verify_tables_data_global_constraints_full (VerifyContext *ctx)
3762 verify_typeref_table (ctx);
3763 verify_typeref_table_global_constraints (ctx);
3767 verify_tables_data (VerifyContext *ctx)
3769 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3770 guint32 size = 0, tables_offset;
3773 for (i = 0; i < 0x2D; ++i) {
3774 MonoTableInfo *table = &ctx->image->tables [i];
3776 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3777 if (tmp_size < size) {
3785 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3787 tables_offset = ctx->image->tables_base - ctx->data;
3788 if (!bounds_check_offset (&tables_area, tables_offset, size))
3789 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)));
3791 verify_module_table (ctx);
3793 /*Obfuscators love to place broken stuff in the typeref table
3794 verify_typeref_table (ctx);
3796 verify_typedef_table (ctx);
3798 verify_field_table (ctx);
3800 verify_method_table (ctx);
3802 verify_param_table (ctx);
3804 verify_interfaceimpl_table (ctx);
3806 verify_memberref_table (ctx);
3808 verify_constant_table (ctx);
3810 verify_cattr_table (ctx);
3812 verify_field_marshal_table (ctx);
3814 verify_decl_security_table (ctx);
3816 verify_class_layout_table (ctx);
3818 verify_field_layout_table (ctx);
3820 verify_standalonesig_table (ctx);
3822 verify_eventmap_table (ctx);
3824 verify_event_table (ctx);
3826 verify_propertymap_table (ctx);
3828 verify_property_table (ctx);
3830 verify_methodimpl_table (ctx);
3832 verify_moduleref_table (ctx);
3834 verify_typespec_table (ctx);
3836 verify_implmap_table (ctx);
3838 verify_fieldrva_table (ctx);
3840 verify_assembly_table (ctx);
3842 verify_assemblyref_table (ctx);
3844 verify_file_table (ctx);
3846 verify_exportedtype_table (ctx);
3848 verify_manifest_resource_table (ctx);
3850 verify_nested_class_table (ctx);
3852 verify_generic_param_table (ctx);
3854 verify_method_spec_table (ctx);
3856 verify_generic_param_constraint_table (ctx);
3858 verify_tables_data_global_constraints (ctx);
3862 init_verify_context (VerifyContext *ctx, MonoImage *image, gboolean report_error)
3864 memset (ctx, 0, sizeof (VerifyContext));
3866 ctx->report_error = report_error;
3867 ctx->report_warning = FALSE; //export this setting in the API
3869 ctx->size = image->raw_data_len;
3870 ctx->data = image->raw_data;
3874 cleanup_context (VerifyContext *ctx, GSList **error_list)
3876 g_free (ctx->sections);
3878 *error_list = ctx->errors;
3880 mono_free_verify_list (ctx->errors);
3885 cleanup_context_checked (VerifyContext *ctx, MonoError *error)
3887 g_free (ctx->sections);
3889 MonoVerifyInfo *info = (MonoVerifyInfo *)ctx->errors->data;
3890 mono_error_set_bad_image (error, ctx->image, "%s", info->message);
3891 mono_free_verify_list (ctx->errors);
3897 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3901 if (!mono_verifier_is_enabled_for_image (image))
3904 init_verify_context (&ctx, image, error_list != NULL);
3905 ctx.stage = STAGE_PE;
3907 verify_msdos_header (&ctx);
3909 verify_pe_header (&ctx);
3911 verify_pe_optional_header (&ctx);
3913 load_section_table (&ctx);
3915 load_data_directories (&ctx);
3917 verify_import_table (&ctx);
3919 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3920 verify_resources_table (&ctx);
3923 return cleanup_context (&ctx, error_list);
3927 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3931 if (!mono_verifier_is_enabled_for_image (image))
3934 init_verify_context (&ctx, image, error_list != NULL);
3935 ctx.stage = STAGE_CLI;
3937 verify_cli_header (&ctx);
3939 verify_metadata_header (&ctx);
3941 verify_tables_schema (&ctx);
3944 return cleanup_context (&ctx, error_list);
3949 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3950 * Other verification checks are meant to be done lazily by the runtime. Those include:
3951 * blob items (signatures, method headers, custom attributes, etc)
3952 * type semantics related
3954 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3956 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3957 * operation still need more checking.
3960 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3964 if (!mono_verifier_is_enabled_for_image (image))
3967 init_verify_context (&ctx, image, error_list != NULL);
3968 ctx.stage = STAGE_TABLES;
3970 verify_tables_data (&ctx);
3972 return cleanup_context (&ctx, error_list);
3977 * Verifies all other constraints.
3980 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3984 if (!mono_verifier_is_enabled_for_image (image))
3987 init_verify_context (&ctx, image, error_list != NULL);
3988 ctx.stage = STAGE_TABLES;
3990 verify_typedef_table_full (&ctx);
3992 verify_field_table_full (&ctx);
3994 verify_method_table_full (&ctx);
3996 verify_memberref_table_full (&ctx);
3998 verify_cattr_table_full (&ctx);
4000 verify_field_marshal_table_full (&ctx);
4002 verify_decl_security_table_full (&ctx);
4004 verify_standalonesig_table_full (&ctx);
4006 verify_event_table_full (&ctx);
4008 verify_typespec_table_full (&ctx);
4010 verify_method_spec_table_full (&ctx);
4012 verify_tables_data_global_constraints_full (&ctx);
4015 return cleanup_context (&ctx, error_list);
4019 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4023 if (!mono_verifier_is_enabled_for_image (image))
4026 init_verify_context (&ctx, image, error_list != NULL);
4027 ctx.stage = STAGE_TABLES;
4029 is_valid_field_signature (&ctx, offset);
4030 return cleanup_context (&ctx, error_list);
4034 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4037 guint32 locals_token;
4039 if (!mono_verifier_is_enabled_for_image (image))
4042 init_verify_context (&ctx, image, error_list != NULL);
4043 ctx.stage = STAGE_TABLES;
4045 is_valid_method_header (&ctx, offset, &locals_token);
4047 guint32 sig_offset = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_STANDALONESIG], locals_token - 1, MONO_STAND_ALONE_SIGNATURE);
4048 is_valid_standalonesig_blob (&ctx, sig_offset);
4051 return cleanup_context (&ctx, error_list);
4055 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4061 if (!mono_verifier_is_enabled_for_image (image))
4064 init_verify_context (&ctx, image, TRUE);
4065 ctx.stage = STAGE_TABLES;
4067 is_valid_method_signature (&ctx, offset);
4068 /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4069 return cleanup_context_checked (&ctx, error);
4073 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4077 if (!mono_verifier_is_enabled_for_image (image))
4080 init_verify_context (&ctx, image, error_list != NULL);
4081 ctx.stage = STAGE_TABLES;
4083 is_valid_memberref_method_signature (&ctx, offset);
4084 return cleanup_context (&ctx, error_list);
4088 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4092 if (!mono_verifier_is_enabled_for_image (image))
4095 init_verify_context (&ctx, image, error_list != NULL);
4096 ctx.stage = STAGE_TABLES;
4098 is_valid_field_signature (&ctx, offset);
4099 return cleanup_context (&ctx, error_list);
4103 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4107 if (!mono_verifier_is_enabled_for_image (image))
4110 init_verify_context (&ctx, image, error_list != NULL);
4111 ctx.stage = STAGE_TABLES;
4113 is_valid_standalonesig_blob (&ctx, offset);
4114 return cleanup_context (&ctx, error_list);
4118 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4122 if (!mono_verifier_is_enabled_for_image (image))
4125 init_verify_context (&ctx, image, error_list != NULL);
4126 ctx.stage = STAGE_TABLES;
4129 is_valid_typespec_blob (&ctx, offset);
4130 return cleanup_context (&ctx, error_list);
4134 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4138 if (!mono_verifier_is_enabled_for_image (image))
4141 init_verify_context (&ctx, image, error_list != NULL);
4142 ctx.stage = STAGE_TABLES;
4144 is_valid_methodspec_blob (&ctx, offset);
4145 return cleanup_context (&ctx, error_list);
4149 verify_user_string (VerifyContext *ctx, guint32 offset)
4151 OffsetAndSize heap_us = get_metadata_stream (ctx, &ctx->image->heap_us);
4152 guint32 entry_size, bytes;
4154 if (heap_us.size < offset)
4155 ADD_ERROR (ctx, g_strdup ("User string offset beyond heap_us size"));
4157 if (!decode_value (ctx->data + offset + heap_us.offset, heap_us.size - heap_us.offset, &entry_size, &bytes))
4158 ADD_ERROR (ctx, g_strdup ("Could not decode user string blob size"));
4160 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
4161 ADD_ERROR (ctx, g_strdup ("User string size overflow"));
4163 entry_size += bytes;
4165 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, heap_us.size))
4166 ADD_ERROR (ctx, g_strdup ("User string oveflow heap_us"));
4170 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4174 if (!mono_verifier_is_enabled_for_image (image))
4177 init_verify_context (&ctx, image, error_list != NULL);
4178 ctx.stage = STAGE_TABLES;
4180 verify_user_string (&ctx, offset);
4182 return cleanup_context (&ctx, error_list);
4186 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4190 if (!mono_verifier_is_enabled_for_image (image))
4193 init_verify_context (&ctx, image, error_list != NULL);
4194 ctx.stage = STAGE_TABLES;
4196 is_valid_cattr_blob (&ctx, offset);
4198 return cleanup_context (&ctx, error_list);
4202 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4206 if (!mono_verifier_is_enabled_for_image (image))
4209 init_verify_context (&ctx, image, error_list != NULL);
4210 ctx.stage = STAGE_TABLES;
4212 is_valid_cattr_content (&ctx, ctor, (const char*)data, size);
4214 return cleanup_context (&ctx, error_list);
4218 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4220 MonoMethodSignature *original_sig;
4221 if (!mono_verifier_is_enabled_for_image (image))
4224 original_sig = mono_method_signature (method);
4225 if (original_sig->call_convention == MONO_CALL_VARARG) {
4226 if (original_sig->hasthis != signature->hasthis)
4228 if (original_sig->call_convention != signature->call_convention)
4230 if (original_sig->explicit_this != signature->explicit_this)
4232 if (original_sig->pinvoke != signature->pinvoke)
4234 if (original_sig->sentinelpos != signature->sentinelpos)
4236 } else if (!mono_metadata_signature_equal (signature, original_sig)) {
4244 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4246 MonoTableInfo *table = &image->tables [MONO_TABLE_TYPEREF];
4247 guint32 data [MONO_TYPEREF_SIZE];
4251 if (!mono_verifier_is_enabled_for_image (image))
4254 if (row >= table->rows) {
4255 mono_error_set_bad_image (error, image, "Invalid typeref row %d - table has %d rows", row, table->rows);
4259 mono_metadata_decode_row (table, row, data, MONO_TYPEREF_SIZE);
4260 if (!is_valid_coded_index_with_image (image, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4261 mono_error_set_bad_image (error, image, "Invalid typeref row %d coded index 0x%08x", row, data [MONO_TYPEREF_SCOPE]);
4265 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE])) {
4266 mono_error_set_bad_image (error, image, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row);
4270 if (!data [MONO_TYPEREF_NAME] || !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAME], FALSE)) {
4271 mono_error_set_bad_image (error, image, "Invalid typeref row %d name token 0x%08x", row, data [MONO_TYPEREF_NAME]);
4275 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_string_full_with_image (image, data [MONO_TYPEREF_NAMESPACE], FALSE)) {
4276 mono_error_set_bad_image (error, image, "Invalid typeref row %d namespace token 0x%08x", row, data [MONO_TYPEREF_NAMESPACE]);
4283 /*Perform additional verification including metadata ones*/
4285 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4287 MonoMethod *declaration, *body;
4288 MonoMethodSignature *body_sig, *decl_sig;
4289 MonoTableInfo *table = &image->tables [MONO_TABLE_METHODIMPL];
4290 guint32 data [MONO_METHODIMPL_SIZE];
4294 if (!mono_verifier_is_enabled_for_image (image))
4297 if (row >= table->rows) {
4298 mono_error_set_bad_image (error, image, "Invalid methodimpl row %d - table has %d rows", row, table->rows);
4302 mono_metadata_decode_row (table, row, data, MONO_METHODIMPL_SIZE);
4304 body = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_BODY], NULL, error);
4308 declaration = method_from_method_def_or_ref (image, data [MONO_METHODIMPL_DECLARATION], NULL, error);
4313 mono_class_setup_supertypes (class);
4314 if (!mono_class_has_parent (class, body->klass)) {
4315 mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
4319 if (!(body_sig = mono_method_signature_checked (body, error))) {
4323 if (!(decl_sig = mono_method_signature_checked (declaration, error))) {
4327 if (!mono_verifier_is_signature_compatible (decl_sig, body_sig)) {
4328 mono_error_set_bad_image (error, image, "Invalid methodimpl body signature not compatible with declaration row %x", row);
4337 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
4343 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
4349 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
4355 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
4361 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4367 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
4373 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, MonoError *error)
4380 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
4386 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, guint32 token, GSList **error_list)
4392 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
4398 mono_verifier_verify_string_signature (MonoImage *image, guint32 offset, GSList **error_list)
4404 mono_verifier_verify_cattr_blob (MonoImage *image, guint32 offset, GSList **error_list)
4410 mono_verifier_verify_cattr_content (MonoImage *image, MonoMethod *ctor, const guchar *data, guint32 size, GSList **error_list)
4416 mono_verifier_is_sig_compatible (MonoImage *image, MonoMethod *method, MonoMethodSignature *signature)
4423 mono_verifier_verify_typeref_row (MonoImage *image, guint32 row, MonoError *error)
4430 mono_verifier_verify_methodimpl_row (MonoImage *image, guint32 row, MonoError *error)
4437 mono_verifier_verify_memberref_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
4443 mono_verifier_verify_memberref_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
4448 #endif /* DISABLE_VERIFIER */