2 * metadata-verify.c: Metadata verfication support
5 * Mono Project (http://www.mono-project.com)
7 * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
9 #include <mono/metadata/object-internals.h>
10 #include <mono/metadata/verify.h>
11 #include <mono/metadata/verify-internals.h>
12 #include <mono/metadata/opcodes.h>
13 #include <mono/metadata/tabledefs.h>
14 #include <mono/metadata/reflection.h>
15 #include <mono/metadata/debug-helpers.h>
16 #include <mono/metadata/mono-endian.h>
17 #include <mono/metadata/metadata.h>
18 #include <mono/metadata/metadata-internals.h>
19 #include <mono/metadata/class-internals.h>
20 #include <mono/metadata/tokentype.h>
21 #include <mono/metadata/security-manager.h>
22 #include <mono/metadata/security-core-clr.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/attrdefs.h>
25 #include <mono/utils/strenc.h>
30 #ifndef DISABLE_VERIFIER
32 TODO add fail fast mode
33 TODO add PE32+ support
34 TODO verify the entry point RVA and content.
35 TODO load_section_table and load_data_directories must take PE32+ into account
36 TODO add section relocation support
37 TODO verify the relocation table, since we really don't use, no need so far.
38 TODO do full PECOFF resources verification
39 TODO verify in the CLI header entry point and resources
40 TODO implement null token typeref validation
41 TODO verify table wide invariants for typedef (sorting and uniqueness)
42 TODO implement proper authenticode data directory validation
43 TODO verify properties that require multiple tables to be valid
44 FIXME use subtraction based bounds checking to avoid overflows
45 FIXME get rid of metadata_streams and other fields from VerifyContext
48 #ifdef MONO_VERIFIER_DEBUG
49 #define VERIFIER_DEBUG(code) do { code; } while (0)
51 #define VERIFIER_DEBUG(code)
54 #define INVALID_OFFSET ((guint32)-1)
55 #define INVALID_ADDRESS 0xffffffff
65 RESOURCE_TABLE_IDX = 2,
66 CERTIFICATE_TABLE_IDX = 4,
67 RELOCATION_TABLE_IDX = 5,
81 #define INVALID_TABLE (0xFF)
82 /*format: number of bits, number of tables, tables{n. tables} */
83 const static unsigned char coded_index_desc[] = {
84 #define TYPEDEF_OR_REF_DESC (0)
91 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
98 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
106 MONO_TABLE_INTERFACEIMPL,
107 MONO_TABLE_MEMBERREF,
109 MONO_TABLE_DECLSECURITY,
112 MONO_TABLE_STANDALONESIG,
113 MONO_TABLE_MODULEREF,
116 MONO_TABLE_ASSEMBLYREF,
118 MONO_TABLE_EXPORTEDTYPE,
119 MONO_TABLE_MANIFESTRESOURCE,
120 MONO_TABLE_GENERICPARAM,
122 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
128 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
135 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
144 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
150 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
154 MONO_TABLE_MEMBERREF,
156 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
162 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
166 MONO_TABLE_ASSEMBLYREF,
167 MONO_TABLE_EXPORTEDTYPE,
169 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
175 MONO_TABLE_MEMBERREF,
178 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
182 MONO_TABLE_MODULEREF,
183 MONO_TABLE_ASSEMBLYREF,
186 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
196 guint32 translated_offset;
208 guint32 rellocationsRVA;
209 guint16 numberOfRelocations;
224 gboolean report_error;
227 DataDirectory data_directories [16];
228 guint32 section_count;
229 SectionHeader *sections;
231 OffsetAndSize metadata_streams [5]; //offset from begin of the image
234 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
236 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
237 vinfo->info.status = __status; \
238 vinfo->info.message = ( __msg); \
239 vinfo->exception_type = (__exception); \
240 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
244 #define ADD_ERROR(__ctx, __msg) \
246 if ((__ctx)->report_error) \
247 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
248 (__ctx)->valid = 0; \
252 #define FAIL(__ctx, __msg) \
254 if ((__ctx)->report_error) \
255 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
256 (__ctx)->valid = 0; \
260 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
262 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
264 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
265 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
267 #if SIZEOF_VOID_P == 4
268 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
270 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
273 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
274 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
277 dword_align (const char *ptr)
279 #if SIZEOF_VOID_P == 8
280 return (const char *) (((guint64) (ptr + 3)) & ~3);
282 return (const char *) (((guint32) (ptr + 3)) & ~3);
287 pe_signature_offset (VerifyContext *ctx)
289 return read32 (ctx->data + 0x3c);
293 pe_header_offset (VerifyContext *ctx)
295 return read32 (ctx->data + 0x3c) + 4;
299 bounds_check_virtual_address (VerifyContext *ctx, guint32 rva, guint32 size)
303 if (rva + size < rva) //overflow
306 if (ctx->stage > STAGE_PE) {
307 MonoCLIImageInfo *iinfo = ctx->image->image_info;
308 const int top = iinfo->cli_section_count;
309 MonoSectionTable *tables = iinfo->cli_section_tables;
312 for (i = 0; i < top; i++) {
313 guint32 base = tables->st_virtual_address;
314 guint32 end = base + tables->st_raw_data_size;
316 if (rva >= base && rva + size <= end)
319 /*if ((addr >= tables->st_virtual_address) &&
320 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
322 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
332 for (i = 0; i < ctx->section_count; ++i) {
333 guint32 base = ctx->sections [i].baseRVA;
334 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
335 if (rva >= base && rva + size <= end)
342 bounds_check_datadir (DataDirectory *dir, guint32 offset, guint32 size)
344 if (dir->translated_offset > offset)
346 if (dir->size < size)
348 return offset + size <= dir->translated_offset + dir->size;
352 bounds_check_offset (OffsetAndSize *off, guint32 offset, guint32 size)
354 if (off->offset > offset)
357 if (off->size < size)
360 return offset + size <= off->offset + off->size;
364 translate_rva (VerifyContext *ctx, guint32 rva)
368 if (ctx->stage > STAGE_PE)
369 return mono_cli_rva_image_map (ctx->image, rva);
374 for (i = 0; i < ctx->section_count; ++i) {
375 guint32 base = ctx->sections [i].baseRVA;
376 guint32 end = ctx->sections [i].baseRVA + ctx->sections [i].size;
377 if (rva >= base && rva <= end) {
378 guint32 res = (rva - base) + ctx->sections [i].baseOffset;
380 return res >= ctx->size ? INVALID_OFFSET : res;
384 return INVALID_OFFSET;
388 verify_msdos_header (VerifyContext *ctx)
392 ADD_ERROR (ctx, g_strdup ("Not enough space for the MS-DOS header"));
393 if (ctx->data [0] != 0x4d || ctx->data [1] != 0x5a)
394 ADD_ERROR (ctx, g_strdup ("Invalid MS-DOS watermark"));
395 lfanew = pe_signature_offset (ctx);
396 if (lfanew > ctx->size - 4)
397 ADD_ERROR (ctx, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
401 verify_pe_header (VerifyContext *ctx)
403 guint32 offset = pe_signature_offset (ctx);
404 const char *pe_header = ctx->data + offset;
405 if (pe_header [0] != 'P' || pe_header [1] != 'E' ||pe_header [2] != 0 ||pe_header [3] != 0)
406 ADD_ERROR (ctx, g_strdup ("Invalid PE header watermark"));
410 if (offset > ctx->size - 20)
411 ADD_ERROR (ctx, g_strdup ("File with truncated pe header"));
412 if (read16 (pe_header) != 0x14c)
413 ADD_ERROR (ctx, g_strdup ("Invalid PE header Machine value"));
417 verify_pe_optional_header (VerifyContext *ctx)
419 guint32 offset = pe_header_offset (ctx);
420 guint32 header_size, file_alignment;
421 const char *pe_header = ctx->data + offset;
422 const char *pe_optional_header = pe_header + 20;
424 header_size = read16 (pe_header + 16);
427 if (header_size < 2) /*must be at least 2 or we won't be able to read magic*/
428 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
430 if (offset > ctx->size - header_size || header_size > ctx->size)
431 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
433 if (read16 (pe_optional_header) == 0x10b) {
434 if (header_size != 224)
435 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header size %d", header_size));
437 /* LAMESPEC MS plays around this value and ignore it during validation
438 if (read32 (pe_optional_header + 28) != 0x400000)
439 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
440 if (read32 (pe_optional_header + 32) != 0x2000)
441 ADD_ERROR (ctx, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header + 32)));
442 file_alignment = read32 (pe_optional_header + 36);
443 if (file_alignment != 0x200 && file_alignment != 0x1000)
444 ADD_ERROR (ctx, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment));
445 /* All the junk in the middle is irrelevant, specially for mono. */
446 if (read32 (pe_optional_header + 92) > 0x10)
447 ADD_ERROR (ctx, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header + 92)));
449 if (read16 (pe_optional_header) == 0x20B)
450 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle PE32+"));
452 ADD_ERROR (ctx, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header)));
457 load_section_table (VerifyContext *ctx)
460 SectionHeader *sections;
461 guint32 offset = pe_header_offset (ctx);
462 const char *ptr = ctx->data + offset;
463 guint16 num_sections = ctx->section_count = read16 (ptr + 2);
465 offset += 244;/*FIXME, this constant is different under PE32+*/
468 if (num_sections * 40 > ctx->size - offset)
469 ADD_ERROR (ctx, g_strdup ("Invalid PE optional header size"));
471 sections = ctx->sections = g_new0 (SectionHeader, num_sections);
472 for (i = 0; i < num_sections; ++i) {
473 sections [i].size = read32 (ptr + 8);
474 sections [i].baseRVA = read32 (ptr + 12);
475 sections [i].baseOffset = read32 (ptr + 20);
476 sections [i].rellocationsRVA = read32 (ptr + 24);
477 sections [i].numberOfRelocations = read16 (ptr + 32);
481 ptr = ctx->data + offset; /*reset it to the beggining*/
482 for (i = 0; i < num_sections; ++i) {
483 guint32 raw_size, flags;
484 if (sections [i].baseOffset == 0)
485 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
486 if (sections [i].baseOffset >= ctx->size)
487 ADD_ERROR (ctx, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections [i].baseOffset));
488 if (sections [i].size > ctx->size - sections [i].baseOffset)
489 ADD_ERROR (ctx, g_strdup ("Invalid VirtualSize points beyond EOF"));
491 raw_size = read32 (ptr + 16);
492 if (raw_size < sections [i].size)
493 ADD_ERROR (ctx, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
495 if (raw_size > ctx->size - sections [i].baseOffset)
496 ADD_ERROR (ctx, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size));
498 if (sections [i].rellocationsRVA || sections [i].numberOfRelocations)
499 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
501 flags = read32 (ptr + 36);
502 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
503 if (flags == 0 || (flags & ~0xFE0000E0) != 0)
504 ADD_ERROR (ctx, g_strdup_printf ("Invalid section flags %x", flags));
511 is_valid_data_directory (int i)
513 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
514 return i == 1 || i == 2 || i == 5 || i == 12 || i == 14 || i == 4 || i == 6;
518 load_data_directories (VerifyContext *ctx)
520 guint32 offset = pe_header_offset (ctx) + 116; /*FIXME, this constant is different under PE32+*/
521 const char *ptr = ctx->data + offset;
524 for (i = 0; i < 16; ++i) {
525 guint32 rva = read32 (ptr);
526 guint32 size = read32 (ptr + 4);
528 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
529 if (i == CERTIFICATE_TABLE_IDX) {
533 if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
534 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
536 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
537 ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i, rva, size));
539 ctx->data_directories [i].rva = rva;
540 ctx->data_directories [i].size = size;
541 ctx->data_directories [i].translated_offset = translate_rva (ctx, rva);
547 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
549 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
552 verify_hint_name_table (VerifyContext *ctx, guint32 import_rva, const char *table_name)
555 guint32 hint_table_rva;
557 import_rva = translate_rva (ctx, import_rva);
558 g_assert (import_rva != INVALID_OFFSET);
560 hint_table_rva = read32 (ctx->data + import_rva);
561 if (!bounds_check_virtual_address (ctx, hint_table_rva, SIZE_OF_CORMAIN + 2))
562 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva, table_name));
564 hint_table_rva = translate_rva (ctx, hint_table_rva);
565 g_assert (hint_table_rva != INVALID_OFFSET);
566 ptr = ctx->data + hint_table_rva + 2;
568 if (memcmp ("_CorExeMain", ptr, SIZE_OF_CORMAIN) && memcmp ("_CorDllMain", ptr, SIZE_OF_CORMAIN)) {
569 char name[SIZE_OF_CORMAIN];
570 memcpy (name, ptr, SIZE_OF_CORMAIN);
571 name [SIZE_OF_CORMAIN - 1] = 0;
572 ADD_ERROR (ctx, g_strdup_printf ("Invalid Hint / Name: '%s'", name));
577 verify_import_table (VerifyContext *ctx)
579 DataDirectory it = ctx->data_directories [IMPORT_TABLE_IDX];
580 guint32 offset = it.translated_offset;
581 const char *ptr = ctx->data + offset;
582 guint32 name_rva, ilt_rva, iat_rva;
584 g_assert (offset != INVALID_OFFSET);
587 ADD_ERROR (ctx, g_strdup_printf ("Import table size %d is smaller than 40", it.size));
589 ilt_rva = read32 (ptr);
590 if (ilt_rva && !bounds_check_virtual_address (ctx, ilt_rva, 8))
591 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva));
593 name_rva = read32 (ptr + 12);
594 if (name_rva && !bounds_check_virtual_address (ctx, name_rva, SIZE_OF_MSCOREE))
595 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva));
597 iat_rva = read32 (ptr + 16);
599 if (!bounds_check_virtual_address (ctx, iat_rva, 8))
600 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva));
602 if (iat_rva != ctx->data_directories [IAT_IDX].rva)
603 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));
607 name_rva = translate_rva (ctx, name_rva);
608 g_assert (name_rva != INVALID_OFFSET);
609 ptr = ctx->data + name_rva;
611 if (memcmp ("mscoree.dll", ptr, SIZE_OF_MSCOREE)) {
612 char name[SIZE_OF_MSCOREE];
613 memcpy (name, ptr, SIZE_OF_MSCOREE);
614 name [SIZE_OF_MSCOREE - 1] = 0;
615 ADD_ERROR (ctx, g_strdup_printf ("Invalid Import Table Name: '%s'", name));
620 verify_hint_name_table (ctx, ilt_rva, "Import Lookup Table");
625 verify_hint_name_table (ctx, iat_rva, "Import Address Table");
629 verify_resources_table (VerifyContext *ctx)
631 DataDirectory it = ctx->data_directories [RESOURCE_TABLE_IDX];
633 guint16 named_entries, id_entries;
634 const char *ptr, *root, *end;
640 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));
642 offset = it.translated_offset;
643 root = ptr = ctx->data + offset;
644 end = root + it.size;
646 g_assert (offset != INVALID_OFFSET);
648 named_entries = read16 (ptr + 12);
649 id_entries = read16 (ptr + 14);
651 if ((named_entries + id_entries) * 8 + 16 > it.size)
652 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));
654 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
655 if (named_entries || id_entries)
656 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
660 /*----------nothing from here on can use data_directory---*/
663 get_data_dir (VerifyContext *ctx, int idx)
665 MonoCLIImageInfo *iinfo = ctx->image->image_info;
666 MonoPEDirEntry *entry= &iinfo->cli_header.datadir.pe_export_table;
670 res.rva = entry->rva;
671 res.size = entry->size;
672 res.translated_offset = translate_rva (ctx, res.rva);
677 verify_cli_header (VerifyContext *ctx)
679 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
685 ADD_ERROR (ctx, g_strdup_printf ("CLI header missing"));
688 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it.size));
690 offset = it.translated_offset;
691 ptr = ctx->data + offset;
693 g_assert (offset != INVALID_OFFSET);
695 if (read16 (ptr) != 72)
696 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr)));
698 if (!bounds_check_virtual_address (ctx, read32 (ptr + 8), read32 (ptr + 12)))
699 ADD_ERROR (ctx, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr + 8), read32 (ptr + 12)));
702 if (!read32 (ptr + 8) || !read32 (ptr + 12))
703 ADD_ERROR (ctx, g_strdup_printf ("Missing medatata section in the CLI header"));
705 if ((read32 (ptr + 16) & ~0x0001000B) != 0)
706 ADD_ERROR (ctx, g_strdup_printf ("Invalid CLI header flags"));
709 for (i = 0; i < 6; ++i) {
710 guint32 rva = read32 (ptr);
711 guint32 size = read32 (ptr + 4);
713 if (rva != 0 && !bounds_check_virtual_address (ctx, rva, size))
714 ADD_ERROR (ctx, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i, rva, size));
719 ADD_ERROR (ctx, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i));
724 pad4 (guint32 offset)
726 if (offset & 0x3) //pad to the next 4 byte boundary
727 offset = (offset & ~0x3) + 4;
732 verify_metadata_header (VerifyContext *ctx)
735 DataDirectory it = get_data_dir (ctx, CLI_HEADER_IDX);
739 offset = it.translated_offset;
740 ptr = ctx->data + offset;
741 g_assert (offset != INVALID_OFFSET);
743 //build a directory entry for the metadata root
745 it.rva = read32 (ptr);
747 it.size = read32 (ptr);
748 it.translated_offset = offset = translate_rva (ctx, it.rva);
750 ptr = ctx->data + offset;
751 g_assert (offset != INVALID_OFFSET);
754 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it.size));
756 if (read32 (ptr) != 0x424A5342)
757 ADD_ERROR (ctx, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr)));
759 offset = pad4 (offset + 16 + read32 (ptr + 12));
761 if (!bounds_check_datadir (&it, offset, 4))
762 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));
764 ptr = ctx->data + offset; //move to streams header
766 if (read16 (ptr + 2) < 3)
767 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section must have at least 3 streams (#~, #GUID and #Blob"));
772 for (i = 0; i < 5; ++i) {
773 guint32 stream_off, stream_size;
774 int string_size, stream_idx;
776 if (!bounds_check_datadir (&it, offset, 8))
777 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));
779 stream_off = it.translated_offset + read32 (ptr);
780 stream_size = read32 (ptr + 4);
782 if (!bounds_check_datadir (&it, stream_off, stream_size))
783 ADD_ERROR (ctx, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off, stream_size));
788 for (string_size = 0; string_size < 32; ++string_size) {
789 if (!bounds_check_datadir (&it, offset++, 1))
790 ADD_ERROR (ctx, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i));
791 if (!ptr [string_size])
795 if (ptr [string_size])
796 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i));
798 if (!strncmp ("#Strings", ptr, 9))
799 stream_idx = STRINGS_STREAM;
800 else if (!strncmp ("#US", ptr, 4))
801 stream_idx = USER_STRINGS_STREAM;
802 else if (!strncmp ("#Blob", ptr, 6))
803 stream_idx = BLOB_STREAM;
804 else if (!strncmp ("#GUID", ptr, 6))
805 stream_idx = GUID_STREAM;
806 else if (!strncmp ("#~", ptr, 3))
807 stream_idx = TILDE_STREAM;
809 ADD_ERROR (ctx, g_strdup_printf ("Metadata stream header %d invalid name %s", i, ptr));
811 if (ctx->metadata_streams [stream_idx].offset != 0)
812 ADD_ERROR (ctx, g_strdup_printf ("Duplicated metadata stream header %s", ptr));
814 ctx->metadata_streams [stream_idx].offset = stream_off;
815 ctx->metadata_streams [stream_idx].size = stream_size;
817 offset = pad4 (offset);
818 ptr = ctx->data + offset;
821 if (!ctx->metadata_streams [TILDE_STREAM].size)
822 ADD_ERROR (ctx, g_strdup_printf ("Metadata #~ stream missing"));
823 if (!ctx->metadata_streams [GUID_STREAM].size)
824 ADD_ERROR (ctx, g_strdup_printf ("Metadata guid stream missing"));
825 if (!ctx->metadata_streams [BLOB_STREAM].size)
826 ADD_ERROR (ctx, g_strdup_printf ("Metadata blob stream missing"));
831 verify_tables_schema (VerifyContext *ctx)
833 OffsetAndSize tables_area = ctx->metadata_streams [TILDE_STREAM];
834 unsigned offset = tables_area.offset;
835 const char *ptr = ctx->data + offset;
836 guint64 valid_tables;
840 //printf ("tables_area size %d offset %x %s\n", tables_area.size, tables_area.offset, ctx->image->name);
841 if (tables_area.size < 24)
842 ADD_ERROR (ctx, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area.size));
844 //printf ("ptr %x %x\n", ptr[4], ptr[5]);
845 if (ptr [4] != 2 && ptr [4] != 1)
846 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr [4]));
848 ADD_ERROR (ctx, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr [5]));
850 if ((ptr [6] & ~0x7) != 0)
851 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]));
853 valid_tables = read64 (ptr + 8);
855 for (i = 0; i < 64; ++i) {
856 if (!(valid_tables & ((guint64)1 << i)))
859 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
860 Unused: 0x1E 0x1F 0x2D-0x3F
861 We don't care about the MS extensions.*/
862 if (i == 0x3 || i == 0x5 || i == 0x7 || i == 0x13 || i == 0x16)
863 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifies doesn't support MS specific table %x", i));
864 if (i == 0x1E || i == 0x1F || i >= 0x2D)
865 ADD_ERROR (ctx, g_strdup_printf ("Invalid table %x", i));
869 if (tables_area.size < 24 + count * 4)
870 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));
873 for (i = 0; i < 64; ++i) {
874 if (valid_tables & ((guint64)1 << i)) {
875 guint32 row_count = read32 (ptr);
876 if (row_count > (1 << 24) - 1)
877 ADD_ERROR (ctx, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i, row_count));
883 /*----------nothing from here on can use data_directory or metadata_streams ---*/
886 get_col_offset (VerifyContext *ctx, int table, int column)
888 guint32 bitfield = ctx->image->tables [table].size_bitfield;
892 offset += mono_metadata_table_size (bitfield, column);
898 get_col_size (VerifyContext *ctx, int table, int column)
900 return mono_metadata_table_size (ctx->image->tables [table].size_bitfield, column);
904 get_metadata_stream (VerifyContext *ctx, MonoStreamHeader *header)
907 res.offset = header->data - ctx->data;
908 res.size = header->size;
914 is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
916 OffsetAndSize strings = get_metadata_stream (ctx, &ctx->image->heap_strings);
918 const char *data = ctx->data + strings.offset;
920 if (offset >= strings.size)
922 if (data + offset < data) //FIXME, use a generalized and smart unsigned add with overflow check and fix the whole thing
925 if (!mono_utf8_validate_and_len_with_bounds (data + offset, strings.size - offset, &length, NULL))
927 return allow_empty || length > 0;
931 is_valid_string (VerifyContext *ctx, guint32 offset)
933 return is_valid_string_full (ctx, offset, TRUE);
937 is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
939 return is_valid_string_full (ctx, offset, FALSE);
943 is_valid_guid (VerifyContext *ctx, guint32 offset)
945 OffsetAndSize guids = get_metadata_stream (ctx, &ctx->image->heap_guid);
946 return guids.size >= 8 && guids.size - 8 >= offset;
950 get_coded_index_token (int token_kind, guint32 coded_token)
952 guint32 bits = coded_index_desc [token_kind];
953 return coded_token >> bits;
957 get_coded_index_table (int kind, guint32 coded_token)
959 guint32 idx, bits = coded_index_desc [kind];
961 idx = coded_token & ((1 << bits) - 1);
962 return coded_index_desc [kind + idx];
966 make_coded_token (int kind, guint32 table, guint32 table_idx)
968 guint32 bits = coded_index_desc [kind++];
969 guint32 tables = coded_index_desc [kind++];
971 for (i = 0; i < tables; ++i) {
972 if (coded_index_desc [kind++] == table)
973 return ((table_idx + 1) << bits) | i;
975 g_assert_not_reached ();
980 is_valid_coded_index (VerifyContext *ctx, int token_kind, guint32 coded_token)
982 guint32 bits = coded_index_desc [token_kind++];
983 guint32 table_count = coded_index_desc [token_kind++];
984 guint32 table = coded_token & ((1 << bits) - 1);
985 guint32 token = coded_token >> bits;
987 if (table >= table_count)
990 /*token_kind points to the first table idx*/
991 table = coded_index_desc [token_kind + table];
993 if (table == INVALID_TABLE)
995 return token <= ctx->image->tables [table].rows;
1002 MonoTableInfo *table;
1006 token_locator (const void *a, const void *b)
1008 RowLocator *loc = (RowLocator *)a;
1009 unsigned const char *row = (unsigned const char *)b;
1010 guint32 token = loc->col_size == 2 ? read16 (row + loc->col_offset) : read32 (row + loc->col_offset);
1012 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token, ((const char*)row - loc->table->base) / loc->table->row_size) );
1013 return (int)loc->token - (int)token;
1017 search_sorted_table (VerifyContext *ctx, int table, int column, guint32 coded_token)
1019 MonoTableInfo *tinfo = &ctx->image->tables [table];
1021 const char *res, *base;
1022 locator.token = coded_token;
1023 locator.col_offset = get_col_offset (ctx, table, column);
1024 locator.col_size = get_col_size (ctx, table, column);
1025 locator.table = tinfo;
1029 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) );
1030 res = bsearch (&locator, base, tinfo->rows, tinfo->row_size, token_locator);
1034 return (res - base) / tinfo->row_size;
1037 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1039 get_string_ptr (VerifyContext *ctx, guint offset)
1041 return ctx->image->heap_strings.data + offset;
1044 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1046 string_cmp (VerifyContext *ctx, const char *str, guint offset)
1049 return strcmp (str, "");
1051 return strcmp (str, get_string_ptr (ctx, offset));
1055 mono_verifier_is_corlib (MonoImage *image)
1057 gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
1058 TRUE : mono_security_core_clr_is_platform_image (image);
1060 return trusted_location && image->module_name && !strcmp ("mscorlib.dll", image->module_name);
1064 typedef_is_system_object (VerifyContext *ctx, guint32 *data)
1066 return mono_verifier_is_corlib (ctx->image) && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAMESPACE]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAME]);
1070 decode_value (const char *_ptr, unsigned available, unsigned *value, unsigned *size)
1073 const unsigned char *ptr = (const unsigned char *)_ptr;
1081 if ((b & 0x80) == 0) {
1084 } else if ((b & 0x40) == 0) {
1088 *value = ((b & 0x3f) << 8 | ptr [1]);
1093 *value = ((b & 0x1f) << 24) |
1103 decode_signature_header (VerifyContext *ctx, guint32 offset, int *size, const char **first_byte)
1105 MonoStreamHeader blob = ctx->image->heap_blob;
1106 guint32 value, enc_size;
1108 if (offset >= blob.size)
1111 if (!decode_value (blob.data + offset, blob.size - offset, &value, &enc_size))
1114 if (offset + enc_size + value < offset)
1117 if (offset + enc_size + value > blob.size)
1121 *first_byte = blob.data + offset + enc_size;
1126 safe_read (const char **_ptr, const char *limit, void *dest, int size)
1128 const char *ptr = *_ptr;
1129 if (ptr + size > limit)
1133 *((guint8*)dest) = *((guint8*)ptr);
1137 *((guint16*)dest) = read16 (ptr);
1141 *((guint32*)dest) = read32 (ptr);
1150 safe_read_compressed_int (const char **_ptr, const char *limit, unsigned *dest)
1153 const char *ptr = *_ptr;
1154 gboolean res = decode_value (ptr, limit - ptr, dest, &size);
1159 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1160 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1161 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1162 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1165 parse_type (VerifyContext *ctx, const char **_ptr, const char *end);
1168 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged);
1171 parse_custom_mods (VerifyContext *ctx, const char **_ptr, const char *end)
1173 const char *ptr = *_ptr;
1178 if (!safe_read8 (type, ptr, end))
1179 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the type"));
1181 if (type != MONO_TYPE_CMOD_REQD && type != MONO_TYPE_CMOD_OPT) {
1186 if (!safe_read_cint (token, ptr, end))
1187 FAIL (ctx, g_strdup ("CustomMod: Not enough room for the token"));
1189 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1190 FAIL (ctx, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token));
1198 parse_array_shape (VerifyContext *ctx, const char **_ptr, const char *end)
1200 const char *ptr = *_ptr;
1202 guint32 size, num, i;
1204 if (!safe_read8 (val, ptr, end))
1205 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for Rank"));
1208 FAIL (ctx, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1210 if (!safe_read_cint (size, ptr, end))
1211 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1213 for (i = 0; i < size; ++i) {
1214 if (!safe_read_cint (num, ptr, end))
1215 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i + 1));
1218 if (!safe_read_cint (size, ptr, end))
1219 FAIL (ctx, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1221 for (i = 0; i < size; ++i) {
1222 if (!safe_read_cint (num, ptr, end))
1223 FAIL (ctx, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i + 1));
1231 parse_generic_inst (VerifyContext *ctx, const char **_ptr, const char *end)
1233 const char *ptr = *_ptr;
1235 guint32 count, token, i;
1237 if (!safe_read8 (type, ptr, end))
1238 FAIL (ctx, g_strdup ("GenericInst: Not enough room for kind"));
1240 if (type != MONO_TYPE_CLASS && type != MONO_TYPE_VALUETYPE)
1241 FAIL (ctx, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type));
1243 if (!safe_read_cint (token, ptr, end))
1244 FAIL (ctx, g_strdup ("GenericInst: Not enough room for type token"));
1246 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1247 FAIL (ctx, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token));
1249 if (!safe_read_cint (count, ptr, end))
1250 FAIL (ctx, g_strdup ("GenericInst: Not enough room for argument count"));
1253 FAIL (ctx, g_strdup ("GenericInst: Zero arguments generic instance"));
1255 for (i = 0; i < count; ++i) {
1256 if (!parse_type (ctx, &ptr, end))
1257 FAIL (ctx, g_strdup_printf ("GenericInst: invalid generic argument %d", i + 1));
1264 parse_type (VerifyContext *ctx, const char **_ptr, const char *end)
1266 const char *ptr = *_ptr;
1270 if (!safe_read8 (type, ptr, end))
1271 FAIL (ctx, g_strdup ("Type: Not enough room for the type"));
1273 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_PTR) ||
1274 (type >= MONO_TYPE_VALUETYPE && type <= MONO_TYPE_GENERICINST) ||
1275 (type >= MONO_TYPE_I && type <= MONO_TYPE_U) ||
1276 (type >= MONO_TYPE_FNPTR && type <= MONO_TYPE_MVAR)))
1277 FAIL (ctx, g_strdup_printf ("Type: Invalid type kind %x\n", type));
1281 if (!parse_custom_mods (ctx, &ptr, end))
1282 FAIL (ctx, g_strdup ("Type: Failed to parse pointer custom attr"));
1284 if (!safe_read8 (type, ptr, end))
1285 FAIL (ctx, g_strdup ("Type: Not enough room to parse the pointer type"));
1287 if (type != MONO_TYPE_VOID) {
1289 if (!parse_type (ctx, &ptr, end))
1290 FAIL (ctx, g_strdup ("Type: Could not parse pointer type"));
1294 case MONO_TYPE_VALUETYPE:
1295 case MONO_TYPE_CLASS:
1296 if (!safe_read_cint (token, ptr, end))
1297 FAIL (ctx, g_strdup ("Type: Not enough room for the type token"));
1299 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, token))
1300 FAIL (ctx, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token));
1304 case MONO_TYPE_MVAR:
1305 if (!safe_read_cint (token, ptr, end))
1306 FAIL (ctx, g_strdup ("Type: Not enough room for to decode generic argument number"));
1309 case MONO_TYPE_ARRAY:
1310 if (!parse_type (ctx, &ptr, end))
1311 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1312 if (!parse_array_shape (ctx, &ptr, end))
1313 FAIL (ctx, g_strdup ("Type: Could not parse array shape"));
1316 case MONO_TYPE_GENERICINST:
1317 if (!parse_generic_inst (ctx, &ptr, end))
1318 FAIL (ctx, g_strdup ("Type: Could not parse generic inst"));
1321 case MONO_TYPE_FNPTR:
1322 if (!parse_method_signature (ctx, &ptr, end, TRUE, TRUE))
1323 FAIL (ctx, g_strdup ("Type: Could not parse method pointer signature"));
1326 case MONO_TYPE_SZARRAY:
1327 if (!parse_custom_mods (ctx, &ptr, end))
1328 FAIL (ctx, g_strdup ("Type: Failed to parse array element custom attr"));
1329 if (!parse_type (ctx, &ptr, end))
1330 FAIL (ctx, g_strdup ("Type: Could not parse array type"));
1338 parse_return_type (VerifyContext *ctx, const char **_ptr, const char *end)
1343 if (!parse_custom_mods (ctx, _ptr, end))
1347 if (!safe_read8 (type, ptr, end))
1348 FAIL (ctx, g_strdup ("ReturnType: Not enough room for the type"));
1350 if (type == MONO_TYPE_VOID || type == MONO_TYPE_TYPEDBYREF) {
1355 //it's a byref, update the cursor ptr
1356 if (type == MONO_TYPE_BYREF)
1359 return parse_type (ctx, _ptr, end);
1363 parse_param (VerifyContext *ctx, const char **_ptr, const char *end)
1368 if (!parse_custom_mods (ctx, _ptr, end))
1372 if (!safe_read8 (type, ptr, end))
1373 FAIL (ctx, g_strdup ("Param: Not enough room for the type"));
1375 if (type == MONO_TYPE_TYPEDBYREF) {
1380 //it's a byref, update the cursor ptr
1381 if (type == MONO_TYPE_BYREF)
1384 return parse_type (ctx, _ptr, end);
1388 parse_method_signature (VerifyContext *ctx, const char **_ptr, const char *end, gboolean allow_sentinel, gboolean allow_unmanaged)
1391 unsigned param_count = 0, gparam_count = 0, type = 0, i;
1392 const char *ptr = *_ptr;
1393 gboolean saw_sentinel = FALSE;
1395 if (!safe_read8 (cconv, ptr, end))
1396 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the call conv"));
1399 FAIL (ctx, g_strdup ("MethodSig: CallConv has 0x80 set"));
1401 if (allow_unmanaged) {
1402 if ((cconv & 0x0F) > MONO_CALL_VARARG)
1403 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv & 0x0F));
1404 } else if ((cconv & 0x0F) != MONO_CALL_DEFAULT && (cconv & 0x0F) != MONO_CALL_VARARG)
1405 FAIL (ctx, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv & 0x0F));
1407 if ((cconv & 0x10) && !safe_read_cint (gparam_count, ptr, end))
1408 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the generic param count"));
1410 if ((cconv & 0x10) && gparam_count == 0)
1411 FAIL (ctx, g_strdup ("MethodSig: Signature with generics but zero arity"));
1413 if (allow_unmanaged && (cconv & 0x10))
1414 FAIL (ctx, g_strdup ("MethodSig: Standalone signature with generic params"));
1416 if (!safe_read_cint (param_count, ptr, end))
1417 FAIL (ctx, g_strdup ("MethodSig: Not enough room for the param count"));
1419 if (!parse_return_type (ctx, &ptr, end))
1420 FAIL (ctx, g_strdup ("MethodSig: Error parsing return type"));
1422 for (i = 0; i < param_count; ++i) {
1423 if (allow_sentinel) {
1424 if (!safe_read8 (type, ptr, end))
1425 FAIL (ctx, g_strdup_printf ("MethodSig: Not enough room for param %d type", i));
1427 if (type == MONO_TYPE_SENTINEL) {
1428 if ((cconv & 0x0F) != MONO_CALL_VARARG)
1429 FAIL (ctx, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1432 FAIL (ctx, g_strdup ("MethodSig: More than one sentinel type"));
1434 saw_sentinel = TRUE;
1440 if (!parse_param (ctx, &ptr, end))
1441 FAIL (ctx, g_strdup_printf ("MethodSig: Error parsing arg %d", i));
1449 parse_property_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1452 unsigned param_count = 0, i;
1453 const char *ptr = *_ptr;
1455 if (!safe_read8 (sig, ptr, end))
1456 FAIL (ctx, g_strdup ("PropertySig: Not enough room for signature"));
1458 if (sig != 0x08 && sig != 0x28)
1459 FAIL (ctx, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig));
1461 if (!safe_read_cint (param_count, ptr, end))
1462 FAIL (ctx, g_strdup ("PropertySig: Not enough room for the param count"));
1464 if (!parse_custom_mods (ctx, &ptr, end))
1467 if (!parse_type (ctx, &ptr, end))
1468 FAIL (ctx, g_strdup ("PropertySig: Could not parse property type"));
1470 for (i = 0; i < param_count; ++i) {
1471 if (!parse_type (ctx, &ptr, end))
1472 FAIL (ctx, g_strdup_printf ("PropertySig: Error parsing arg %d", i));
1480 parse_field (VerifyContext *ctx, const char **_ptr, const char *end)
1482 const char *ptr = *_ptr;
1483 guint8 signature = 0;
1485 if (!safe_read8 (signature, ptr, end))
1486 FAIL (ctx, g_strdup ("Field: Not enough room for field signature"));
1488 if (signature != 0x06)
1489 FAIL (ctx, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature));
1492 if (!parse_custom_mods (ctx, _ptr, end))
1495 return parse_type (ctx, _ptr, end);
1499 parse_locals_signature (VerifyContext *ctx, const char **_ptr, const char *end)
1502 unsigned locals_count = 0, i;
1503 const char *ptr = *_ptr;
1505 if (!safe_read8 (sig, ptr, end))
1506 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for signature"));
1509 FAIL (ctx, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig));
1511 if (!safe_read_cint (locals_count, ptr, end))
1512 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for the param count"));
1514 if (locals_count == 0)
1515 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1517 for (i = 0; i < locals_count; ++i) {
1518 if (!safe_read8 (sig, ptr, end))
1519 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1521 if (sig == MONO_TYPE_TYPEDBYREF)
1524 while (sig == MONO_TYPE_CMOD_REQD || sig == MONO_TYPE_CMOD_OPT || sig == MONO_TYPE_PINNED) {
1525 if (sig != MONO_TYPE_PINNED && !parse_custom_mods (ctx, &ptr, end))
1526 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1527 if (!safe_read8 (sig, ptr, end))
1528 FAIL (ctx, g_strdup ("LocalsSig: Not enough room for type"));
1531 if (!parse_type (ctx, &ptr, end))
1532 FAIL (ctx, g_strdup_printf ("LocalsSig: Error parsing local %d", i));
1540 is_valid_field_signature (VerifyContext *ctx, guint32 offset)
1542 int size = 0, signature = 0;
1543 const char *ptr = NULL, *end;
1545 if (!decode_signature_header (ctx, offset, &size, &ptr))
1546 FAIL (ctx, g_strdup ("FieldSig: Could not decode signature header"));
1549 if (!safe_read8 (signature, ptr, end))
1550 FAIL (ctx, g_strdup ("FieldSig: Not enough room for the signature"));
1553 FAIL (ctx, g_strdup_printf ("FieldSig: Invalid signature %x", signature));
1556 return parse_field (ctx, &ptr, end);
1560 is_valid_method_signature (VerifyContext *ctx, guint32 offset)
1563 const char *ptr = NULL, *end;
1565 if (!decode_signature_header (ctx, offset, &size, &ptr))
1566 FAIL (ctx, g_strdup ("MethodSig: Could not decode signature header"));
1569 return parse_method_signature (ctx, &ptr, end, FALSE, FALSE);
1573 is_valid_method_or_field_signature (VerifyContext *ctx, guint32 offset)
1576 unsigned signature = 0;
1577 const char *ptr = NULL, *end;
1579 if (!decode_signature_header (ctx, offset, &size, &ptr))
1580 FAIL (ctx, g_strdup ("MemberRefSig: Could not decode signature header"));
1583 if (!safe_read8 (signature, ptr, end))
1584 FAIL (ctx, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1587 if (signature == 0x06)
1588 return parse_field (ctx, &ptr, end);
1590 return parse_method_signature (ctx, &ptr, end, TRUE, FALSE);
1594 is_vald_cattr_blob (VerifyContext *ctx, guint32 offset)
1598 const char *ptr = NULL, *end;
1603 if (!decode_signature_header (ctx, offset, &size, &ptr))
1604 FAIL (ctx, g_strdup ("CustomAttribute: Could not decode signature header"));
1607 if (!safe_read16 (prolog, ptr, end))
1608 FAIL (ctx, g_strdup ("CustomAttribute: Not enough room for prolog"));
1611 FAIL (ctx, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog));
1617 is_valid_marshal_spec (VerifyContext *ctx, guint32 offset)
1619 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1620 //TODO do proper verification
1621 return blob.size >= 1 && blob.size - 1 >= offset;
1625 is_valid_permission_set (VerifyContext *ctx, guint32 offset)
1627 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1628 //TODO do proper verification
1629 return blob.size >= 1 && blob.size - 1 >= offset;
1633 is_valid_standalonesig_blob (VerifyContext *ctx, guint32 offset)
1636 unsigned signature = 0;
1637 const char *ptr = NULL, *end;
1639 if (!decode_signature_header (ctx, offset, &size, &ptr))
1640 FAIL (ctx, g_strdup ("StandAloneSig: Could not decode signature header"));
1643 if (!safe_read8 (signature, ptr, end))
1644 FAIL (ctx, g_strdup ("StandAloneSig: Not enough room for the call conv"));
1647 if (signature == 0x07)
1648 return parse_locals_signature (ctx, &ptr, end);
1649 return parse_method_signature (ctx, &ptr, end, TRUE, TRUE);
1653 is_valid_property_sig_blob (VerifyContext *ctx, guint32 offset)
1656 const char *ptr = NULL, *end;
1658 if (!decode_signature_header (ctx, offset, &size, &ptr))
1659 FAIL (ctx, g_strdup ("PropertySig: Could not decode signature header"));
1662 return parse_property_signature (ctx, &ptr, end);
1666 is_valid_typespec_blob (VerifyContext *ctx, guint32 offset)
1669 const char *ptr = NULL, *end;
1673 if (!decode_signature_header (ctx, offset, &size, &ptr))
1674 FAIL (ctx, g_strdup ("TypeSpec: Could not decode signature header"));
1677 if (!parse_custom_mods (ctx, &ptr, end))
1680 if (!safe_read8 (type, ptr, end))
1681 FAIL (ctx, g_strdup ("TypeSpec: Not enough room for type"));
1684 if (type == MONO_TYPE_TYPEDBYREF)
1687 return parse_type (ctx, &ptr, end);
1691 is_valid_methodspec_blog (VerifyContext *ctx, guint32 offset)
1694 const char *ptr = NULL, *end;
1696 guint32 count = 0, i;
1698 if (!decode_signature_header (ctx, offset, &size, &ptr))
1699 FAIL (ctx, g_strdup ("MethodSpec: Could not decode signature header"));
1702 if (!safe_read8 (type, ptr, end))
1703 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for call convention"));
1706 FAIL (ctx, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type));
1708 if (!safe_read_cint (count, ptr, end))
1709 FAIL (ctx, g_strdup ("MethodSpec: Not enough room for parameter count"));
1712 FAIL (ctx, g_strdup ("MethodSpec: Zero generic argument count"));
1714 for (i = 0; i < count; ++i) {
1715 if (!parse_type (ctx, &ptr, end))
1716 FAIL (ctx, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i + 1));
1722 is_valid_blob_object (VerifyContext *ctx, guint32 offset, guint32 minsize)
1724 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1725 guint32 entry_size, bytes;
1727 if (blob.size < offset)
1730 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1733 if (entry_size < minsize)
1736 if (CHECK_ADD4_OVERFLOW_UN (entry_size, bytes))
1738 entry_size += bytes;
1740 return !ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size);
1744 is_valid_constant (VerifyContext *ctx, guint32 type, guint32 offset)
1746 OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
1747 guint32 size, entry_size, bytes;
1749 if (blob.size < offset)
1750 FAIL (ctx, g_strdup ("ContantValue: invalid offset"));
1752 if (!decode_value (ctx->data + offset + blob.offset, blob.size - blob.offset, &entry_size, &bytes))
1753 FAIL (ctx, g_strdup ("ContantValue: not enough space to decode size"));
1755 if (type == MONO_TYPE_STRING) {
1756 //String is encoded as: compressed_int:len len *bytes
1759 if (ADD_IS_GREATER_OR_OVF (offset, entry_size, blob.size))
1760 FAIL (ctx, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size * 2, blob.size - offset));
1766 case MONO_TYPE_BOOLEAN:
1771 case MONO_TYPE_CHAR:
1779 case MONO_TYPE_CLASS:
1789 g_assert_not_reached ();
1792 if (size != entry_size)
1793 FAIL (ctx, g_strdup_printf ("ContantValue: Expected size %d but got %d", size, entry_size));
1797 if (ADD_IS_GREATER_OR_OVF (offset, size, blob.size))
1798 FAIL (ctx, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size, blob.size - offset));
1800 if (type == MONO_TYPE_CLASS && read32 (ctx->data + blob.offset + offset))
1801 FAIL (ctx, g_strdup_printf ("ContantValue: Type is class but value is not null"));
1805 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
1806 //only 0x01, 0x40 and 0x80 are allowed
1807 #define SECTION_HEADER_INVALID_FLAGS 0x3E
1810 is_valid_method_header (VerifyContext *ctx, guint32 rva)
1812 guint32 local_vars_tok, code_size, offset = mono_cli_rva_image_map (ctx->image, rva);
1814 guint16 fat_header = 0, size = 0, max_stack;
1815 const char *ptr = NULL, *end;
1817 if (offset == INVALID_ADDRESS)
1818 FAIL (ctx, g_strdup ("MethodHeader: Invalid RVA"));
1820 ptr = ctx->data + offset;
1821 end = ctx->data + ctx->size; /*no worries if it spawns multiple sections*/
1823 if (!safe_read8 (header, ptr, end))
1824 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for header"));
1826 switch (header & 0x3) {
1829 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header & 0x3));
1832 if (ADDP_IS_GREATER_OR_OVF (ptr, header, end))
1833 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header, (int)(end - ptr)));
1838 if (!safe_read16 (fat_header, ptr, end))
1839 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for fat header"));
1841 size = (fat_header >> 12) & 0xF;
1843 FAIL (ctx, g_strdup ("MethodHeader: header size must be 3"));
1845 if (!safe_read16 (max_stack, ptr, end))
1846 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for max stack"));
1848 if (!safe_read32 (code_size, ptr, end))
1849 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for code size"));
1851 if (!safe_read32 (local_vars_tok, ptr, end))
1852 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for local vars tok"));
1854 if (local_vars_tok) {
1855 if (((local_vars_tok >> 24) & 0xFF) != 0x11)
1856 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok >> 24) & 0xFF)));
1857 if ((local_vars_tok & 0xFFFFFF) > ctx->image->tables [MONO_TABLE_STANDALONESIG].rows)
1858 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok & 0xFFFFFF));
1861 if (fat_header & FAT_HEADER_INVALID_FLAGS)
1862 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header & FAT_HEADER_INVALID_FLAGS));
1864 if (ADDP_IS_GREATER_OR_OVF (ptr, code_size, end))
1865 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size));
1867 if (!(fat_header & 0x08))
1873 guint32 section_header = 0, section_size = 0;
1876 ptr = dword_align (ptr);
1877 if (!safe_read32 (section_header, ptr, end))
1878 FAIL (ctx, g_strdup ("MethodHeader: Not enough room for data section header"));
1880 if (section_header & SECTION_HEADER_INVALID_FLAGS)
1881 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header & SECTION_HEADER_INVALID_FLAGS));
1883 is_fat = (section_header & METHOD_HEADER_SECTION_FAT_FORMAT) != 0;
1884 section_size = (section_header >> 8) & (is_fat ? 0xFFFFFF : 0xFF);
1886 if (section_size < 4)
1887 FAIL (ctx, g_strdup_printf ("MethodHeader: Section size too small"));
1889 if (ADDP_IS_GREATER_OR_OVF (ptr, section_size - 4, end)) /*must be section_size -4 as ptr was incremented by safe_read32*/
1890 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size));
1892 if (section_header & METHOD_HEADER_SECTION_EHTABLE) {
1893 guint32 i, clauses = (section_size - 4) / (is_fat ? 24 : 12);
1894 if (clauses * (is_fat ? 24 : 12) + 4 != section_size)
1895 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the proper size", section_size));
1897 /* only verify the class token is verified as the rest is done by the IL verifier*/
1898 for (i = 0; i < clauses; ++i) {
1900 guint32 class_token = 0;
1901 ptr += (is_fat ? 20 : 8);
1902 if (!safe_read32 (class_token, ptr, end))
1903 FAIL (ctx, g_strdup_printf ("MethodHeader: Not enough room for section %d", i));
1904 if (flags == MONO_EXCEPTION_CLAUSE_NONE && class_token) {
1905 guint table = mono_metadata_token_table (class_token);
1906 if (table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPESPEC)
1907 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i, table));
1908 if (mono_metadata_token_index (class_token) > ctx->image->tables [table].rows)
1909 FAIL (ctx, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i, mono_metadata_token_index (class_token)));
1914 if (!(section_header & METHOD_HEADER_SECTION_MORE_SECTS))
1921 verify_module_table (VerifyContext *ctx)
1923 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULE];
1924 guint32 data [MONO_MODULE_SIZE];
1926 if (table->rows != 1)
1927 ADD_ERROR (ctx, g_strdup_printf ("Module table must have exactly one row, but have %d", table->rows));
1929 mono_metadata_decode_row (table, 0, data, MONO_MODULE_SIZE);
1931 if (!is_valid_non_empty_string (ctx, data [MONO_MODULE_NAME]))
1932 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data [MONO_MODULE_NAME]));
1934 if (!is_valid_guid (ctx, data [MONO_MODULE_MVID]))
1935 ADD_ERROR (ctx, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data [MONO_MODULE_MVID]));
1937 if (data [MONO_MODULE_ENC] != 0)
1938 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero Enc field %x", data [MONO_MODULE_ENC]));
1940 if (data [MONO_MODULE_ENCBASE] != 0)
1941 ADD_ERROR (ctx, g_strdup_printf ("Module has a non zero EncBase field %x", data [MONO_MODULE_ENCBASE]));
1945 verify_typeref_table (VerifyContext *ctx)
1947 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEREF];
1948 guint32 data [MONO_TYPEREF_SIZE];
1951 for (i = 0; i < table->rows; ++i) {
1952 mono_metadata_decode_row (table, i, data, MONO_TYPEREF_SIZE);
1953 if (!is_valid_coded_index (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1954 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i, data [MONO_TYPEREF_SCOPE]));
1956 if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
1957 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i));
1959 if (!data [MONO_TYPEREF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAME]))
1960 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d name token 0x%08x", i, data [MONO_TYPEREF_NAME]));
1962 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
1963 ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d namespace token 0x%08x", i, data [MONO_TYPEREF_NAMESPACE]));
1967 /*bits 9,11,14,15,19,21,24-31 */
1968 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
1970 verify_typedef_table (VerifyContext *ctx)
1972 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
1973 guint32 data [MONO_TYPEDEF_SIZE];
1974 guint32 fieldlist = 1, methodlist = 1;
1977 if (table->rows == 0)
1978 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
1980 for (i = 0; i < table->rows; ++i) {
1981 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
1982 if (data [MONO_TYPEDEF_FLAGS] & INVALID_TYPEDEF_FLAG_BITS)
1983 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i, data [MONO_TYPEDEF_FLAGS]));
1985 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_LAYOUT_MASK) == 0x18)
1986 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i));
1988 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == 0x30000)
1989 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
1991 if ((data [MONO_TYPEDEF_FLAGS] & 0xC00000) != 0)
1992 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i));
1994 if ((data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) && (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_ABSTRACT) == 0)
1995 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i));
1997 if (!data [MONO_TYPEDEF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEDEF_NAME]))
1998 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i, data [MONO_TYPEDEF_NAME]));
2000 if (data [MONO_TYPEREF_NAMESPACE] && !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAMESPACE]))
2001 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i, data [MONO_TYPEREF_NAMESPACE]));
2003 if (data [MONO_TYPEDEF_EXTENDS] && !is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
2004 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
2006 if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
2007 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
2009 if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2010 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
2012 if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
2013 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));
2015 if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
2016 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
2018 if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
2019 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
2021 if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
2022 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));
2024 fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
2025 methodlist = data [MONO_TYPEDEF_METHOD_LIST];
2030 verify_typedef_table_full (VerifyContext *ctx)
2032 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2033 guint32 data [MONO_TYPEDEF_SIZE];
2036 if (table->rows == 0)
2037 ADD_ERROR (ctx, g_strdup_printf ("Typedef table must have exactly at least one row"));
2039 for (i = 0; i < table->rows; ++i) {
2040 mono_metadata_decode_row (table, i, data, MONO_TYPEDEF_SIZE);
2043 if (data [MONO_TYPEDEF_EXTENDS] != 0)
2044 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2048 if (data [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_INTERFACE) {
2049 if (data [MONO_TYPEDEF_EXTENDS])
2050 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i));
2052 gboolean is_sys_obj = typedef_is_system_object (ctx, data);
2053 gboolean has_parent = get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]) != 0;
2057 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i));
2060 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
2068 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2070 verify_field_table (VerifyContext *ctx)
2072 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2073 guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
2076 module_field_list = (guint32)-1;
2077 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2078 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2079 module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
2082 for (i = 0; i < table->rows; ++i) {
2083 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2084 flags = data [MONO_FIELD_FLAGS];
2086 if (flags & INVALID_FIELD_FLAG_BITS)
2087 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i, flags));
2089 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == 0x7)
2090 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i));
2092 if ((flags & (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY)) == (FIELD_ATTRIBUTE_LITERAL | FIELD_ATTRIBUTE_INIT_ONLY))
2093 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i));
2095 if ((flags & FIELD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & FIELD_ATTRIBUTE_SPECIAL_NAME))
2096 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i));
2098 if ((flags & FIELD_ATTRIBUTE_LITERAL) && !(flags & FIELD_ATTRIBUTE_STATIC))
2099 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but not Static", i));
2101 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) &&
2102 search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_FIELD, i)) == -1)
2103 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i));
2105 if ((flags & FIELD_ATTRIBUTE_HAS_DEFAULT) &&
2106 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2107 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2109 if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
2110 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
2111 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
2113 if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
2114 search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
2115 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
2117 if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
2118 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
2120 if (data [MONO_FIELD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_FIELD_SIGNATURE], 1))
2121 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i, data [MONO_FIELD_SIGNATURE]));
2123 //TODO verify contant flag
2125 if (i + 1 < module_field_list) {
2126 guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
2127 if (!(flags & FIELD_ATTRIBUTE_STATIC))
2128 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
2129 if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
2130 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
2136 verify_field_table_full (VerifyContext *ctx)
2138 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
2139 guint32 data [MONO_FIELD_SIZE];
2142 for (i = 0; i < table->rows; ++i) {
2143 mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
2145 if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
2146 ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
2150 /*bits 6,8,9,10,11,13,14,15*/
2151 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2153 verify_method_table (VerifyContext *ctx)
2155 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2156 guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
2157 guint32 paramlist = 1;
2158 gboolean is_ctor, is_cctor;
2162 module_method_list = (guint32)-1;
2163 if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
2164 MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
2165 module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
2168 for (i = 0; i < table->rows; ++i) {
2169 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2170 rva = data [MONO_METHOD_RVA];
2171 implflags = data [MONO_METHOD_IMPLFLAGS];
2172 flags = data [MONO_METHOD_FLAGS];
2173 access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
2174 code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
2177 if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
2178 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
2181 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
2183 if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
2184 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
2186 name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
2187 is_ctor = !strcmp (".ctor", name);
2188 is_cctor = !strcmp (".cctor", name);
2190 if ((is_ctor || is_cctor) &&
2191 search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
2192 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
2194 if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
2195 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
2197 if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
2198 if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2199 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
2200 if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
2201 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
2204 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
2205 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
2207 if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
2208 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
2210 //XXX no checks against cas stuff 10,11,12,13)
2212 //TODO check iface with .ctor (15,16)
2214 if (i + 1 < module_method_list) {
2215 if (!(flags & METHOD_ATTRIBUTE_STATIC))
2216 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
2217 if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
2218 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
2219 if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
2220 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
2223 //TODO check valuetype for synchronized
2225 if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
2226 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
2228 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (flags & METHOD_ATTRIBUTE_VIRTUAL))
2229 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
2231 if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
2232 !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2233 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
2235 if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
2236 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
2238 //TODO check signature contents
2241 if (flags & METHOD_ATTRIBUTE_ABSTRACT)
2242 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
2243 if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
2244 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
2246 if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
2247 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
2250 if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
2252 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
2253 if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
2254 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
2256 if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
2257 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
2259 if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
2260 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
2262 if (data [MONO_METHOD_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHOD_SIGNATURE], 1))
2263 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i, data [MONO_METHOD_SIGNATURE]));
2265 if (data [MONO_METHOD_PARAMLIST] == 0)
2266 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
2268 if (data [MONO_METHOD_PARAMLIST] < paramlist)
2269 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));
2271 if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
2272 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
2274 paramlist = data [MONO_METHOD_PARAMLIST];
2280 verify_method_table_full (VerifyContext *ctx)
2282 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2283 guint32 data [MONO_METHOD_SIZE], rva;
2286 for (i = 0; i < table->rows; ++i) {
2287 mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
2288 rva = data [MONO_METHOD_RVA];
2290 if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
2291 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i, data [MONO_METHOD_SIGNATURE]));
2293 if (rva && !is_valid_method_header (ctx, rva))
2294 ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
2299 get_next_param_count (VerifyContext *ctx, guint32 *current_method)
2301 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
2302 guint32 row = *current_method;
2303 guint32 paramlist, tmp;
2306 paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
2307 while (row < table->rows) {
2308 tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
2309 if (tmp > paramlist) {
2310 *current_method = row;
2311 return tmp - paramlist;
2316 /*no more methods, all params apply to the last one*/
2317 *current_method = table->rows;
2322 #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))
2324 verify_param_table (VerifyContext *ctx)
2326 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
2327 guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
2328 gboolean first_param = TRUE;
2331 if (ctx->image->tables [MONO_TABLE_METHOD].rows == 0) {
2332 if (table->rows > 0)
2333 ADD_ERROR (ctx, g_strdup ("Param table has rows while the method table has zero"));
2337 remaining_params = get_next_param_count (ctx, ¤t_method);
2339 for (i = 0; i < table->rows; ++i) {
2340 mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
2341 flags = data [MONO_PARAM_FLAGS];
2343 if (flags & INVALID_PARAM_FLAGS_BITS)
2344 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
2346 if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
2347 if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
2348 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
2350 if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
2351 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
2354 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)
2355 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
2357 if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
2358 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
2360 if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
2361 ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
2363 first_param = FALSE;
2364 sequence = data [MONO_PARAM_SEQUENCE];
2365 if (--remaining_params == 0) {
2366 remaining_params = get_next_param_count (ctx, ¤t_method);
2373 verify_interfaceimpl_table (VerifyContext *ctx)
2375 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
2376 guint32 data [MONO_INTERFACEIMPL_SIZE];
2379 for (i = 0; i < table->rows; ++i) {
2380 mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
2381 if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
2382 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2384 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2385 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
2387 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
2388 ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
2393 verify_memberref_table (VerifyContext *ctx)
2395 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2396 guint32 data [MONO_MEMBERREF_SIZE];
2399 for (i = 0; i < table->rows; ++i) {
2400 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2402 if (!is_valid_coded_index (ctx, MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2403 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i, data [MONO_MEMBERREF_CLASS]));
2405 if (!get_coded_index_token (MEMBERREF_PARENT_DESC, data [MONO_MEMBERREF_CLASS]))
2406 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i));
2408 if (!is_valid_non_empty_string (ctx, data [MONO_MEMBERREF_NAME]))
2409 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i, data [MONO_MEMBERREF_NAME]));
2411 if (data [MONO_MEMBERREF_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_MEMBERREF_SIGNATURE], 1))
2412 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i, data [MONO_MEMBERREF_SIGNATURE]));
2418 verify_memberref_table_full (VerifyContext *ctx)
2420 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MEMBERREF];
2421 guint32 data [MONO_MEMBERREF_SIZE];
2424 for (i = 0; i < table->rows; ++i) {
2425 mono_metadata_decode_row (table, i, data, MONO_MEMBERREF_SIZE);
2427 if (!is_valid_method_or_field_signature (ctx, data [MONO_MEMBERREF_SIGNATURE]))
2428 ADD_ERROR (ctx, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i, data [MONO_MEMBERREF_SIGNATURE]));
2433 verify_constant_table (VerifyContext *ctx)
2435 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CONSTANT];
2436 guint32 data [MONO_CONSTANT_SIZE], type;
2439 for (i = 0; i < table->rows; ++i) {
2440 mono_metadata_decode_row (table, i, data, MONO_CONSTANT_SIZE);
2441 type = data [MONO_CONSTANT_TYPE];
2443 if (!((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_STRING) || type == MONO_TYPE_CLASS))
2444 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i, type));
2446 if (!is_valid_coded_index (ctx, HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2447 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i, data [MONO_CONSTANT_PARENT]));
2449 if (!get_coded_index_token (HAS_CONSTANT_DESC, data [MONO_CONSTANT_PARENT]))
2450 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i));
2452 if (!is_valid_constant (ctx, type, data [MONO_CONSTANT_VALUE]))
2453 ADD_ERROR (ctx, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i, data [MONO_CONSTANT_VALUE]));
2458 verify_cattr_table (VerifyContext *ctx)
2460 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2461 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2464 for (i = 0; i < table->rows; ++i) {
2465 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2467 if (!is_valid_coded_index (ctx, HAS_CATTR_DESC, data [MONO_CUSTOM_ATTR_PARENT]))
2468 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2470 if (!is_valid_coded_index (ctx, CATTR_TYPE_DESC, data [MONO_CUSTOM_ATTR_TYPE]))
2471 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i, data [MONO_CUSTOM_ATTR_PARENT]));
2473 if (data [MONO_CUSTOM_ATTR_VALUE] && !is_valid_blob_object (ctx, data [MONO_CUSTOM_ATTR_VALUE], 0))
2474 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2479 verify_cattr_table_full (VerifyContext *ctx)
2481 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2482 guint32 data [MONO_CUSTOM_ATTR_SIZE];
2485 for (i = 0; i < table->rows; ++i) {
2486 mono_metadata_decode_row (table, i, data, MONO_CUSTOM_ATTR_SIZE);
2488 if (!is_vald_cattr_blob (ctx, data [MONO_CUSTOM_ATTR_VALUE]))
2489 ADD_ERROR (ctx, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i, data [MONO_CUSTOM_ATTR_VALUE]));
2494 verify_field_marshal_table (VerifyContext *ctx)
2496 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2497 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2500 for (i = 0; i < table->rows; ++i) {
2501 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2503 if (!is_valid_coded_index (ctx, HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2504 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i, data [MONO_FIELD_MARSHAL_PARENT]));
2506 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC, data [MONO_FIELD_MARSHAL_PARENT]))
2507 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i));
2509 if (!data [MONO_FIELD_MARSHAL_NATIVE_TYPE])
2510 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i));
2512 if (!is_valid_blob_object (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE], 1))
2513 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2518 verify_field_marshal_table_full (VerifyContext *ctx)
2520 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDMARSHAL];
2521 guint32 data [MONO_FIELD_MARSHAL_SIZE];
2524 for (i = 0; i < table->rows; ++i) {
2525 mono_metadata_decode_row (table, i, data, MONO_FIELD_MARSHAL_SIZE);
2527 if (!is_valid_marshal_spec (ctx, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]))
2528 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i, data [MONO_FIELD_MARSHAL_NATIVE_TYPE]));
2533 verify_decl_security_table (VerifyContext *ctx)
2535 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2536 guint32 data [MONO_DECL_SECURITY_SIZE];
2539 for (i = 0; i < table->rows; ++i) {
2540 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2542 if (!is_valid_coded_index (ctx, HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2543 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i, data [MONO_DECL_SECURITY_PARENT]));
2545 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC, data [MONO_DECL_SECURITY_PARENT]))
2546 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i));
2548 if (!data [MONO_DECL_SECURITY_PERMISSIONSET])
2549 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i));
2554 verify_decl_security_table_full (VerifyContext *ctx)
2556 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_DECLSECURITY];
2557 guint32 data [MONO_DECL_SECURITY_SIZE];
2560 for (i = 0; i < table->rows; ++i) {
2561 mono_metadata_decode_row (table, i, data, MONO_DECL_SECURITY_SIZE);
2563 if (!is_valid_permission_set (ctx, data [MONO_DECL_SECURITY_PERMISSIONSET]))
2564 ADD_ERROR (ctx, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i, data [MONO_DECL_SECURITY_PERMISSIONSET]));
2569 verify_class_layout_table (VerifyContext *ctx)
2571 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_CLASSLAYOUT];
2572 guint32 data [MONO_CLASS_LAYOUT_SIZE];
2575 for (i = 0; i < table->rows; ++i) {
2576 mono_metadata_decode_row (table, i, data, MONO_CLASS_LAYOUT_SIZE);
2578 if (!data [MONO_CLASS_LAYOUT_PARENT] || data[MONO_CLASS_LAYOUT_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2579 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
2581 switch (data [MONO_CLASS_LAYOUT_PACKING_SIZE]) {
2593 ADD_ERROR (ctx, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i, data [MONO_CLASS_LAYOUT_PACKING_SIZE]));
2599 verify_field_layout_table (VerifyContext *ctx)
2601 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDLAYOUT];
2602 guint32 data [MONO_FIELD_LAYOUT_SIZE];
2605 for (i = 0; i < table->rows; ++i) {
2606 mono_metadata_decode_row (table, i, data, MONO_FIELD_LAYOUT_SIZE);
2608 if (!data [MONO_FIELD_LAYOUT_FIELD] || data[MONO_FIELD_LAYOUT_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2609 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i, data [MONO_FIELD_LAYOUT_FIELD]));
2614 verify_standalonesig_table (VerifyContext *ctx)
2616 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2617 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2620 for (i = 0; i < table->rows; ++i) {
2621 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2623 if (data [MONO_STAND_ALONE_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_STAND_ALONE_SIGNATURE], 1))
2624 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2629 verify_standalonesig_table_full (VerifyContext *ctx)
2631 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_STANDALONESIG];
2632 guint32 data [MONO_STAND_ALONE_SIGNATURE_SIZE];
2635 for (i = 0; i < table->rows; ++i) {
2636 mono_metadata_decode_row (table, i, data, MONO_STAND_ALONE_SIGNATURE_SIZE);
2638 if (!is_valid_standalonesig_blob (ctx, data [MONO_STAND_ALONE_SIGNATURE]))
2639 ADD_ERROR (ctx, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i, data [MONO_STAND_ALONE_SIGNATURE]));
2644 verify_eventmap_table (VerifyContext *ctx)
2646 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENTMAP];
2647 guint32 data [MONO_EVENT_MAP_SIZE], eventlist = 0;
2650 for (i = 0; i < table->rows; ++i) {
2651 mono_metadata_decode_row (table, i, data, MONO_EVENT_MAP_SIZE);
2653 if (!data [MONO_EVENT_MAP_PARENT] || data [MONO_EVENT_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2654 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i, data [MONO_EVENT_MAP_PARENT]));
2656 if (!data [MONO_EVENT_MAP_EVENTLIST] || data [MONO_EVENT_MAP_EVENTLIST] <= eventlist)
2657 ADD_ERROR (ctx, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i, data [MONO_EVENT_MAP_EVENTLIST]));
2659 eventlist = data [MONO_EVENT_MAP_EVENTLIST];
2663 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
2665 verify_event_table (VerifyContext *ctx)
2667 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2668 guint32 data [MONO_EVENT_SIZE];
2671 for (i = 0; i < table->rows; ++i) {
2672 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2674 if (data [MONO_EVENT_FLAGS] & INVALID_EVENT_FLAGS_BITS)
2675 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i, data [MONO_EVENT_FLAGS]));
2677 if (!is_valid_non_empty_string (ctx, data [MONO_EVENT_NAME]))
2678 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d Name field %08x", i, data [MONO_EVENT_NAME]));
2680 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_EVENT_TYPE]))
2681 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d EventType field %08x", i, data [MONO_EVENT_TYPE]));
2686 verify_event_table_full (VerifyContext *ctx)
2688 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EVENT];
2689 MonoTableInfo *sema_table = &ctx->image->tables [MONO_TABLE_METHODSEMANTICS];
2690 guint32 data [MONO_EVENT_SIZE], sema_data [MONO_METHOD_SEMA_SIZE], token;
2691 gboolean found_add, found_remove;
2694 for (i = 0; i < table->rows; ++i) {
2695 mono_metadata_decode_row (table, i, data, MONO_EVENT_SIZE);
2697 token = make_coded_token (HAS_SEMANTICS_DESC, MONO_TABLE_EVENT, i);
2698 idx = search_sorted_table (ctx, MONO_TABLE_METHODSEMANTICS, MONO_METHOD_SEMA_ASSOCIATION, token);
2700 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i));
2702 //first we move to the first row for this event
2704 if (mono_metadata_decode_row_col (sema_table, idx - 1, MONO_METHOD_SEMA_ASSOCIATION) != token)
2708 //now move forward looking for AddOn and RemoveOn rows
2709 found_add = found_remove = FALSE;
2710 while (idx < sema_table->rows) {
2711 mono_metadata_decode_row (sema_table, idx, sema_data, MONO_METHOD_SEMA_SIZE);
2712 if (sema_data [MONO_METHOD_SEMA_ASSOCIATION] != token)
2714 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_ADD_ON)
2716 if (sema_data [MONO_METHOD_SEMA_SEMANTICS] & METHOD_SEMANTIC_REMOVE_ON)
2717 found_remove = TRUE;
2718 if (found_add && found_remove)
2724 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2726 ADD_ERROR (ctx, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i));
2731 verify_propertymap_table (VerifyContext *ctx)
2733 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTYMAP];
2734 guint32 data [MONO_PROPERTY_MAP_SIZE], propertylist = 0;
2737 for (i = 0; i < table->rows; ++i) {
2738 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_MAP_SIZE);
2740 if (!data [MONO_PROPERTY_MAP_PARENT] || data [MONO_PROPERTY_MAP_PARENT] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2741 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i, data [MONO_PROPERTY_MAP_PARENT]));
2743 if (!data [MONO_PROPERTY_MAP_PROPERTY_LIST] || data [MONO_PROPERTY_MAP_PROPERTY_LIST] <= propertylist)
2744 ADD_ERROR (ctx, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i, data [MONO_PROPERTY_MAP_PROPERTY_LIST]));
2746 propertylist = data [MONO_PROPERTY_MAP_PROPERTY_LIST];
2750 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
2752 verify_property_table (VerifyContext *ctx)
2754 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PROPERTY];
2755 guint32 data [MONO_PROPERTY_SIZE];
2758 for (i = 0; i < table->rows; ++i) {
2759 mono_metadata_decode_row (table, i, data, MONO_PROPERTY_SIZE);
2761 if (data [MONO_PROPERTY_FLAGS] & INVALID_PROPERTY_FLAGS_BITS)
2762 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i, data [MONO_PROPERTY_FLAGS]));
2764 if (!is_valid_non_empty_string (ctx, data [MONO_PROPERTY_NAME]))
2765 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Name field %08x", i, data [MONO_PROPERTY_NAME]));
2767 if (!is_valid_property_sig_blob (ctx, data [MONO_PROPERTY_TYPE]))
2768 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d Type field %08x", i, data [MONO_PROPERTY_TYPE]));
2770 if ((data [MONO_PROPERTY_FLAGS] & PROPERTY_ATTRIBUTE_HAS_DEFAULT) &&
2771 search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PROPERTY, i)) == -1)
2772 ADD_ERROR (ctx, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i));
2778 verify_methodimpl_table (VerifyContext *ctx)
2780 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODIMPL];
2781 guint32 data [MONO_METHODIMPL_SIZE];
2784 for (i = 0; i < table->rows; ++i) {
2785 mono_metadata_decode_row (table, i, data, MONO_METHODIMPL_SIZE);
2787 if (!data [MONO_METHODIMPL_CLASS] || data [MONO_METHODIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows + 1)
2788 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2790 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2791 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2793 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_BODY]))
2794 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i, data [MONO_METHODIMPL_BODY]));
2796 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2797 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2799 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODIMPL_DECLARATION]))
2800 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i, data [MONO_METHODIMPL_DECLARATION]));
2805 verify_moduleref_table (VerifyContext *ctx)
2807 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MODULEREF];
2808 guint32 data [MONO_MODULEREF_SIZE];
2811 for (i = 0; i < table->rows; ++i) {
2812 mono_metadata_decode_row (table, i, data, MONO_MODULEREF_SIZE);
2814 if (!is_valid_non_empty_string (ctx, data[MONO_MODULEREF_NAME]))
2815 ADD_ERROR (ctx, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i, data [MONO_TABLE_TYPEDEF]));
2820 verify_typespec_table (VerifyContext *ctx)
2822 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2823 guint32 data [MONO_TYPESPEC_SIZE];
2826 for (i = 0; i < table->rows; ++i) {
2827 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2829 if (data [MONO_TYPESPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_TYPESPEC_SIGNATURE], 1))
2830 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2835 verify_typespec_table_full (VerifyContext *ctx)
2837 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_TYPESPEC];
2838 guint32 data [MONO_TYPESPEC_SIZE];
2841 for (i = 0; i < table->rows; ++i) {
2842 mono_metadata_decode_row (table, i, data, MONO_TYPESPEC_SIZE);
2844 if (!is_valid_typespec_blob (ctx, data [MONO_TYPESPEC_SIGNATURE]))
2845 ADD_ERROR (ctx, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i, data [MONO_TYPESPEC_SIGNATURE]));
2849 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10))
2851 verify_implmap_table (VerifyContext *ctx)
2853 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_IMPLMAP];
2854 guint32 data [MONO_IMPLMAP_SIZE], cconv;
2857 for (i = 0; i < table->rows; ++i) {
2858 mono_metadata_decode_row (table, i, data, MONO_IMPLMAP_SIZE);
2860 if (data [MONO_IMPLMAP_FLAGS] & INVALID_IMPLMAP_FLAGS_BITS)
2861 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i, data [MONO_IMPLMAP_FLAGS]));
2863 cconv = data [MONO_IMPLMAP_FLAGS] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK;
2864 if (cconv == 0 || cconv == 0x0600 || cconv == 0x0700)
2865 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i, cconv));
2867 if (!is_valid_coded_index (ctx, MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2868 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i, data [MONO_IMPLMAP_MEMBER]));
2870 if (get_coded_index_table (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]) != MONO_TABLE_METHOD)
2871 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i, data [MONO_IMPLMAP_MEMBER]));
2873 if (!get_coded_index_token (MEMBER_FORWARDED_DESC, data [MONO_IMPLMAP_MEMBER]))
2874 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d null token", i));
2876 if (!is_valid_non_empty_string (ctx, data [MONO_IMPLMAP_NAME]))
2877 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i, data [MONO_IMPLMAP_NAME]));
2879 if (!data [MONO_IMPLMAP_SCOPE] || data [MONO_IMPLMAP_SCOPE] > ctx->image->tables [MONO_TABLE_MODULEREF].rows + 1)
2880 ADD_ERROR (ctx, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i, data [MONO_IMPLMAP_SCOPE]));
2885 verify_fieldrva_table (VerifyContext *ctx)
2887 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELDRVA];
2888 guint32 data [MONO_FIELD_RVA_SIZE];
2891 for (i = 0; i < table->rows; ++i) {
2892 mono_metadata_decode_row (table, i, data, MONO_FIELD_RVA_SIZE);
2894 if (!data [MONO_FIELD_RVA_RVA] || mono_cli_rva_image_map (ctx->image, data [MONO_FIELD_RVA_RVA]) == INVALID_ADDRESS)
2895 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i, data [MONO_FIELD_RVA_RVA]));
2897 if (!data [MONO_FIELD_RVA_FIELD] || data [MONO_FIELD_RVA_FIELD] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
2898 ADD_ERROR (ctx, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i, data [MONO_FIELD_RVA_FIELD]));
2902 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
2904 verify_assembly_table (VerifyContext *ctx)
2906 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLY];
2907 guint32 data [MONO_ASSEMBLY_SIZE], hash;
2910 if (table->rows > 1)
2911 ADD_ERROR (ctx, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table->rows));
2913 for (i = 0; i < table->rows; ++i) {
2914 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLY_SIZE);
2916 hash = data [MONO_ASSEMBLY_HASH_ALG];
2917 if (!(hash == 0 || hash == 0x8003 || hash == 0x8004))
2918 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i, hash));
2920 if (data [MONO_ASSEMBLY_FLAGS] & INVALID_ASSEMBLY_FLAGS_BITS)
2921 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2923 if (data [MONO_ASSEMBLY_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLY_PUBLIC_KEY], 1))
2924 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i, data [MONO_ASSEMBLY_FLAGS]));
2926 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLY_NAME]))
2927 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i, data [MONO_ASSEMBLY_NAME]));
2929 if (data [MONO_ASSEMBLY_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLY_CULTURE]))
2930 ADD_ERROR (ctx, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLY_CULTURE]));
2934 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
2936 verify_assemblyref_table (VerifyContext *ctx)
2938 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_ASSEMBLYREF];
2939 guint32 data [MONO_ASSEMBLYREF_SIZE];
2942 for (i = 0; i < table->rows; ++i) {
2943 mono_metadata_decode_row (table, i, data, MONO_ASSEMBLYREF_SIZE);
2945 if (data [MONO_ASSEMBLYREF_FLAGS] & INVALID_ASSEMBLYREF_FLAGS_BITS)
2946 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i, data [MONO_ASSEMBLYREF_FLAGS]));
2948 if (data [MONO_ASSEMBLYREF_PUBLIC_KEY] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_PUBLIC_KEY], 1))
2949 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i, data [MONO_ASSEMBLYREF_PUBLIC_KEY]));
2951 if (!is_valid_non_empty_string (ctx, data [MONO_ASSEMBLYREF_NAME]))
2952 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i, data [MONO_ASSEMBLYREF_NAME]));
2954 if (data [MONO_ASSEMBLYREF_CULTURE] && !is_valid_string (ctx, data [MONO_ASSEMBLYREF_CULTURE]))
2955 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i, data [MONO_ASSEMBLYREF_CULTURE]));
2957 if (data [MONO_ASSEMBLYREF_HASH_VALUE] && !is_valid_blob_object (ctx, data [MONO_ASSEMBLYREF_HASH_VALUE], 1))
2958 ADD_ERROR (ctx, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i, data [MONO_ASSEMBLYREF_HASH_VALUE]));
2962 #define INVALID_FILE_FLAGS_BITS ~(1)
2964 verify_file_table (VerifyContext *ctx)
2966 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FILE];
2967 guint32 data [MONO_FILE_SIZE];
2970 for (i = 0; i < table->rows; ++i) {
2971 mono_metadata_decode_row (table, i, data, MONO_FILE_SIZE);
2973 if (data [MONO_FILE_FLAGS] & INVALID_FILE_FLAGS_BITS)
2974 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Flags %08x", i, data [MONO_FILE_FLAGS]));
2976 if (!is_valid_non_empty_string (ctx, data [MONO_FILE_NAME]))
2977 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid Name %08x", i, data [MONO_FILE_NAME]));
2979 if (!data [MONO_FILE_HASH_VALUE] || !is_valid_blob_object (ctx, data [MONO_FILE_HASH_VALUE], 1))
2980 ADD_ERROR (ctx, g_strdup_printf ("File table row %d has invalid HashValue %08x", i, data [MONO_FILE_HASH_VALUE]));
2984 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
2986 verify_exportedtype_table (VerifyContext *ctx)
2988 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_EXPORTEDTYPE];
2989 guint32 data [MONO_EXP_TYPE_SIZE];
2992 for (i = 0; i < table->rows; ++i) {
2993 mono_metadata_decode_row (table, i, data, MONO_EXP_TYPE_SIZE);
2995 if (data [MONO_EXP_TYPE_FLAGS] & INVALID_EXPORTED_TYPE_FLAGS_BITS)
2996 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i, data [MONO_EXP_TYPE_FLAGS]));
2998 if (!is_valid_non_empty_string (ctx, data [MONO_EXP_TYPE_NAME]))
2999 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i, data [MONO_FILE_NAME]));
3001 if (data [MONO_EXP_TYPE_NAMESPACE] && !is_valid_string (ctx, data [MONO_EXP_TYPE_NAMESPACE]))
3002 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i, data [MONO_EXP_TYPE_NAMESPACE]));
3004 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3005 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i, data [MONO_EXP_TYPE_IMPLEMENTATION]));
3007 if (!get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]))
3008 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has null Implementation token", i));
3010 /*nested type can't have a namespace*/
3011 if (get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_EXP_TYPE_IMPLEMENTATION]) == MONO_TABLE_EXPORTEDTYPE && data [MONO_EXP_TYPE_NAMESPACE])
3012 ADD_ERROR (ctx, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i));
3016 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3018 verify_manifest_resource_table (VerifyContext *ctx)
3020 MonoCLIImageInfo *iinfo = ctx->image->image_info;
3021 MonoCLIHeader *ch = &iinfo->cli_cli_header;
3022 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3023 guint32 data [MONO_MANIFEST_SIZE], impl_table, token, resources_size;
3026 resources_size = ch->ch_resources.size;
3028 for (i = 0; i < table->rows; ++i) {
3029 mono_metadata_decode_row (table, i, data, MONO_MANIFEST_SIZE);
3031 if (data [MONO_MANIFEST_FLAGS] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS)
3032 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i, data [MONO_MANIFEST_FLAGS]));
3034 if (data [MONO_MANIFEST_FLAGS] != 1 && data [MONO_MANIFEST_FLAGS] != 2)
3035 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i, data [MONO_MANIFEST_FLAGS]));
3037 if (!is_valid_non_empty_string (ctx, data [MONO_MANIFEST_NAME]))
3038 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i, data [MONO_MANIFEST_NAME]));
3040 if (!is_valid_coded_index (ctx, IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]))
3041 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i, data [MONO_MANIFEST_IMPLEMENTATION]));
3043 impl_table = get_coded_index_table (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3044 token = get_coded_index_token (IMPLEMENTATION_DESC, data [MONO_MANIFEST_IMPLEMENTATION]);
3046 if (impl_table == MONO_TABLE_EXPORTEDTYPE)
3047 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])));
3049 if (impl_table == MONO_TABLE_FILE && token && data [MONO_MANIFEST_OFFSET])
3050 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i));
3052 if (!token && data [MONO_MANIFEST_OFFSET] >= resources_size)
3053 ADD_ERROR (ctx, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i, data [MONO_MANIFEST_OFFSET]));
3058 verify_nested_class_table (VerifyContext *ctx)
3060 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_NESTEDCLASS];
3061 guint32 data [MONO_NESTED_CLASS_SIZE];
3064 for (i = 0; i < table->rows; ++i) {
3065 mono_metadata_decode_row (table, i, data, MONO_NESTED_CLASS_SIZE);
3067 if (!data [MONO_NESTED_CLASS_NESTED] || data [MONO_NESTED_CLASS_NESTED] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3068 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i, data [MONO_NESTED_CLASS_NESTED]));
3069 if (!data [MONO_NESTED_CLASS_ENCLOSING] || data [MONO_NESTED_CLASS_ENCLOSING] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
3070 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3071 if (data [MONO_NESTED_CLASS_ENCLOSING] == data [MONO_NESTED_CLASS_NESTED])
3072 ADD_ERROR (ctx, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i, data [MONO_NESTED_CLASS_ENCLOSING]));
3076 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3078 verify_generic_param_table (VerifyContext *ctx)
3080 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAM];
3081 guint32 data [MONO_GENERICPARAM_SIZE], token, last_token = 0;
3082 int i, param_number = 0;
3084 for (i = 0; i < table->rows; ++i) {
3085 mono_metadata_decode_row (table, i, data, MONO_GENERICPARAM_SIZE);
3087 if (data [MONO_GENERICPARAM_FLAGS] & INVALID_GENERIC_PARAM_FLAGS_BITS)
3088 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i, data [MONO_GENERICPARAM_FLAGS]));
3090 if ((data [MONO_GENERICPARAM_FLAGS] & MONO_GEN_PARAM_VARIANCE_MASK) == 0x3)
3091 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i));
3093 if (!is_valid_non_empty_string (ctx, data [MONO_GENERICPARAM_NAME]))
3094 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i, data [MONO_GENERICPARAM_NAME]));
3096 token = data [MONO_GENERICPARAM_OWNER];
3098 if (!is_valid_coded_index (ctx, TYPE_OR_METHODDEF_DESC, token))
3099 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i, token));
3101 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC, token))
3102 ADD_ERROR (ctx, g_strdup_printf ("GenericParam table row %d has null Owner token", i));
3104 if (token != last_token) {
3109 if (data [MONO_GENERICPARAM_NUMBER] != param_number)
3110 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));
3117 verify_method_spec_table (VerifyContext *ctx)
3119 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3120 guint32 data [MONO_METHODSPEC_SIZE];
3123 for (i = 0; i < table->rows; ++i) {
3124 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3126 if (!is_valid_coded_index (ctx, METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3127 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i, data [MONO_METHODSPEC_METHOD]));
3129 if (!get_coded_index_token (METHODDEF_OR_REF_DESC, data [MONO_METHODSPEC_METHOD]))
3130 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has null Method token", i));
3132 if (data [MONO_METHODSPEC_SIGNATURE] && !is_valid_blob_object (ctx, data [MONO_METHODSPEC_SIGNATURE], 1))
3133 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3138 verify_method_spec_table_full (VerifyContext *ctx)
3140 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHODSPEC];
3141 guint32 data [MONO_METHODSPEC_SIZE];
3144 for (i = 0; i < table->rows; ++i) {
3145 mono_metadata_decode_row (table, i, data, MONO_METHODSPEC_SIZE);
3147 if (!is_valid_methodspec_blog (ctx, data [MONO_METHODSPEC_SIGNATURE]))
3148 ADD_ERROR (ctx, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i, data [MONO_METHODSPEC_SIGNATURE]));
3153 verify_generic_param_constraint_table (VerifyContext *ctx)
3155 MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
3156 guint32 data [MONO_GENPARCONSTRAINT_SIZE];
3159 for (i = 0; i < table->rows; ++i) {
3160 mono_metadata_decode_row (table, i, data, MONO_GENPARCONSTRAINT_SIZE);
3162 if (!data [MONO_GENPARCONSTRAINT_GENERICPAR] || data [MONO_GENPARCONSTRAINT_GENERICPAR] > ctx->image->tables [MONO_TABLE_GENERICPARAM].rows)
3163 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i, data [MONO_TABLE_GENERICPARAM]));
3165 if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3166 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i, data [MONO_GENPARCONSTRAINT_CONSTRAINT]));
3168 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_GENPARCONSTRAINT_CONSTRAINT]))
3169 ADD_ERROR (ctx, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i));
3174 verify_tables_data (VerifyContext *ctx)
3176 OffsetAndSize tables_area = get_metadata_stream (ctx, &ctx->image->heap_tables);
3177 guint32 size = 0, tables_offset;
3180 for (i = 0; i < 0x2D; ++i) {
3181 MonoTableInfo *table = &ctx->image->tables [i];
3183 tmp_size = size + (guint32)table->row_size * (guint32)table->rows;
3184 if (tmp_size < size) {
3192 ADD_ERROR (ctx, g_strdup_printf ("table space is either empty or overflowed"));
3194 tables_offset = ctx->image->tables_base - ctx->data;
3195 if (!bounds_check_offset (&tables_area, tables_offset, size))
3196 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)));
3198 verify_module_table (ctx);
3200 verify_typeref_table (ctx);
3202 verify_typedef_table (ctx);
3204 verify_field_table (ctx);
3206 verify_method_table (ctx);
3208 verify_param_table (ctx);
3210 verify_interfaceimpl_table (ctx);
3212 verify_memberref_table (ctx);
3214 verify_constant_table (ctx);
3216 verify_cattr_table (ctx);
3218 verify_field_marshal_table (ctx);
3220 verify_decl_security_table (ctx);
3222 verify_class_layout_table (ctx);
3224 verify_field_layout_table (ctx);
3226 verify_standalonesig_table (ctx);
3228 verify_eventmap_table (ctx);
3230 verify_event_table (ctx);
3232 verify_propertymap_table (ctx);
3234 verify_property_table (ctx);
3236 verify_methodimpl_table (ctx);
3238 verify_moduleref_table (ctx);
3240 verify_typespec_table (ctx);
3242 verify_implmap_table (ctx);
3244 verify_fieldrva_table (ctx);
3246 verify_assembly_table (ctx);
3248 verify_assemblyref_table (ctx);
3250 verify_file_table (ctx);
3252 verify_exportedtype_table (ctx);
3254 verify_manifest_resource_table (ctx);
3256 verify_nested_class_table (ctx);
3258 verify_generic_param_table (ctx);
3260 verify_method_spec_table (ctx);
3262 verify_generic_param_constraint_table (ctx);
3266 init_verify_context (VerifyContext *ctx, MonoImage *image, GSList **error_list)
3268 memset (ctx, 0, sizeof (VerifyContext));
3270 ctx->report_error = error_list != NULL;
3272 ctx->size = image->raw_data_len;
3273 ctx->data = image->raw_data;
3277 cleanup_context (VerifyContext *ctx, GSList **error_list)
3279 g_free (ctx->sections);
3281 *error_list = ctx->errors;
3283 mono_free_verify_list (ctx->errors);
3288 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3292 if (!mono_verifier_is_enabled_for_image (image))
3295 init_verify_context (&ctx, image, error_list);
3296 ctx.stage = STAGE_PE;
3298 verify_msdos_header (&ctx);
3300 verify_pe_header (&ctx);
3302 verify_pe_optional_header (&ctx);
3304 load_section_table (&ctx);
3306 load_data_directories (&ctx);
3308 verify_import_table (&ctx);
3310 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3311 verify_resources_table (&ctx);
3314 return cleanup_context (&ctx, error_list);
3318 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3322 if (!mono_verifier_is_enabled_for_image (image))
3325 init_verify_context (&ctx, image, error_list);
3326 ctx.stage = STAGE_CLI;
3328 verify_cli_header (&ctx);
3330 verify_metadata_header (&ctx);
3332 verify_tables_schema (&ctx);
3335 return cleanup_context (&ctx, error_list);
3340 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3341 * Other verification checks are meant to be done lazily by the runtime. Those include:
3342 * blob items (signatures, method headers, custom attributes, etc)
3343 * type semantics related
3345 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3347 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3348 * operation still need more checking.
3351 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3355 if (!mono_verifier_is_enabled_for_image (image))
3358 init_verify_context (&ctx, image, error_list);
3359 ctx.stage = STAGE_TABLES;
3361 verify_tables_data (&ctx);
3363 return cleanup_context (&ctx, error_list);
3368 * Verifies all other constraints.
3371 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3375 if (!mono_verifier_is_enabled_for_image (image))
3378 init_verify_context (&ctx, image, error_list);
3379 ctx.stage = STAGE_TABLES;
3381 verify_typedef_table_full (&ctx);
3383 verify_field_table_full (&ctx);
3385 verify_method_table_full (&ctx);
3387 verify_memberref_table_full (&ctx);
3389 verify_cattr_table_full (&ctx);
3391 verify_field_marshal_table_full (&ctx);
3393 verify_decl_security_table_full (&ctx);
3395 verify_standalonesig_table_full (&ctx);
3397 verify_event_table_full (&ctx);
3399 verify_typespec_table_full (&ctx);
3401 verify_method_spec_table_full (&ctx);
3404 return cleanup_context (&ctx, error_list);
3408 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3412 if (!mono_verifier_is_enabled_for_image (image))
3415 init_verify_context (&ctx, image, error_list);
3416 ctx.stage = STAGE_TABLES;
3418 is_valid_field_signature (&ctx, offset);
3419 return cleanup_context (&ctx, error_list);
3423 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3427 if (!mono_verifier_is_enabled_for_image (image))
3430 init_verify_context (&ctx, image, error_list);
3431 ctx.stage = STAGE_TABLES;
3433 is_valid_method_header (&ctx, offset);
3434 return cleanup_context (&ctx, error_list);
3438 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3442 if (!mono_verifier_is_enabled_for_image (image))
3445 init_verify_context (&ctx, image, error_list);
3446 ctx.stage = STAGE_TABLES;
3448 is_valid_method_signature (&ctx, offset);
3449 return cleanup_context (&ctx, error_list);
3453 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3457 if (!mono_verifier_is_enabled_for_image (image))
3460 init_verify_context (&ctx, image, error_list);
3461 ctx.stage = STAGE_TABLES;
3463 is_valid_method_or_field_signature (&ctx, offset);
3464 return cleanup_context (&ctx, error_list);
3468 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3472 if (!mono_verifier_is_enabled_for_image (image))
3475 init_verify_context (&ctx, image, error_list);
3476 ctx.stage = STAGE_TABLES;
3478 is_valid_standalonesig_blob (&ctx, offset);
3479 return cleanup_context (&ctx, error_list);
3483 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3487 if (!mono_verifier_is_enabled_for_image (image))
3490 init_verify_context (&ctx, image, error_list);
3491 ctx.stage = STAGE_TABLES;
3493 is_valid_typespec_blob (&ctx, offset);
3494 return cleanup_context (&ctx, error_list);
3498 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3502 if (!mono_verifier_is_enabled_for_image (image))
3505 init_verify_context (&ctx, image, error_list);
3506 ctx.stage = STAGE_TABLES;
3508 is_valid_methodspec_blog (&ctx, offset);
3509 return cleanup_context (&ctx, error_list);
3514 mono_verifier_verify_table_data (MonoImage *image, GSList **error_list)
3520 mono_verifier_verify_cli_data (MonoImage *image, GSList **error_list)
3526 mono_verifier_verify_pe_data (MonoImage *image, GSList **error_list)
3532 mono_verifier_verify_full_table_data (MonoImage *image, GSList **error_list)
3538 mono_verifier_verify_field_signature (MonoImage *image, guint32 offset, GSList **error_list)
3544 mono_verifier_verify_method_header (MonoImage *image, guint32 offset, GSList **error_list)
3550 mono_verifier_verify_method_signature (MonoImage *image, guint32 offset, GSList **error_list)
3556 mono_verifier_verify_memberref_signature (MonoImage *image, guint32 offset, GSList **error_list)
3562 mono_verifier_verify_standalone_signature (MonoImage *image, guint32 offset, GSList **error_list)
3568 mono_verifier_verify_typespec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3574 mono_verifier_verify_methodspec_signature (MonoImage *image, guint32 offset, GSList **error_list)
3579 #endif /* DISABLE_VERIFIER */