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
;
225 gboolean report_warning
;
228 DataDirectory data_directories
[16];
229 guint32 section_count
;
230 SectionHeader
*sections
;
232 OffsetAndSize metadata_streams
[5]; //offset from begin of the image
235 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
237 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
238 vinfo->info.status = __status; \
239 vinfo->info.message = ( __msg); \
240 vinfo->exception_type = (__exception); \
241 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
244 #define ADD_WARNING(__ctx, __msg) \
246 if ((__ctx)->report_warning) { \
247 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
248 (__ctx)->valid = 0; \
253 #define ADD_ERROR_NO_RETURN(__ctx, __msg) \
255 if ((__ctx)->report_error) \
256 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
257 (__ctx)->valid = 0; \
260 #define ADD_ERROR(__ctx, __msg) \
262 if ((__ctx)->report_error) \
263 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
264 (__ctx)->valid = 0; \
268 #define FAIL(__ctx, __msg) \
270 if ((__ctx)->report_error) \
271 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
272 (__ctx)->valid = 0; \
276 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
278 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
280 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
281 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
283 #if SIZEOF_VOID_P == 4
284 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
286 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
289 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
290 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
293 dword_align (const char *ptr
)
295 #if SIZEOF_VOID_P == 8
296 return (const char *) (((guint64
) (ptr
+ 3)) & ~3);
298 return (const char *) (((guint32
) (ptr
+ 3)) & ~3);
303 pe_signature_offset (VerifyContext
*ctx
)
305 return read32 (ctx
->data
+ 0x3c);
309 pe_header_offset (VerifyContext
*ctx
)
311 return read32 (ctx
->data
+ 0x3c) + 4;
315 bounds_check_virtual_address (VerifyContext
*ctx
, guint32 rva
, guint32 size
)
319 if (rva
+ size
< rva
) //overflow
322 if (ctx
->stage
> STAGE_PE
) {
323 MonoCLIImageInfo
*iinfo
= ctx
->image
->image_info
;
324 const int top
= iinfo
->cli_section_count
;
325 MonoSectionTable
*tables
= iinfo
->cli_section_tables
;
328 for (i
= 0; i
< top
; i
++) {
329 guint32 base
= tables
->st_virtual_address
;
330 guint32 end
= base
+ tables
->st_raw_data_size
;
332 if (rva
>= base
&& rva
+ size
<= end
)
335 /*if ((addr >= tables->st_virtual_address) &&
336 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
338 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
348 for (i
= 0; i
< ctx
->section_count
; ++i
) {
349 guint32 base
= ctx
->sections
[i
].baseRVA
;
350 guint32 end
= ctx
->sections
[i
].baseRVA
+ ctx
->sections
[i
].size
;
351 if (rva
>= base
&& rva
+ size
<= end
)
358 bounds_check_datadir (DataDirectory
*dir
, guint32 offset
, guint32 size
)
360 if (dir
->translated_offset
> offset
)
362 if (dir
->size
< size
)
364 return offset
+ size
<= dir
->translated_offset
+ dir
->size
;
368 bounds_check_offset (OffsetAndSize
*off
, guint32 offset
, guint32 size
)
370 if (off
->offset
> offset
)
373 if (off
->size
< size
)
376 return offset
+ size
<= off
->offset
+ off
->size
;
380 translate_rva (VerifyContext
*ctx
, guint32 rva
)
384 if (ctx
->stage
> STAGE_PE
)
385 return mono_cli_rva_image_map (ctx
->image
, rva
);
390 for (i
= 0; i
< ctx
->section_count
; ++i
) {
391 guint32 base
= ctx
->sections
[i
].baseRVA
;
392 guint32 end
= ctx
->sections
[i
].baseRVA
+ ctx
->sections
[i
].size
;
393 if (rva
>= base
&& rva
<= end
) {
394 guint32 res
= (rva
- base
) + ctx
->sections
[i
].baseOffset
;
396 return res
>= ctx
->size
? INVALID_OFFSET
: res
;
400 return INVALID_OFFSET
;
404 verify_msdos_header (VerifyContext
*ctx
)
408 ADD_ERROR (ctx
, g_strdup ("Not enough space for the MS-DOS header"));
409 if (ctx
->data
[0] != 0x4d || ctx
->data
[1] != 0x5a)
410 ADD_ERROR (ctx
, g_strdup ("Invalid MS-DOS watermark"));
411 lfanew
= pe_signature_offset (ctx
);
412 if (lfanew
> ctx
->size
- 4)
413 ADD_ERROR (ctx
, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
417 verify_pe_header (VerifyContext
*ctx
)
419 guint32 offset
= pe_signature_offset (ctx
);
420 const char *pe_header
= ctx
->data
+ offset
;
421 if (pe_header
[0] != 'P' || pe_header
[1] != 'E' ||pe_header
[2] != 0 ||pe_header
[3] != 0)
422 ADD_ERROR (ctx
, g_strdup ("Invalid PE header watermark"));
426 if (offset
> ctx
->size
- 20)
427 ADD_ERROR (ctx
, g_strdup ("File with truncated pe header"));
428 if (read16 (pe_header
) != 0x14c)
429 ADD_ERROR (ctx
, g_strdup ("Invalid PE header Machine value"));
433 verify_pe_optional_header (VerifyContext
*ctx
)
435 guint32 offset
= pe_header_offset (ctx
);
436 guint32 header_size
, file_alignment
;
437 const char *pe_header
= ctx
->data
+ offset
;
438 const char *pe_optional_header
= pe_header
+ 20;
440 header_size
= read16 (pe_header
+ 16);
443 if (header_size
< 2) /*must be at least 2 or we won't be able to read magic*/
444 ADD_ERROR (ctx
, g_strdup ("Invalid PE optional header size"));
446 if (offset
> ctx
->size
- header_size
|| header_size
> ctx
->size
)
447 ADD_ERROR (ctx
, g_strdup ("Invalid PE optional header size"));
449 if (read16 (pe_optional_header
) == 0x10b) {
450 if (header_size
!= 224)
451 ADD_ERROR (ctx
, g_strdup_printf ("Invalid optional header size %d", header_size
));
453 /* LAMESPEC MS plays around this value and ignore it during validation
454 if (read32 (pe_optional_header + 28) != 0x400000)
455 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
456 if (read32 (pe_optional_header
+ 32) != 0x2000)
457 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header
+ 32)));
458 file_alignment
= read32 (pe_optional_header
+ 36);
459 if (file_alignment
!= 0x200 && file_alignment
!= 0x1000)
460 ADD_ERROR (ctx
, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment
));
461 /* All the junk in the middle is irrelevant, specially for mono. */
462 if (read32 (pe_optional_header
+ 92) > 0x10)
463 ADD_ERROR (ctx
, g_strdup_printf ("Too many data directories %x", read32 (pe_optional_header
+ 92)));
465 if (read16 (pe_optional_header
) == 0x20B)
466 ADD_ERROR (ctx
, g_strdup ("Metadata verifier doesn't handle PE32+"));
468 ADD_ERROR (ctx
, g_strdup_printf ("Invalid optional header magic %d", read16 (pe_optional_header
)));
473 load_section_table (VerifyContext
*ctx
)
476 SectionHeader
*sections
;
477 guint32 offset
= pe_header_offset (ctx
);
478 const char *ptr
= ctx
->data
+ offset
;
479 guint16 num_sections
= ctx
->section_count
= read16 (ptr
+ 2);
481 offset
+= 244;/*FIXME, this constant is different under PE32+*/
484 if (num_sections
* 40 > ctx
->size
- offset
)
485 ADD_ERROR (ctx
, g_strdup ("Invalid PE optional header size"));
487 sections
= ctx
->sections
= g_new0 (SectionHeader
, num_sections
);
488 for (i
= 0; i
< num_sections
; ++i
) {
489 sections
[i
].size
= read32 (ptr
+ 8);
490 sections
[i
].baseRVA
= read32 (ptr
+ 12);
491 sections
[i
].baseOffset
= read32 (ptr
+ 20);
492 sections
[i
].rellocationsRVA
= read32 (ptr
+ 24);
493 sections
[i
].numberOfRelocations
= read16 (ptr
+ 32);
497 ptr
= ctx
->data
+ offset
; /*reset it to the beggining*/
498 for (i
= 0; i
< num_sections
; ++i
) {
499 guint32 raw_size
, flags
;
500 if (sections
[i
].baseOffset
== 0)
501 ADD_ERROR (ctx
, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
502 if (sections
[i
].baseOffset
>= ctx
->size
)
503 ADD_ERROR (ctx
, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections
[i
].baseOffset
));
504 if (sections
[i
].size
> ctx
->size
- sections
[i
].baseOffset
)
505 ADD_ERROR (ctx
, g_strdup ("Invalid VirtualSize points beyond EOF"));
507 raw_size
= read32 (ptr
+ 16);
508 if (raw_size
< sections
[i
].size
)
509 ADD_ERROR (ctx
, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
511 if (raw_size
> ctx
->size
- sections
[i
].baseOffset
)
512 ADD_ERROR (ctx
, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size
));
514 if (sections
[i
].rellocationsRVA
|| sections
[i
].numberOfRelocations
)
515 ADD_ERROR (ctx
, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
517 flags
= read32 (ptr
+ 36);
518 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
519 if (flags
== 0 || (flags
& ~0xFE0000E0) != 0)
520 ADD_ERROR (ctx
, g_strdup_printf ("Invalid section flags %x", flags
));
527 is_valid_data_directory (int i
)
529 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
530 return i
== 1 || i
== 2 || i
== 5 || i
== 12 || i
== 14 || i
== 4 || i
== 6;
534 load_data_directories (VerifyContext
*ctx
)
536 guint32 offset
= pe_header_offset (ctx
) + 116; /*FIXME, this constant is different under PE32+*/
537 const char *ptr
= ctx
->data
+ offset
;
540 for (i
= 0; i
< 16; ++i
) {
541 guint32 rva
= read32 (ptr
);
542 guint32 size
= read32 (ptr
+ 4);
544 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
545 if (i
== CERTIFICATE_TABLE_IDX
) {
549 if ((rva
!= 0 || size
!= 0) && !is_valid_data_directory (i
))
550 ADD_ERROR (ctx
, g_strdup_printf ("Invalid data directory %d", i
));
552 if (rva
!= 0 && !bounds_check_virtual_address (ctx
, rva
, size
))
553 ADD_ERROR (ctx
, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i
, rva
, size
));
555 ctx
->data_directories
[i
].rva
= rva
;
556 ctx
->data_directories
[i
].size
= size
;
557 ctx
->data_directories
[i
].translated_offset
= translate_rva (ctx
, rva
);
563 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
565 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
568 verify_hint_name_table (VerifyContext
*ctx
, guint32 import_rva
, const char *table_name
)
571 guint32 hint_table_rva
;
573 import_rva
= translate_rva (ctx
, import_rva
);
574 g_assert (import_rva
!= INVALID_OFFSET
);
576 hint_table_rva
= read32 (ctx
->data
+ import_rva
);
577 if (!bounds_check_virtual_address (ctx
, hint_table_rva
, SIZE_OF_CORMAIN
+ 2))
578 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva
, table_name
));
580 hint_table_rva
= translate_rva (ctx
, hint_table_rva
);
581 g_assert (hint_table_rva
!= INVALID_OFFSET
);
582 ptr
= ctx
->data
+ hint_table_rva
+ 2;
584 if (memcmp ("_CorExeMain", ptr
, SIZE_OF_CORMAIN
) && memcmp ("_CorDllMain", ptr
, SIZE_OF_CORMAIN
)) {
585 char name
[SIZE_OF_CORMAIN
];
586 memcpy (name
, ptr
, SIZE_OF_CORMAIN
);
587 name
[SIZE_OF_CORMAIN
- 1] = 0;
588 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Hint / Name: '%s'", name
));
593 verify_import_table (VerifyContext
*ctx
)
595 DataDirectory it
= ctx
->data_directories
[IMPORT_TABLE_IDX
];
596 guint32 offset
= it
.translated_offset
;
597 const char *ptr
= ctx
->data
+ offset
;
598 guint32 name_rva
, ilt_rva
, iat_rva
;
600 g_assert (offset
!= INVALID_OFFSET
);
603 ADD_ERROR (ctx
, g_strdup_printf ("Import table size %d is smaller than 40", it
.size
));
605 ilt_rva
= read32 (ptr
);
606 if (ilt_rva
&& !bounds_check_virtual_address (ctx
, ilt_rva
, 8))
607 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva
));
609 name_rva
= read32 (ptr
+ 12);
610 if (name_rva
&& !bounds_check_virtual_address (ctx
, name_rva
, SIZE_OF_MSCOREE
))
611 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva
));
613 iat_rva
= read32 (ptr
+ 16);
615 if (!bounds_check_virtual_address (ctx
, iat_rva
, 8))
616 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva
));
618 if (iat_rva
!= ctx
->data_directories
[IAT_IDX
].rva
)
619 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
));
623 name_rva
= translate_rva (ctx
, name_rva
);
624 g_assert (name_rva
!= INVALID_OFFSET
);
625 ptr
= ctx
->data
+ name_rva
;
627 if (memcmp ("mscoree.dll", ptr
, SIZE_OF_MSCOREE
)) {
628 char name
[SIZE_OF_MSCOREE
];
629 memcpy (name
, ptr
, SIZE_OF_MSCOREE
);
630 name
[SIZE_OF_MSCOREE
- 1] = 0;
631 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Table Name: '%s'", name
));
636 verify_hint_name_table (ctx
, ilt_rva
, "Import Lookup Table");
641 verify_hint_name_table (ctx
, iat_rva
, "Import Address Table");
645 verify_resources_table (VerifyContext
*ctx
)
647 DataDirectory it
= ctx
->data_directories
[RESOURCE_TABLE_IDX
];
649 guint16 named_entries
, id_entries
;
650 const char *ptr
, *root
, *end
;
656 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
));
658 offset
= it
.translated_offset
;
659 root
= ptr
= ctx
->data
+ offset
;
660 end
= root
+ it
.size
;
662 g_assert (offset
!= INVALID_OFFSET
);
664 named_entries
= read16 (ptr
+ 12);
665 id_entries
= read16 (ptr
+ 14);
667 if ((named_entries
+ id_entries
) * 8 + 16 > it
.size
)
668 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
));
670 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
671 if (named_entries || id_entries)
672 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
676 /*----------nothing from here on can use data_directory---*/
679 get_data_dir (VerifyContext
*ctx
, int idx
)
681 MonoCLIImageInfo
*iinfo
= ctx
->image
->image_info
;
682 MonoPEDirEntry
*entry
= &iinfo
->cli_header
.datadir
.pe_export_table
;
686 res
.rva
= entry
->rva
;
687 res
.size
= entry
->size
;
688 res
.translated_offset
= translate_rva (ctx
, res
.rva
);
693 verify_cli_header (VerifyContext
*ctx
)
695 DataDirectory it
= get_data_dir (ctx
, CLI_HEADER_IDX
);
701 ADD_ERROR (ctx
, g_strdup_printf ("CLI header missing"));
704 ADD_ERROR (ctx
, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it
.size
));
706 offset
= it
.translated_offset
;
707 ptr
= ctx
->data
+ offset
;
709 g_assert (offset
!= INVALID_OFFSET
);
711 if (read16 (ptr
) != 72)
712 ADD_ERROR (ctx
, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr
)));
714 if (!bounds_check_virtual_address (ctx
, read32 (ptr
+ 8), read32 (ptr
+ 12)))
715 ADD_ERROR (ctx
, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr
+ 8), read32 (ptr
+ 12)));
718 if (!read32 (ptr
+ 8) || !read32 (ptr
+ 12))
719 ADD_ERROR (ctx
, g_strdup_printf ("Missing medatata section in the CLI header"));
721 if ((read32 (ptr
+ 16) & ~0x0001000B) != 0)
722 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CLI header flags"));
725 for (i
= 0; i
< 6; ++i
) {
726 guint32 rva
= read32 (ptr
);
727 guint32 size
= read32 (ptr
+ 4);
729 if (rva
!= 0 && !bounds_check_virtual_address (ctx
, rva
, size
))
730 ADD_ERROR (ctx
, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i
, rva
, size
));
735 ADD_ERROR (ctx
, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i
));
740 pad4 (guint32 offset
)
742 if (offset
& 0x3) //pad to the next 4 byte boundary
743 offset
= (offset
& ~0x3) + 4;
748 verify_metadata_header (VerifyContext
*ctx
)
751 DataDirectory it
= get_data_dir (ctx
, CLI_HEADER_IDX
);
752 guint32 offset
, section_count
;
755 offset
= it
.translated_offset
;
756 ptr
= ctx
->data
+ offset
;
757 g_assert (offset
!= INVALID_OFFSET
);
759 //build a directory entry for the metadata root
761 it
.rva
= read32 (ptr
);
763 it
.size
= read32 (ptr
);
764 it
.translated_offset
= offset
= translate_rva (ctx
, it
.rva
);
766 ptr
= ctx
->data
+ offset
;
767 g_assert (offset
!= INVALID_OFFSET
);
770 ADD_ERROR (ctx
, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it
.size
));
772 if (read32 (ptr
) != 0x424A5342)
773 ADD_ERROR (ctx
, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr
)));
775 offset
= pad4 (offset
+ 16 + read32 (ptr
+ 12));
777 if (!bounds_check_datadir (&it
, offset
, 4))
778 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
));
780 ptr
= ctx
->data
+ offset
; //move to streams header
782 section_count
= read16 (ptr
+ 2);
783 if (section_count
< 2)
784 ADD_ERROR (ctx
, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
789 for (i
= 0; i
< section_count
; ++i
) {
790 guint32 stream_off
, stream_size
;
791 int string_size
, stream_idx
;
793 if (!bounds_check_datadir (&it
, offset
, 8))
794 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
));
796 stream_off
= it
.translated_offset
+ read32 (ptr
);
797 stream_size
= read32 (ptr
+ 4);
799 if (!bounds_check_datadir (&it
, stream_off
, stream_size
))
800 ADD_ERROR (ctx
, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off
, stream_size
));
805 for (string_size
= 0; string_size
< 32; ++string_size
) {
806 if (!bounds_check_datadir (&it
, offset
++, 1))
807 ADD_ERROR (ctx
, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i
));
808 if (!ptr
[string_size
])
812 if (ptr
[string_size
])
813 ADD_ERROR (ctx
, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i
));
815 if (!strncmp ("#Strings", ptr
, 9))
816 stream_idx
= STRINGS_STREAM
;
817 else if (!strncmp ("#US", ptr
, 4))
818 stream_idx
= USER_STRINGS_STREAM
;
819 else if (!strncmp ("#Blob", ptr
, 6))
820 stream_idx
= BLOB_STREAM
;
821 else if (!strncmp ("#GUID", ptr
, 6))
822 stream_idx
= GUID_STREAM
;
823 else if (!strncmp ("#~", ptr
, 3))
824 stream_idx
= TILDE_STREAM
;
826 ADD_WARNING (ctx
, g_strdup_printf ("Metadata stream header %d invalid name %s", i
, ptr
));
827 offset
= pad4 (offset
);
828 ptr
= ctx
->data
+ offset
;
832 if (ctx
->metadata_streams
[stream_idx
].offset
!= 0)
833 ADD_ERROR (ctx
, g_strdup_printf ("Duplicated metadata stream header %s", ptr
));
835 ctx
->metadata_streams
[stream_idx
].offset
= stream_off
;
836 ctx
->metadata_streams
[stream_idx
].size
= stream_size
;
838 offset
= pad4 (offset
);
839 ptr
= ctx
->data
+ offset
;
842 if (!ctx
->metadata_streams
[TILDE_STREAM
].size
)
843 ADD_ERROR (ctx
, g_strdup_printf ("Metadata #~ stream missing"));
844 if (!ctx
->metadata_streams
[GUID_STREAM
].size
)
845 ADD_ERROR (ctx
, g_strdup_printf ("Metadata guid stream missing"));
849 verify_tables_schema (VerifyContext
*ctx
)
851 OffsetAndSize tables_area
= ctx
->metadata_streams
[TILDE_STREAM
];
852 unsigned offset
= tables_area
.offset
;
853 const char *ptr
= ctx
->data
+ offset
;
854 guint64 valid_tables
;
858 if (tables_area
.size
< 24)
859 ADD_ERROR (ctx
, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area
.size
));
861 if (ptr
[4] != 2 && ptr
[4] != 1)
862 ADD_ERROR (ctx
, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr
[4]));
864 ADD_ERROR (ctx
, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr
[5]));
866 if ((ptr
[6] & ~0x7) != 0)
867 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]));
869 valid_tables
= read64 (ptr
+ 8);
871 for (i
= 0; i
< 64; ++i
) {
872 if (!(valid_tables
& ((guint64
)1 << i
)))
875 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
876 Unused: 0x1E 0x1F 0x2D-0x3F
877 We don't care about the MS extensions.*/
878 if (i
== 0x3 || i
== 0x5 || i
== 0x7 || i
== 0x13 || i
== 0x16)
879 ADD_ERROR (ctx
, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i
));
880 if (i
== 0x1E || i
== 0x1F || i
>= 0x2D)
881 ADD_ERROR (ctx
, g_strdup_printf ("Invalid table %x", i
));
885 if (tables_area
.size
< 24 + count
* 4)
886 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));
889 for (i
= 0; i
< 64; ++i
) {
890 if (valid_tables
& ((guint64
)1 << i
)) {
891 guint32 row_count
= read32 (ptr
);
892 if (row_count
> (1 << 24) - 1)
893 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i
, row_count
));
899 /*----------nothing from here on can use data_directory or metadata_streams ---*/
902 get_col_offset (VerifyContext
*ctx
, int table
, int column
)
904 guint32 bitfield
= ctx
->image
->tables
[table
].size_bitfield
;
908 offset
+= mono_metadata_table_size (bitfield
, column
);
914 get_col_size (VerifyContext
*ctx
, int table
, int column
)
916 return mono_metadata_table_size (ctx
->image
->tables
[table
].size_bitfield
, column
);
920 get_metadata_stream (VerifyContext
*ctx
, MonoStreamHeader
*header
)
923 res
.offset
= header
->data
- ctx
->data
;
924 res
.size
= header
->size
;
930 is_valid_string_full (VerifyContext
*ctx
, guint32 offset
, gboolean allow_empty
)
932 OffsetAndSize strings
= get_metadata_stream (ctx
, &ctx
->image
->heap_strings
);
934 const char *data
= ctx
->data
+ strings
.offset
;
936 if (offset
>= strings
.size
)
938 if (data
+ offset
< data
) //FIXME, use a generalized and smart unsigned add with overflow check and fix the whole thing
941 if (!mono_utf8_validate_and_len_with_bounds (data
+ offset
, strings
.size
- offset
, &length
, NULL
))
943 return allow_empty
|| length
> 0;
947 is_valid_string (VerifyContext
*ctx
, guint32 offset
)
949 return is_valid_string_full (ctx
, offset
, TRUE
);
953 is_valid_non_empty_string (VerifyContext
*ctx
, guint32 offset
)
955 return is_valid_string_full (ctx
, offset
, FALSE
);
959 is_valid_guid (VerifyContext
*ctx
, guint32 offset
)
961 OffsetAndSize guids
= get_metadata_stream (ctx
, &ctx
->image
->heap_guid
);
962 return guids
.size
>= 8 && guids
.size
- 8 >= offset
;
966 get_coded_index_token (int token_kind
, guint32 coded_token
)
968 guint32 bits
= coded_index_desc
[token_kind
];
969 return coded_token
>> bits
;
973 get_coded_index_table (int kind
, guint32 coded_token
)
975 guint32 idx
, bits
= coded_index_desc
[kind
];
977 idx
= coded_token
& ((1 << bits
) - 1);
978 return coded_index_desc
[kind
+ idx
];
982 make_coded_token (int kind
, guint32 table
, guint32 table_idx
)
984 guint32 bits
= coded_index_desc
[kind
++];
985 guint32 tables
= coded_index_desc
[kind
++];
987 for (i
= 0; i
< tables
; ++i
) {
988 if (coded_index_desc
[kind
++] == table
)
989 return ((table_idx
+ 1) << bits
) | i
;
991 g_assert_not_reached ();
996 is_valid_coded_index (VerifyContext
*ctx
, int token_kind
, guint32 coded_token
)
998 guint32 bits
= coded_index_desc
[token_kind
++];
999 guint32 table_count
= coded_index_desc
[token_kind
++];
1000 guint32 table
= coded_token
& ((1 << bits
) - 1);
1001 guint32 token
= coded_token
>> bits
;
1003 if (table
>= table_count
)
1006 /*token_kind points to the first table idx*/
1007 table
= coded_index_desc
[token_kind
+ table
];
1009 if (table
== INVALID_TABLE
)
1011 return token
<= ctx
->image
->tables
[table
].rows
;
1018 MonoTableInfo
*table
;
1022 token_locator (const void *a
, const void *b
)
1024 RowLocator
*loc
= (RowLocator
*)a
;
1025 unsigned const char *row
= (unsigned const char *)b
;
1026 guint32 token
= loc
->col_size
== 2 ? read16 (row
+ loc
->col_offset
) : read32 (row
+ loc
->col_offset
);
1028 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token
, ((const char*)row
- loc
->table
->base
) / loc
->table
->row_size
) );
1029 return (int)loc
->token
- (int)token
;
1033 search_sorted_table (VerifyContext
*ctx
, int table
, int column
, guint32 coded_token
)
1035 MonoTableInfo
*tinfo
= &ctx
->image
->tables
[table
];
1037 const char *res
, *base
;
1038 locator
.token
= coded_token
;
1039 locator
.col_offset
= get_col_offset (ctx
, table
, column
);
1040 locator
.col_size
= get_col_size (ctx
, table
, column
);
1041 locator
.table
= tinfo
;
1045 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
) );
1046 res
= bsearch (&locator
, base
, tinfo
->rows
, tinfo
->row_size
, token_locator
);
1050 return (res
- base
) / tinfo
->row_size
;
1053 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1055 get_string_ptr (VerifyContext
*ctx
, guint offset
)
1057 return ctx
->image
->heap_strings
.data
+ offset
;
1060 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1062 string_cmp (VerifyContext
*ctx
, const char *str
, guint offset
)
1065 return strcmp (str
, "");
1067 return strcmp (str
, get_string_ptr (ctx
, offset
));
1071 mono_verifier_is_corlib (MonoImage
*image
)
1073 gboolean trusted_location
= (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR
) ?
1074 TRUE
: mono_security_core_clr_is_platform_image (image
);
1076 return trusted_location
&& image
->module_name
&& !strcmp ("mscorlib.dll", image
->module_name
);
1080 typedef_is_system_object (VerifyContext
*ctx
, guint32
*data
)
1082 return mono_verifier_is_corlib (ctx
->image
) && !string_cmp (ctx
, "System", data
[MONO_TYPEDEF_NAMESPACE
]) && !string_cmp (ctx
, "Object", data
[MONO_TYPEDEF_NAME
]);
1086 decode_value (const char *_ptr
, unsigned available
, unsigned *value
, unsigned *size
)
1089 const unsigned char *ptr
= (const unsigned char *)_ptr
;
1097 if ((b
& 0x80) == 0) {
1100 } else if ((b
& 0x40) == 0) {
1104 *value
= ((b
& 0x3f) << 8 | ptr
[1]);
1109 *value
= ((b
& 0x1f) << 24) |
1119 decode_signature_header (VerifyContext
*ctx
, guint32 offset
, guint32
*size
, const char **first_byte
)
1121 MonoStreamHeader blob
= ctx
->image
->heap_blob
;
1122 guint32 value
, enc_size
;
1124 if (offset
>= blob
.size
)
1127 if (!decode_value (blob
.data
+ offset
, blob
.size
- offset
, &value
, &enc_size
))
1130 if (CHECK_ADD4_OVERFLOW_UN (offset
, enc_size
))
1135 if (ADD_IS_GREATER_OR_OVF (offset
, value
, blob
.size
))
1139 *first_byte
= blob
.data
+ offset
;
1144 safe_read (const char **_ptr
, const char *limit
, unsigned *dest
, int size
)
1146 const char *ptr
= *_ptr
;
1147 if (ptr
+ size
> limit
)
1151 *dest
= *((guint8
*)ptr
);
1155 *dest
= read16 (ptr
);
1159 *dest
= read32 (ptr
);
1168 safe_read_compressed_int (const char **_ptr
, const char *limit
, unsigned *dest
)
1171 const char *ptr
= *_ptr
;
1172 gboolean res
= decode_value (ptr
, limit
- ptr
, dest
, &size
);
1177 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1178 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1179 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1180 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1183 parse_type (VerifyContext
*ctx
, const char **_ptr
, const char *end
);
1186 parse_method_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
, gboolean allow_sentinel
, gboolean allow_unmanaged
);
1189 parse_custom_mods (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1191 const char *ptr
= *_ptr
;
1196 if (!safe_read8 (type
, ptr
, end
))
1197 FAIL (ctx
, g_strdup ("CustomMod: Not enough room for the type"));
1199 if (type
!= MONO_TYPE_CMOD_REQD
&& type
!= MONO_TYPE_CMOD_OPT
) {
1204 if (!safe_read_cint (token
, ptr
, end
))
1205 FAIL (ctx
, g_strdup ("CustomMod: Not enough room for the token"));
1207 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, token
))
1208 FAIL (ctx
, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token
));
1216 parse_array_shape (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1218 const char *ptr
= *_ptr
;
1220 unsigned size
, num
, i
;
1222 if (!safe_read8 (val
, ptr
, end
))
1223 FAIL (ctx
, g_strdup ("ArrayShape: Not enough room for Rank"));
1226 FAIL (ctx
, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1228 if (!safe_read_cint (size
, ptr
, end
))
1229 FAIL (ctx
, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1231 for (i
= 0; i
< size
; ++i
) {
1232 if (!safe_read_cint (num
, ptr
, end
))
1233 FAIL (ctx
, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i
+ 1));
1236 if (!safe_read_cint (size
, ptr
, end
))
1237 FAIL (ctx
, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1239 for (i
= 0; i
< size
; ++i
) {
1240 if (!safe_read_cint (num
, ptr
, end
))
1241 FAIL (ctx
, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i
+ 1));
1249 parse_generic_inst (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1251 const char *ptr
= *_ptr
;
1253 unsigned count
, token
, i
;
1255 if (!safe_read8 (type
, ptr
, end
))
1256 FAIL (ctx
, g_strdup ("GenericInst: Not enough room for kind"));
1258 if (type
!= MONO_TYPE_CLASS
&& type
!= MONO_TYPE_VALUETYPE
)
1259 FAIL (ctx
, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type
));
1261 if (!safe_read_cint (token
, ptr
, end
))
1262 FAIL (ctx
, g_strdup ("GenericInst: Not enough room for type token"));
1264 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, token
))
1265 FAIL (ctx
, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token
));
1268 if (mono_metadata_token_index (ctx
->token
) == get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
) &&
1269 mono_metadata_token_table (ctx
->token
) == get_coded_index_table (TYPEDEF_OR_REF_DESC
, token
))
1270 FAIL (ctx
, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx
->token
));
1273 if (!safe_read_cint (count
, ptr
, end
))
1274 FAIL (ctx
, g_strdup ("GenericInst: Not enough room for argument count"));
1277 FAIL (ctx
, g_strdup ("GenericInst: Zero arguments generic instance"));
1279 for (i
= 0; i
< count
; ++i
) {
1280 if (!parse_type (ctx
, &ptr
, end
))
1281 FAIL (ctx
, g_strdup_printf ("GenericInst: invalid generic argument %d", i
+ 1));
1288 parse_type (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1290 const char *ptr
= *_ptr
;
1294 if (!safe_read8 (type
, ptr
, end
))
1295 FAIL (ctx
, g_strdup ("Type: Not enough room for the type"));
1297 if (!((type
>= MONO_TYPE_BOOLEAN
&& type
<= MONO_TYPE_PTR
) ||
1298 (type
>= MONO_TYPE_VALUETYPE
&& type
<= MONO_TYPE_GENERICINST
) ||
1299 (type
>= MONO_TYPE_I
&& type
<= MONO_TYPE_U
) ||
1300 (type
>= MONO_TYPE_FNPTR
&& type
<= MONO_TYPE_MVAR
)))
1301 FAIL (ctx
, g_strdup_printf ("Type: Invalid type kind %x\n", type
));
1305 if (!parse_custom_mods (ctx
, &ptr
, end
))
1306 FAIL (ctx
, g_strdup ("Type: Failed to parse pointer custom attr"));
1308 if (!safe_read8 (type
, ptr
, end
))
1309 FAIL (ctx
, g_strdup ("Type: Not enough room to parse the pointer type"));
1311 if (type
!= MONO_TYPE_VOID
) {
1313 if (!parse_type (ctx
, &ptr
, end
))
1314 FAIL (ctx
, g_strdup ("Type: Could not parse pointer type"));
1318 case MONO_TYPE_VALUETYPE
:
1319 case MONO_TYPE_CLASS
:
1320 if (!safe_read_cint (token
, ptr
, end
))
1321 FAIL (ctx
, g_strdup ("Type: Not enough room for the type token"));
1323 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, token
))
1324 FAIL (ctx
, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token
));
1326 if (mono_metadata_token_index (ctx
->token
) == get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
) &&
1327 mono_metadata_token_table (ctx
->token
) == get_coded_index_table (TYPEDEF_OR_REF_DESC
, token
))
1328 FAIL (ctx
, g_strdup_printf ("Type: Recurside type specification (%x). A type signature can't reference itself", ctx
->token
));
1333 case MONO_TYPE_MVAR
:
1334 if (!safe_read_cint (token
, ptr
, end
))
1335 FAIL (ctx
, g_strdup ("Type: Not enough room for to decode generic argument number"));
1338 case MONO_TYPE_ARRAY
:
1339 if (!parse_type (ctx
, &ptr
, end
))
1340 FAIL (ctx
, g_strdup ("Type: Could not parse array type"));
1341 if (!parse_array_shape (ctx
, &ptr
, end
))
1342 FAIL (ctx
, g_strdup ("Type: Could not parse array shape"));
1345 case MONO_TYPE_GENERICINST
:
1346 if (!parse_generic_inst (ctx
, &ptr
, end
))
1347 FAIL (ctx
, g_strdup ("Type: Could not parse generic inst"));
1350 case MONO_TYPE_FNPTR
:
1351 if (!parse_method_signature (ctx
, &ptr
, end
, TRUE
, TRUE
))
1352 FAIL (ctx
, g_strdup ("Type: Could not parse method pointer signature"));
1355 case MONO_TYPE_SZARRAY
:
1356 if (!parse_custom_mods (ctx
, &ptr
, end
))
1357 FAIL (ctx
, g_strdup ("Type: Failed to parse array element custom attr"));
1358 if (!parse_type (ctx
, &ptr
, end
))
1359 FAIL (ctx
, g_strdup ("Type: Could not parse array type"));
1367 parse_return_type (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1372 if (!parse_custom_mods (ctx
, _ptr
, end
))
1376 if (!safe_read8 (type
, ptr
, end
))
1377 FAIL (ctx
, g_strdup ("ReturnType: Not enough room for the type"));
1379 if (type
== MONO_TYPE_VOID
|| type
== MONO_TYPE_TYPEDBYREF
) {
1384 //it's a byref, update the cursor ptr
1385 if (type
== MONO_TYPE_BYREF
)
1388 return parse_type (ctx
, _ptr
, end
);
1392 parse_param (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1397 if (!parse_custom_mods (ctx
, _ptr
, end
))
1401 if (!safe_read8 (type
, ptr
, end
))
1402 FAIL (ctx
, g_strdup ("Param: Not enough room for the type"));
1404 if (type
== MONO_TYPE_TYPEDBYREF
) {
1409 //it's a byref, update the cursor ptr
1410 if (type
== MONO_TYPE_BYREF
)
1413 return parse_type (ctx
, _ptr
, end
);
1417 parse_method_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
, gboolean allow_sentinel
, gboolean allow_unmanaged
)
1420 unsigned param_count
= 0, gparam_count
= 0, type
= 0, i
;
1421 const char *ptr
= *_ptr
;
1422 gboolean saw_sentinel
= FALSE
;
1424 if (!safe_read8 (cconv
, ptr
, end
))
1425 FAIL (ctx
, g_strdup ("MethodSig: Not enough room for the call conv"));
1428 FAIL (ctx
, g_strdup ("MethodSig: CallConv has 0x80 set"));
1430 if (allow_unmanaged
) {
1431 if ((cconv
& 0x0F) > MONO_CALL_VARARG
)
1432 FAIL (ctx
, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv
& 0x0F));
1433 } else if ((cconv
& 0x0F) != MONO_CALL_DEFAULT
&& (cconv
& 0x0F) != MONO_CALL_VARARG
)
1434 FAIL (ctx
, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv
& 0x0F));
1436 if ((cconv
& 0x10) && !safe_read_cint (gparam_count
, ptr
, end
))
1437 FAIL (ctx
, g_strdup ("MethodSig: Not enough room for the generic param count"));
1439 if ((cconv
& 0x10) && gparam_count
== 0)
1440 FAIL (ctx
, g_strdup ("MethodSig: Signature with generics but zero arity"));
1442 if (allow_unmanaged
&& (cconv
& 0x10))
1443 FAIL (ctx
, g_strdup ("MethodSig: Standalone signature with generic params"));
1445 if (!safe_read_cint (param_count
, ptr
, end
))
1446 FAIL (ctx
, g_strdup ("MethodSig: Not enough room for the param count"));
1448 if (!parse_return_type (ctx
, &ptr
, end
))
1449 FAIL (ctx
, g_strdup ("MethodSig: Error parsing return type"));
1451 for (i
= 0; i
< param_count
; ++i
) {
1452 if (allow_sentinel
) {
1453 if (!safe_read8 (type
, ptr
, end
))
1454 FAIL (ctx
, g_strdup_printf ("MethodSig: Not enough room for param %d type", i
));
1456 if (type
== MONO_TYPE_SENTINEL
) {
1457 if ((cconv
& 0x0F) != MONO_CALL_VARARG
)
1458 FAIL (ctx
, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1461 FAIL (ctx
, g_strdup ("MethodSig: More than one sentinel type"));
1463 saw_sentinel
= TRUE
;
1469 if (!parse_param (ctx
, &ptr
, end
))
1470 FAIL (ctx
, g_strdup_printf ("MethodSig: Error parsing arg %d", i
));
1478 parse_property_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1481 unsigned param_count
= 0, i
;
1482 const char *ptr
= *_ptr
;
1484 if (!safe_read8 (sig
, ptr
, end
))
1485 FAIL (ctx
, g_strdup ("PropertySig: Not enough room for signature"));
1487 if (sig
!= 0x08 && sig
!= 0x28)
1488 FAIL (ctx
, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig
));
1490 if (!safe_read_cint (param_count
, ptr
, end
))
1491 FAIL (ctx
, g_strdup ("PropertySig: Not enough room for the param count"));
1493 if (!parse_custom_mods (ctx
, &ptr
, end
))
1496 if (!parse_type (ctx
, &ptr
, end
))
1497 FAIL (ctx
, g_strdup ("PropertySig: Could not parse property type"));
1499 for (i
= 0; i
< param_count
; ++i
) {
1500 if (!parse_type (ctx
, &ptr
, end
))
1501 FAIL (ctx
, g_strdup_printf ("PropertySig: Error parsing arg %d", i
));
1509 parse_field (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1511 const char *ptr
= *_ptr
;
1512 unsigned signature
= 0;
1514 if (!safe_read8 (signature
, ptr
, end
))
1515 FAIL (ctx
, g_strdup ("Field: Not enough room for field signature"));
1517 if (signature
!= 0x06)
1518 FAIL (ctx
, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature
));
1520 if (!parse_custom_mods (ctx
, &ptr
, end
))
1523 if (safe_read8 (signature
, ptr
, end
)) {
1524 if (signature
!= MONO_TYPE_BYREF
)
1529 return parse_type (ctx
, _ptr
, end
);
1533 parse_locals_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1536 unsigned locals_count
= 0, i
;
1537 const char *ptr
= *_ptr
;
1539 if (!safe_read8 (sig
, ptr
, end
))
1540 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for signature"));
1543 FAIL (ctx
, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig
));
1545 if (!safe_read_cint (locals_count
, ptr
, end
))
1546 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for the param count"));
1548 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1549 if (locals_count == 0)
1550 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1553 for (i
= 0; i
< locals_count
; ++i
) {
1554 if (!safe_read8 (sig
, ptr
, end
))
1555 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for type"));
1557 while (sig
== MONO_TYPE_CMOD_REQD
|| sig
== MONO_TYPE_CMOD_OPT
|| sig
== MONO_TYPE_PINNED
) {
1558 if (sig
!= MONO_TYPE_PINNED
&& !parse_custom_mods (ctx
, &ptr
, end
))
1559 FAIL (ctx
, g_strdup_printf ("LocalsSig: Error parsing local %d", i
));
1560 if (!safe_read8 (sig
, ptr
, end
))
1561 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for type"));
1564 if (sig
== MONO_TYPE_BYREF
) {
1565 if (!safe_read8 (sig
, ptr
, end
))
1566 FAIL (ctx
, g_strdup_printf ("Type: Not enough room for byref type for local %d", i
));
1567 if (sig
== MONO_TYPE_TYPEDBYREF
)
1568 FAIL (ctx
, g_strdup_printf ("Type: Invalid type typedref& for local %d", i
));
1571 if (sig
== MONO_TYPE_TYPEDBYREF
)
1576 if (!parse_type (ctx
, &ptr
, end
))
1577 FAIL (ctx
, g_strdup_printf ("LocalsSig: Error parsing local %d", i
));
1585 is_valid_field_signature (VerifyContext
*ctx
, guint32 offset
)
1588 unsigned signature
= 0;
1589 const char *ptr
= NULL
, *end
;
1591 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1592 FAIL (ctx
, g_strdup ("FieldSig: Could not decode signature header"));
1595 if (!safe_read8 (signature
, ptr
, end
))
1596 FAIL (ctx
, g_strdup ("FieldSig: Not enough room for the signature"));
1599 FAIL (ctx
, g_strdup_printf ("FieldSig: Invalid signature %x", signature
));
1602 return parse_field (ctx
, &ptr
, end
);
1606 is_valid_method_signature (VerifyContext
*ctx
, guint32 offset
)
1609 const char *ptr
= NULL
, *end
;
1611 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1612 FAIL (ctx
, g_strdup ("MethodSig: Could not decode signature header"));
1615 return parse_method_signature (ctx
, &ptr
, end
, FALSE
, FALSE
);
1619 is_valid_method_or_field_signature (VerifyContext
*ctx
, guint32 offset
)
1622 unsigned signature
= 0;
1623 const char *ptr
= NULL
, *end
;
1625 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1626 FAIL (ctx
, g_strdup ("MemberRefSig: Could not decode signature header"));
1629 if (!safe_read8 (signature
, ptr
, end
))
1630 FAIL (ctx
, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1633 if (signature
== 0x06)
1634 return parse_field (ctx
, &ptr
, end
);
1636 return parse_method_signature (ctx
, &ptr
, end
, TRUE
, FALSE
);
1640 is_valid_cattr_blob (VerifyContext
*ctx
, guint32 offset
)
1643 unsigned prolog
= 0;
1644 const char *ptr
= NULL
, *end
;
1649 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1650 FAIL (ctx
, g_strdup ("CustomAttribute: Could not decode signature header"));
1653 if (!safe_read16 (prolog
, ptr
, end
))
1654 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for prolog"));
1657 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog
));
1663 is_valid_cattr_type (MonoType
*type
)
1667 if (type
->type
== MONO_TYPE_OBJECT
|| (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_STRING
))
1670 if (type
->type
== MONO_TYPE_VALUETYPE
) {
1671 klass
= mono_class_from_mono_type (type
);
1672 return klass
&& klass
->enumtype
;
1675 if (type
->type
== MONO_TYPE_CLASS
)
1676 return mono_class_from_mono_type (type
) == mono_defaults
.systemtype_class
;
1682 is_valid_ser_string_full (VerifyContext
*ctx
, const char **str_start
, guint32
*str_len
, const char **_ptr
, const char *end
)
1685 const char *ptr
= *_ptr
;
1691 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for string size"));
1694 if (*ptr
== (char)0xFF) {
1699 if (!safe_read_cint (size
, ptr
, end
))
1700 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for string size"));
1702 if (ADDP_IS_GREATER_OR_OVF (ptr
, size
, end
))
1703 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for string"));
1713 is_valid_ser_string (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1715 const char *dummy_str
;
1717 return is_valid_ser_string_full (ctx
, &dummy_str
, &dummy_int
, _ptr
, end
);
1721 get_enum_by_encoded_name (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1725 const char *str_start
= NULL
;
1726 const char *ptr
= *_ptr
;
1728 guint32 str_len
= 0;
1730 if (!is_valid_ser_string_full (ctx
, &str_start
, &str_len
, &ptr
, end
))
1733 /*NULL or empty string*/
1734 if (str_start
== NULL
|| str_len
== 0) {
1735 ADD_ERROR_NO_RETURN (ctx
, g_strdup ("CustomAttribute: Null or empty enum name"));
1739 enum_name
= g_memdup (str_start
, str_len
+ 1);
1740 enum_name
[str_len
] = 0;
1741 type
= mono_reflection_type_from_name (enum_name
, ctx
->image
);
1743 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("CustomAttribute: Invalid enum class %s", enum_name
));
1749 klass
= mono_class_from_mono_type (type
);
1750 if (!klass
|| !klass
->enumtype
) {
1751 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", klass
->name_space
, klass
->name
));
1760 is_valid_fixed_param (VerifyContext
*ctx
, MonoType
*mono_type
, const char **_ptr
, const char *end
)
1763 const char *ptr
= *_ptr
;
1765 guint32 element_count
, i
;
1768 klass
= mono_type
->data
.klass
;
1769 type
= mono_type
->type
;
1773 case MONO_TYPE_BOOLEAN
:
1780 case MONO_TYPE_CHAR
:
1794 case MONO_TYPE_STRING
:
1796 return is_valid_ser_string (ctx
, _ptr
, end
);
1798 case MONO_TYPE_OBJECT
: {
1799 unsigned sub_type
= 0;
1800 if (!safe_read8 (sub_type
, ptr
, end
))
1801 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for array type"));
1803 if (sub_type
>= MONO_TYPE_BOOLEAN
&& sub_type
<= MONO_TYPE_STRING
) {
1807 if (sub_type
== MONO_TYPE_ENUM
) {
1808 klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
1812 klass
= klass
->element_class
;
1813 type
= klass
->byval_arg
.type
;
1816 if (sub_type
== 0x50) { /*Type*/
1818 return is_valid_ser_string (ctx
, _ptr
, end
);
1820 if (sub_type
== MONO_TYPE_SZARRAY
) {
1821 MonoType simple_type
= {{0}};
1823 if (!safe_read8 (etype
, ptr
, end
))
1824 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for array element type"));
1826 if (etype
== MONO_TYPE_ENUM
) {
1827 klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
1830 } else if ((etype
>= MONO_TYPE_BOOLEAN
&& etype
<= MONO_TYPE_STRING
) || etype
== 0x51) {
1831 simple_type
.type
= etype
== 0x51 ? MONO_TYPE_OBJECT
: etype
;
1832 klass
= mono_class_from_mono_type (&simple_type
);
1834 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype
));
1836 type
= MONO_TYPE_SZARRAY
;
1839 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type
));
1843 case MONO_TYPE_CLASS
:
1844 if (klass
!= mono_defaults
.systemtype_class
)
1845 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass
->name_space
, klass
->name
));
1847 return is_valid_ser_string (ctx
, _ptr
, end
);
1849 case MONO_TYPE_VALUETYPE
:
1850 if (!klass
|| !klass
->enumtype
)
1851 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",klass
->name_space
, klass
->name
));
1853 klass
= klass
->element_class
;
1854 type
= klass
->byval_arg
.type
;
1857 case MONO_TYPE_SZARRAY
:
1858 mono_type
= &klass
->byval_arg
;
1859 if (!is_valid_cattr_type (mono_type
))
1860 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",klass
->name_space
, klass
->name
));
1861 if (!safe_read32 (element_count
, ptr
, end
))
1862 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",klass
->name_space
, klass
->name
));
1863 if (element_count
== 0xFFFFFFFFu
) {
1867 for (i
= 0; i
< element_count
; ++i
) {
1868 if (!is_valid_fixed_param (ctx
, mono_type
, &ptr
, end
))
1874 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type
));
1877 if (ADDP_IS_GREATER_OR_OVF (ptr
, elem_size
, end
))
1878 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough space for element"));
1879 *_ptr
= ptr
+ elem_size
;
1884 is_valid_cattr_content (VerifyContext
*ctx
, MonoMethod
*ctor
, const char *ptr
, guint32 size
)
1887 unsigned prolog
= 0;
1889 MonoMethodSignature
*sig
;
1894 FAIL (ctx
, g_strdup ("CustomAttribute: Invalid constructor"));
1896 sig
= mono_method_signature_checked (ctor
, &error
);
1897 if (!mono_error_ok (&error
)) {
1898 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (&error
)));
1899 mono_error_cleanup (&error
);
1903 if (sig
->sentinelpos
!= -1 || sig
->call_convention
== MONO_CALL_VARARG
)
1904 FAIL (ctx
, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1908 if (!safe_read16 (prolog
, ptr
, end
))
1909 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for prolog"));
1912 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog
));
1914 args
= sig
->param_count
;
1915 for (i
= 0; i
< args
; ++i
) {
1916 MonoType
*arg_type
= sig
->params
[i
];
1917 if (!is_valid_fixed_param (ctx
, arg_type
, &ptr
, end
))
1921 if (!safe_read16 (num_named
, ptr
, end
))
1922 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough space for num_named field"));
1924 for (i
= 0; i
< num_named
; ++i
) {
1925 MonoType
*type
, simple_type
= {{0}};
1928 if (!safe_read8 (kind
, ptr
, end
))
1929 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i
));
1930 if (kind
!= 0x53 && kind
!= 0x54)
1931 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i
, kind
));
1932 if (!safe_read8 (kind
, ptr
, end
))
1933 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i
));
1935 if (kind
>= MONO_TYPE_BOOLEAN
&& kind
<= MONO_TYPE_STRING
) {
1936 simple_type
.type
= kind
;
1937 type
= &simple_type
;
1938 } else if (kind
== MONO_TYPE_ENUM
) {
1939 MonoClass
*klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
1942 type
= &klass
->byval_arg
;
1943 } else if (kind
== 0x50) {
1944 type
= &mono_defaults
.systemtype_class
->byval_arg
;
1945 } else if (kind
== 0x51) {
1946 type
= &mono_defaults
.object_class
->byval_arg
;
1947 } else if (kind
== MONO_TYPE_SZARRAY
) {
1950 if (!safe_read8 (etype
, ptr
, end
))
1951 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for array element type"));
1953 if (etype
== MONO_TYPE_ENUM
) {
1954 klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
1957 } else if ((etype
>= MONO_TYPE_BOOLEAN
&& etype
<= MONO_TYPE_STRING
) || etype
== 0x51) {
1958 simple_type
.type
= etype
== 0x51 ? MONO_TYPE_OBJECT
: etype
;
1959 klass
= mono_class_from_mono_type (&simple_type
);
1961 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype
));
1963 type
= &mono_array_class_get (klass
, 1)->byval_arg
;
1965 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind
));
1968 if (!is_valid_ser_string (ctx
, &ptr
, end
))
1971 if (!is_valid_fixed_param (ctx
, type
, &ptr
, end
))
1980 is_valid_marshal_spec (VerifyContext
*ctx
, guint32 offset
)
1982 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
1983 //TODO do proper verification
1984 return blob
.size
>= 1 && blob
.size
- 1 >= offset
;
1988 is_valid_permission_set (VerifyContext
*ctx
, guint32 offset
)
1990 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
1991 //TODO do proper verification
1992 return blob
.size
>= 1 && blob
.size
- 1 >= offset
;
1996 is_valid_standalonesig_blob (VerifyContext
*ctx
, guint32 offset
)
1999 unsigned signature
= 0;
2000 const char *ptr
= NULL
, *end
;
2002 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2003 FAIL (ctx
, g_strdup ("StandAloneSig: Could not decode signature header"));
2006 if (!safe_read8 (signature
, ptr
, end
))
2007 FAIL (ctx
, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2010 if (signature
== 0x07)
2011 return parse_locals_signature (ctx
, &ptr
, end
);
2013 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2014 if (signature
== 0x06)
2015 return parse_field (ctx
, &ptr
, end
);
2017 return parse_method_signature (ctx
, &ptr
, end
, TRUE
, TRUE
);
2021 is_valid_property_sig_blob (VerifyContext
*ctx
, guint32 offset
)
2024 const char *ptr
= NULL
, *end
;
2026 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2027 FAIL (ctx
, g_strdup ("PropertySig: Could not decode signature header"));
2030 return parse_property_signature (ctx
, &ptr
, end
);
2034 is_valid_typespec_blob (VerifyContext
*ctx
, guint32 offset
)
2037 const char *ptr
= NULL
, *end
;
2040 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2041 FAIL (ctx
, g_strdup ("TypeSpec: Could not decode signature header"));
2044 if (!parse_custom_mods (ctx
, &ptr
, end
))
2047 if (!safe_read8 (type
, ptr
, end
))
2048 FAIL (ctx
, g_strdup ("TypeSpec: Not enough room for type"));
2050 if (type
== MONO_TYPE_BYREF
) {
2051 if (!safe_read8 (type
, ptr
, end
))
2052 FAIL (ctx
, g_strdup ("TypeSpec: Not enough room for byref type"));
2053 if (type
== MONO_TYPE_TYPEDBYREF
)
2054 FAIL (ctx
, g_strdup ("TypeSpec: Invalid type typedref&"));
2057 if (type
== MONO_TYPE_TYPEDBYREF
)
2061 return parse_type (ctx
, &ptr
, end
);
2065 is_valid_methodspec_blob (VerifyContext
*ctx
, guint32 offset
)
2068 const char *ptr
= NULL
, *end
;
2070 unsigned count
= 0, i
;
2072 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2073 FAIL (ctx
, g_strdup ("MethodSpec: Could not decode signature header"));
2076 if (!safe_read8 (type
, ptr
, end
))
2077 FAIL (ctx
, g_strdup ("MethodSpec: Not enough room for call convention"));
2080 FAIL (ctx
, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type
));
2082 if (!safe_read_cint (count
, ptr
, end
))
2083 FAIL (ctx
, g_strdup ("MethodSpec: Not enough room for parameter count"));
2086 FAIL (ctx
, g_strdup ("MethodSpec: Zero generic argument count"));
2088 for (i
= 0; i
< count
; ++i
) {
2089 if (!parse_type (ctx
, &ptr
, end
))
2090 FAIL (ctx
, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i
+ 1));
2096 is_valid_blob_object (VerifyContext
*ctx
, guint32 offset
, guint32 minsize
)
2098 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
2099 guint32 entry_size
, bytes
;
2101 if (blob
.size
< offset
)
2104 if (!decode_value (ctx
->data
+ offset
+ blob
.offset
, blob
.size
- blob
.offset
, &entry_size
, &bytes
))
2107 if (entry_size
< minsize
)
2110 if (CHECK_ADD4_OVERFLOW_UN (entry_size
, bytes
))
2112 entry_size
+= bytes
;
2114 return !ADD_IS_GREATER_OR_OVF (offset
, entry_size
, blob
.size
);
2118 is_valid_constant (VerifyContext
*ctx
, guint32 type
, guint32 offset
)
2120 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
2121 guint32 size
, entry_size
, bytes
;
2123 if (blob
.size
< offset
)
2124 FAIL (ctx
, g_strdup ("ContantValue: invalid offset"));
2126 if (!decode_value (ctx
->data
+ offset
+ blob
.offset
, blob
.size
- blob
.offset
, &entry_size
, &bytes
))
2127 FAIL (ctx
, g_strdup ("ContantValue: not enough space to decode size"));
2129 if (type
== MONO_TYPE_STRING
) {
2130 //String is encoded as: compressed_int:len len *bytes
2133 if (ADD_IS_GREATER_OR_OVF (offset
, entry_size
, blob
.size
))
2134 FAIL (ctx
, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size
* 2, blob
.size
- offset
));
2140 case MONO_TYPE_BOOLEAN
:
2145 case MONO_TYPE_CHAR
:
2153 case MONO_TYPE_CLASS
:
2163 g_assert_not_reached ();
2166 if (size
!= entry_size
)
2167 FAIL (ctx
, g_strdup_printf ("ContantValue: Expected size %d but got %d", size
, entry_size
));
2171 if (ADD_IS_GREATER_OR_OVF (offset
, size
, blob
.size
))
2172 FAIL (ctx
, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size
, blob
.size
- offset
));
2174 if (type
== MONO_TYPE_CLASS
&& read32 (ctx
->data
+ blob
.offset
+ offset
))
2175 FAIL (ctx
, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2179 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2180 //only 0x01, 0x40 and 0x80 are allowed
2181 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2184 is_valid_method_header (VerifyContext
*ctx
, guint32 rva
)
2186 unsigned local_vars_tok
, code_size
, offset
= mono_cli_rva_image_map (ctx
->image
, rva
);
2187 unsigned header
= 0;
2188 unsigned fat_header
= 0, size
= 0, max_stack
;
2189 const char *ptr
= NULL
, *end
;
2191 if (offset
== INVALID_ADDRESS
)
2192 FAIL (ctx
, g_strdup ("MethodHeader: Invalid RVA"));
2194 ptr
= ctx
->data
+ offset
;
2195 end
= ctx
->data
+ ctx
->size
; /*no worries if it spawns multiple sections*/
2197 if (!safe_read8 (header
, ptr
, end
))
2198 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for header"));
2200 switch (header
& 0x3) {
2203 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header
& 0x3));
2206 if (ADDP_IS_GREATER_OR_OVF (ptr
, header
, end
))
2207 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header
, (int)(end
- ptr
)));
2212 if (!safe_read16 (fat_header
, ptr
, end
))
2213 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for fat header"));
2215 size
= (fat_header
>> 12) & 0xF;
2217 FAIL (ctx
, g_strdup ("MethodHeader: header size must be 3"));
2219 if (!safe_read16 (max_stack
, ptr
, end
))
2220 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for max stack"));
2222 if (!safe_read32 (code_size
, ptr
, end
))
2223 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for code size"));
2225 if (!safe_read32 (local_vars_tok
, ptr
, end
))
2226 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2228 if (local_vars_tok
) {
2229 if (((local_vars_tok
>> 24) & 0xFF) != 0x11)
2230 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok
>> 24) & 0xFF)));
2231 if ((local_vars_tok
& 0xFFFFFF) > ctx
->image
->tables
[MONO_TABLE_STANDALONESIG
].rows
)
2232 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok
& 0xFFFFFF));
2235 if (fat_header
& FAT_HEADER_INVALID_FLAGS
)
2236 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header
& FAT_HEADER_INVALID_FLAGS
));
2238 if (ADDP_IS_GREATER_OR_OVF (ptr
, code_size
, end
))
2239 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size
));
2241 if (!(fat_header
& 0x08))
2247 unsigned section_header
= 0, section_size
= 0;
2250 ptr
= dword_align (ptr
);
2251 if (!safe_read32 (section_header
, ptr
, end
))
2252 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for data section header"));
2254 if (section_header
& SECTION_HEADER_INVALID_FLAGS
)
2255 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header
& SECTION_HEADER_INVALID_FLAGS
));
2257 is_fat
= (section_header
& METHOD_HEADER_SECTION_FAT_FORMAT
) != 0;
2258 section_size
= (section_header
>> 8) & (is_fat
? 0xFFFFFF : 0xFF);
2260 if (section_size
< 4)
2261 FAIL (ctx
, g_strdup_printf ("MethodHeader: Section size too small"));
2263 if (ADDP_IS_GREATER_OR_OVF (ptr
, section_size
- 4, end
)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2264 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size
));
2266 if (section_header
& METHOD_HEADER_SECTION_EHTABLE
) {
2267 guint32 i
, clauses
= section_size
/ (is_fat
? 24 : 12);
2269 LAMEIMPL: MS emits section_size without accounting for header size.
2270 Mono does as the spec says. section_size is header + section
2271 MS's peverify happily accepts both.
2273 if ((clauses
* (is_fat
? 24 : 12) != section_size
) && (clauses
* (is_fat
? 24 : 12) + 4 != section_size
))
2274 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid EH section size %d, it's not of the expected size %d", section_size
, clauses
* (is_fat
? 24 : 12)));
2276 /* only verify the class token is verified as the rest is done by the IL verifier*/
2277 for (i
= 0; i
< clauses
; ++i
) {
2278 unsigned flags
= *(unsigned char*)ptr
;
2279 unsigned class_token
= 0;
2280 ptr
+= (is_fat
? 20 : 8);
2281 if (!safe_read32 (class_token
, ptr
, end
))
2282 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for section %d", i
));
2283 if (flags
== MONO_EXCEPTION_CLAUSE_NONE
&& class_token
) {
2284 guint table
= mono_metadata_token_table (class_token
);
2285 if (table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPESPEC
)
2286 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i
, table
));
2287 if (mono_metadata_token_index (class_token
) > ctx
->image
->tables
[table
].rows
)
2288 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i
, mono_metadata_token_index (class_token
)));
2293 if (!(section_header
& METHOD_HEADER_SECTION_MORE_SECTS
))
2300 verify_module_table (VerifyContext
*ctx
)
2302 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MODULE
];
2303 guint32 data
[MONO_MODULE_SIZE
];
2305 if (table
->rows
!= 1)
2306 ADD_ERROR (ctx
, g_strdup_printf ("Module table must have exactly one row, but have %d", table
->rows
));
2308 mono_metadata_decode_row (table
, 0, data
, MONO_MODULE_SIZE
);
2310 if (!is_valid_non_empty_string (ctx
, data
[MONO_MODULE_NAME
]))
2311 ADD_ERROR (ctx
, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data
[MONO_MODULE_NAME
]));
2313 if (!is_valid_guid (ctx
, data
[MONO_MODULE_MVID
]))
2314 ADD_ERROR (ctx
, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data
[MONO_MODULE_MVID
]));
2316 if (data
[MONO_MODULE_ENC
] != 0)
2317 ADD_ERROR (ctx
, g_strdup_printf ("Module has a non zero Enc field %x", data
[MONO_MODULE_ENC
]));
2319 if (data
[MONO_MODULE_ENCBASE
] != 0)
2320 ADD_ERROR (ctx
, g_strdup_printf ("Module has a non zero EncBase field %x", data
[MONO_MODULE_ENCBASE
]));
2324 verify_typeref_table (VerifyContext
*ctx
)
2326 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEREF
];
2327 guint32 data
[MONO_TYPEREF_SIZE
];
2330 for (i
= 0; i
< table
->rows
; ++i
) {
2331 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEREF_SIZE
);
2332 if (!is_valid_coded_index (ctx
, RES_SCOPE_DESC
, data
[MONO_TYPEREF_SCOPE
]))
2333 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i
, data
[MONO_TYPEREF_SCOPE
]));
2335 if (!get_coded_index_token (RES_SCOPE_DESC
, data
[MONO_TYPEREF_SCOPE
]))
2336 ADD_ERROR (ctx
, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i
));
2338 if (!data
[MONO_TYPEREF_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_TYPEREF_NAME
]))
2339 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typeref row %d name token 0x%08x", i
, data
[MONO_TYPEREF_NAME
]));
2341 if (data
[MONO_TYPEREF_NAMESPACE
] && !is_valid_non_empty_string (ctx
, data
[MONO_TYPEREF_NAMESPACE
]))
2342 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typeref row %d namespace token 0x%08x", i
, data
[MONO_TYPEREF_NAMESPACE
]));
2346 /*bits 9,11,14,15,19,21,24-31 */
2347 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2349 verify_typedef_table (VerifyContext
*ctx
)
2351 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2352 guint32 data
[MONO_TYPEDEF_SIZE
];
2353 guint32 fieldlist
= 1, methodlist
= 1, visibility
;
2356 if (table
->rows
== 0)
2357 ADD_ERROR (ctx
, g_strdup_printf ("Typedef table must have exactly at least one row"));
2359 for (i
= 0; i
< table
->rows
; ++i
) {
2360 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEDEF_SIZE
);
2361 if (data
[MONO_TYPEDEF_FLAGS
] & INVALID_TYPEDEF_FLAG_BITS
)
2362 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x", i
, data
[MONO_TYPEDEF_FLAGS
]));
2364 if ((data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_LAYOUT_MASK
) == 0x18)
2365 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i
));
2367 if ((data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == 0x30000)
2368 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i
));
2370 if ((data
[MONO_TYPEDEF_FLAGS
] & 0xC00000) != 0)
2371 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i
));
2373 if ((data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_INTERFACE
) && (data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_ABSTRACT
) == 0)
2374 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i
));
2376 if (!data
[MONO_TYPEDEF_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_TYPEDEF_NAME
]))
2377 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i
, data
[MONO_TYPEDEF_NAME
]));
2379 if (data
[MONO_TYPEREF_NAMESPACE
] && !is_valid_non_empty_string (ctx
, data
[MONO_TYPEREF_NAMESPACE
]))
2380 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i
, data
[MONO_TYPEREF_NAMESPACE
]));
2382 if (data
[MONO_TYPEDEF_EXTENDS
] && !is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_TYPEDEF_EXTENDS
]))
2383 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i
, data
[MONO_TYPEDEF_EXTENDS
]));
2385 visibility
= data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2386 if ((visibility
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visibility
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
) &&
2387 search_sorted_table (ctx
, MONO_TABLE_NESTEDCLASS
, MONO_NESTED_CLASS_NESTED
, i
+ 1) == -1)
2388 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i
));
2390 if (data
[MONO_TYPEDEF_FIELD_LIST
] == 0)
2391 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i
));
2393 if (data
[MONO_TYPEDEF_FIELD_LIST
] > ctx
->image
->tables
[MONO_TABLE_FIELD
].rows
+ 1)
2394 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i
, data
[MONO_TYPEDEF_FIELD_LIST
]));
2396 if (data
[MONO_TYPEDEF_FIELD_LIST
] < fieldlist
)
2397 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
));
2399 if (data
[MONO_TYPEDEF_METHOD_LIST
] == 0)
2400 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i
));
2402 if (data
[MONO_TYPEDEF_METHOD_LIST
] > ctx
->image
->tables
[MONO_TABLE_METHOD
].rows
+ 1)
2403 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i
, data
[MONO_TYPEDEF_METHOD_LIST
]));
2405 if (data
[MONO_TYPEDEF_METHOD_LIST
] < methodlist
)
2406 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
));
2408 fieldlist
= data
[MONO_TYPEDEF_FIELD_LIST
];
2409 methodlist
= data
[MONO_TYPEDEF_METHOD_LIST
];
2414 verify_typedef_table_full (VerifyContext
*ctx
)
2416 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2417 guint32 data
[MONO_TYPEDEF_SIZE
];
2420 if (table
->rows
== 0)
2421 ADD_ERROR (ctx
, g_strdup_printf ("Typedef table must have exactly at least one row"));
2423 for (i
= 0; i
< table
->rows
; ++i
) {
2424 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEDEF_SIZE
);
2427 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2428 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2429 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2434 if (data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_INTERFACE
) {
2435 if (data
[MONO_TYPEDEF_EXTENDS
])
2436 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i
));
2438 gboolean is_sys_obj
= typedef_is_system_object (ctx
, data
);
2439 gboolean has_parent
= get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_TYPEDEF_EXTENDS
]) != 0;
2443 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i
));
2446 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i
));
2454 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2456 verify_field_table (VerifyContext
*ctx
)
2458 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELD
];
2459 guint32 data
[MONO_FIELD_SIZE
], flags
, module_field_list
;
2462 module_field_list
= (guint32
)-1;
2463 if (ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
> 1) {
2464 MonoTableInfo
*type
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2465 module_field_list
= mono_metadata_decode_row_col (type
, 1, MONO_TYPEDEF_FIELD_LIST
);
2468 for (i
= 0; i
< table
->rows
; ++i
) {
2469 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_SIZE
);
2470 flags
= data
[MONO_FIELD_FLAGS
];
2472 if (flags
& INVALID_FIELD_FLAG_BITS
)
2473 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i
, flags
));
2475 if ((flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == 0x7)
2476 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i
));
2478 if ((flags
& (FIELD_ATTRIBUTE_LITERAL
| FIELD_ATTRIBUTE_INIT_ONLY
)) == (FIELD_ATTRIBUTE_LITERAL
| FIELD_ATTRIBUTE_INIT_ONLY
))
2479 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i
));
2481 if ((flags
& FIELD_ATTRIBUTE_RT_SPECIAL_NAME
) && !(flags
& FIELD_ATTRIBUTE_SPECIAL_NAME
))
2482 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i
));
2484 if ((flags
& FIELD_ATTRIBUTE_LITERAL
) && !(flags
& FIELD_ATTRIBUTE_STATIC
))
2485 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is Literal but not Static", i
));
2487 if ((flags
& FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL
) &&
2488 search_sorted_table (ctx
, MONO_TABLE_FIELDMARSHAL
, MONO_FIELD_MARSHAL_PARENT
, make_coded_token (HAS_FIELD_MARSHAL_DESC
, MONO_TABLE_FIELD
, i
)) == -1)
2489 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i
));
2491 if ((flags
& FIELD_ATTRIBUTE_HAS_DEFAULT
) &&
2492 search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_FIELD
, i
)) == -1)
2493 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i
));
2495 if ((flags
& FIELD_ATTRIBUTE_LITERAL
) &&
2496 search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_FIELD
, i
)) == -1)
2497 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i
));
2499 if ((flags
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) &&
2500 search_sorted_table (ctx
, MONO_TABLE_FIELDRVA
, MONO_FIELD_RVA_FIELD
, i
+ 1) == -1)
2501 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i
));
2503 if (!data
[MONO_FIELD_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_FIELD_NAME
]))
2504 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid name token %08x", i
, data
[MONO_FIELD_NAME
]));
2506 if (data
[MONO_FIELD_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_FIELD_SIGNATURE
], 1))
2507 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i
, data
[MONO_FIELD_SIGNATURE
]));
2509 //TODO verify contant flag
2511 if (i
+ 1 < module_field_list
) {
2512 guint32 access
= flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
;
2513 if (!(flags
& FIELD_ATTRIBUTE_STATIC
))
2514 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i
));
2515 if (access
!= FIELD_ATTRIBUTE_COMPILER_CONTROLLED
&& access
!= FIELD_ATTRIBUTE_PRIVATE
&& access
!= FIELD_ATTRIBUTE_PUBLIC
)
2516 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i
, access
));
2522 verify_field_table_full (VerifyContext
*ctx
)
2524 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELD
];
2525 guint32 data
[MONO_FIELD_SIZE
];
2528 for (i
= 0; i
< table
->rows
; ++i
) {
2529 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_SIZE
);
2531 if (!data
[MONO_FIELD_SIGNATURE
] || !is_valid_field_signature (ctx
, data
[MONO_FIELD_SIGNATURE
]))
2532 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i
, data
[MONO_FIELD_SIGNATURE
]));
2536 /*bits 8,9,10,11,13,14,15*/
2537 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2539 verify_method_table (VerifyContext
*ctx
)
2541 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHOD
];
2542 guint32 data
[MONO_METHOD_SIZE
], flags
, implflags
, rva
, module_method_list
, access
, code_type
;
2543 guint32 paramlist
= 1;
2544 gboolean is_ctor
, is_cctor
;
2548 module_method_list
= (guint32
)-1;
2549 if (ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
> 1) {
2550 MonoTableInfo
*type
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2551 module_method_list
= mono_metadata_decode_row_col (type
, 1, MONO_TYPEDEF_METHOD_LIST
);
2554 for (i
= 0; i
< table
->rows
; ++i
) {
2555 mono_metadata_decode_row (table
, i
, data
, MONO_METHOD_SIZE
);
2556 rva
= data
[MONO_METHOD_RVA
];
2557 implflags
= data
[MONO_METHOD_IMPLFLAGS
];
2558 flags
= data
[MONO_METHOD_FLAGS
];
2559 access
= flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
;
2560 code_type
= implflags
& METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK
;
2563 if (implflags
& INVALID_METHOD_IMPLFLAG_BITS
)
2564 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i
, implflags
));
2567 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i
));
2569 if (!data
[MONO_METHOD_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_METHOD_NAME
]))
2570 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i
, data
[MONO_METHOD_NAME
]));
2572 name
= get_string_ptr (ctx
, data
[MONO_METHOD_NAME
]);
2573 is_ctor
= !strcmp (".ctor", name
);
2574 is_cctor
= !strcmp (".cctor", name
);
2576 if ((is_ctor
|| is_cctor
) &&
2577 search_sorted_table (ctx
, MONO_TABLE_GENERICPARAM
, MONO_GENERICPARAM_OWNER
, make_coded_token (TYPE_OR_METHODDEF_DESC
, MONO_TABLE_METHOD
, i
)) != -1)
2578 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i
));
2580 if ((flags
& METHOD_ATTRIBUTE_STATIC
) && (flags
& (METHOD_ATTRIBUTE_FINAL
| METHOD_ATTRIBUTE_VIRTUAL
| METHOD_ATTRIBUTE_NEW_SLOT
)))
2581 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i
));
2583 if (flags
& METHOD_ATTRIBUTE_ABSTRACT
) {
2584 if (flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
2585 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i
));
2586 if (flags
& METHOD_ATTRIBUTE_FINAL
)
2587 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is Abstract and Final", i
));
2588 if (!(flags
& METHOD_ATTRIBUTE_VIRTUAL
))
2589 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i
));
2592 if (access
== METHOD_ATTRIBUTE_COMPILER_CONTROLLED
&& (flags
& (METHOD_ATTRIBUTE_RT_SPECIAL_NAME
| METHOD_ATTRIBUTE_SPECIAL_NAME
)))
2593 ADD_WARNING (ctx
, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i
));
2595 if ((flags
& METHOD_ATTRIBUTE_RT_SPECIAL_NAME
) && !(flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
))
2596 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i
));
2598 //XXX no checks against cas stuff 10,11,12,13)
2600 //TODO check iface with .ctor (15,16)
2602 if (i
+ 1 < module_method_list
) {
2603 if (!(flags
& METHOD_ATTRIBUTE_STATIC
))
2604 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is a global method but not Static", i
));
2605 if (flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_VIRTUAL
))
2606 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i
));
2607 if (!(access
== METHOD_ATTRIBUTE_COMPILER_CONTROLLED
|| access
== METHOD_ATTRIBUTE_PUBLIC
|| access
== METHOD_ATTRIBUTE_PRIVATE
))
2608 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i
));
2611 //TODO check valuetype for synchronized
2613 if ((flags
& (METHOD_ATTRIBUTE_FINAL
| METHOD_ATTRIBUTE_NEW_SLOT
| METHOD_ATTRIBUTE_STRICT
)) && !(flags
& METHOD_ATTRIBUTE_VIRTUAL
))
2614 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i
));
2616 if (flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
2617 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
2618 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i
));
2619 if (!(flags
& METHOD_ATTRIBUTE_STATIC
))
2620 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i
));
2623 if (!(flags
& METHOD_ATTRIBUTE_ABSTRACT
) && !rva
&& !(flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) &&
2624 !(implflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) && code_type
!= METHOD_IMPL_ATTRIBUTE_RUNTIME
)
2625 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i
));
2627 if (access
== METHOD_ATTRIBUTE_COMPILER_CONTROLLED
&& !(rva
|| (flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)))
2628 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i
));
2630 //TODO check signature contents
2633 if (flags
& METHOD_ATTRIBUTE_ABSTRACT
)
2634 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i
));
2635 if (code_type
== METHOD_IMPL_ATTRIBUTE_OPTIL
)
2636 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i
));
2638 if (!(flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_PINVOKE_IMPL
)) && !(implflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) && code_type
!= METHOD_IMPL_ATTRIBUTE_RUNTIME
)
2639 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i
));
2642 if ((flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)) {
2644 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i
));
2645 if (search_sorted_table (ctx
, MONO_TABLE_IMPLMAP
, MONO_IMPLMAP_MEMBER
, make_coded_token (MEMBER_FORWARDED_DESC
, MONO_TABLE_METHOD
, i
)) == -1)
2646 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i
));
2648 if (flags
& METHOD_ATTRIBUTE_RT_SPECIAL_NAME
&& !is_ctor
&& !is_cctor
)
2649 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i
));
2651 if ((is_ctor
|| is_cctor
) && !(flags
& METHOD_ATTRIBUTE_RT_SPECIAL_NAME
))
2652 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i
));
2654 if (data
[MONO_METHOD_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_METHOD_SIGNATURE
], 1))
2655 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i
, data
[MONO_METHOD_SIGNATURE
]));
2657 if (data
[MONO_METHOD_PARAMLIST
] == 0)
2658 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i
));
2660 if (data
[MONO_METHOD_PARAMLIST
] < paramlist
)
2661 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
));
2663 if (data
[MONO_METHOD_PARAMLIST
] > ctx
->image
->tables
[MONO_TABLE_PARAM
].rows
+ 1)
2664 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i
, data
[MONO_METHOD_PARAMLIST
]));
2666 paramlist
= data
[MONO_METHOD_PARAMLIST
];
2672 verify_method_table_full (VerifyContext
*ctx
)
2674 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHOD
];
2675 guint32 data
[MONO_METHOD_SIZE
], rva
;
2678 for (i
= 0; i
< table
->rows
; ++i
) {
2679 mono_metadata_decode_row (table
, i
, data
, MONO_METHOD_SIZE
);
2680 rva
= data
[MONO_METHOD_RVA
];
2682 if (!data
[MONO_METHOD_SIGNATURE
] || !is_valid_method_signature (ctx
, data
[MONO_METHOD_SIGNATURE
]))
2683 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i
, data
[MONO_METHOD_SIGNATURE
]));
2685 if (rva
&& !is_valid_method_header (ctx
, rva
))
2686 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i
));
2691 get_next_param_count (VerifyContext
*ctx
, guint32
*current_method
)
2693 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHOD
];
2694 guint32 row
= *current_method
;
2695 guint32 paramlist
, tmp
;
2698 paramlist
= mono_metadata_decode_row_col (table
, row
++, MONO_METHOD_PARAMLIST
);
2699 while (row
< table
->rows
) {
2700 tmp
= mono_metadata_decode_row_col (table
, row
, MONO_METHOD_PARAMLIST
);
2701 if (tmp
> paramlist
) {
2702 *current_method
= row
;
2703 return tmp
- paramlist
;
2708 /*no more methods, all params apply to the last one*/
2709 *current_method
= table
->rows
;
2714 #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))
2716 verify_param_table (VerifyContext
*ctx
)
2718 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_PARAM
];
2719 guint32 data
[MONO_PARAM_SIZE
], flags
, sequence
= 0, remaining_params
, current_method
= 0;
2720 gboolean first_param
= TRUE
;
2723 if (ctx
->image
->tables
[MONO_TABLE_METHOD
].rows
== 0) {
2724 if (table
->rows
> 0)
2725 ADD_ERROR (ctx
, g_strdup ("Param table has rows while the method table has zero"));
2729 remaining_params
= get_next_param_count (ctx
, ¤t_method
);
2731 for (i
= 0; i
< table
->rows
; ++i
) {
2732 mono_metadata_decode_row (table
, i
, data
, MONO_PARAM_SIZE
);
2733 flags
= data
[MONO_PARAM_FLAGS
];
2735 if (flags
& INVALID_PARAM_FLAGS_BITS
)
2736 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i
, flags
));
2738 if (search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_PARAM
, i
)) == -1) {
2739 if (flags
& PARAM_ATTRIBUTE_HAS_DEFAULT
)
2740 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i
));
2742 if (!(flags
& PARAM_ATTRIBUTE_HAS_DEFAULT
))
2743 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i
));
2746 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)
2747 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i
));
2749 if (!is_valid_string (ctx
, data
[MONO_PARAM_NAME
]))
2750 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i
, data
[MONO_PARAM_NAME
]));
2752 if (!first_param
&& data
[MONO_PARAM_SEQUENCE
] <= sequence
)
2753 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i
, data
[MONO_PARAM_SEQUENCE
], sequence
));
2755 first_param
= FALSE
;
2756 sequence
= data
[MONO_PARAM_SEQUENCE
];
2757 if (--remaining_params
== 0) {
2758 remaining_params
= get_next_param_count (ctx
, ¤t_method
);
2765 verify_interfaceimpl_table (VerifyContext
*ctx
)
2767 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_INTERFACEIMPL
];
2768 guint32 data
[MONO_INTERFACEIMPL_SIZE
];
2771 for (i
= 0; i
< table
->rows
; ++i
) {
2772 mono_metadata_decode_row (table
, i
, data
, MONO_INTERFACEIMPL_SIZE
);
2773 if (data
[MONO_INTERFACEIMPL_CLASS
] && data
[MONO_INTERFACEIMPL_CLASS
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
)
2774 ADD_ERROR (ctx
, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i
, data
[MONO_TABLE_TYPEDEF
]));
2776 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_INTERFACEIMPL_INTERFACE
]))
2777 ADD_ERROR (ctx
, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i
, data
[MONO_INTERFACEIMPL_INTERFACE
]));
2779 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_INTERFACEIMPL_INTERFACE
]))
2780 ADD_ERROR (ctx
, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i
));
2785 verify_memberref_table (VerifyContext
*ctx
)
2787 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MEMBERREF
];
2788 guint32 data
[MONO_MEMBERREF_SIZE
];
2791 for (i
= 0; i
< table
->rows
; ++i
) {
2792 mono_metadata_decode_row (table
, i
, data
, MONO_MEMBERREF_SIZE
);
2794 if (!is_valid_coded_index (ctx
, MEMBERREF_PARENT_DESC
, data
[MONO_MEMBERREF_CLASS
]))
2795 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i
, data
[MONO_MEMBERREF_CLASS
]));
2797 if (!get_coded_index_token (MEMBERREF_PARENT_DESC
, data
[MONO_MEMBERREF_CLASS
]))
2798 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i
));
2800 if (!is_valid_non_empty_string (ctx
, data
[MONO_MEMBERREF_NAME
]))
2801 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i
, data
[MONO_MEMBERREF_NAME
]));
2803 if (data
[MONO_MEMBERREF_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_MEMBERREF_SIGNATURE
], 1))
2804 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i
, data
[MONO_MEMBERREF_SIGNATURE
]));
2810 verify_memberref_table_full (VerifyContext
*ctx
)
2812 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MEMBERREF
];
2813 guint32 data
[MONO_MEMBERREF_SIZE
];
2816 for (i
= 0; i
< table
->rows
; ++i
) {
2817 mono_metadata_decode_row (table
, i
, data
, MONO_MEMBERREF_SIZE
);
2819 if (!is_valid_method_or_field_signature (ctx
, data
[MONO_MEMBERREF_SIGNATURE
]))
2820 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i
, data
[MONO_MEMBERREF_SIGNATURE
]));
2825 verify_constant_table (VerifyContext
*ctx
)
2827 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CONSTANT
];
2828 guint32 data
[MONO_CONSTANT_SIZE
], type
;
2831 for (i
= 0; i
< table
->rows
; ++i
) {
2832 mono_metadata_decode_row (table
, i
, data
, MONO_CONSTANT_SIZE
);
2833 type
= data
[MONO_CONSTANT_TYPE
];
2835 if (!((type
>= MONO_TYPE_BOOLEAN
&& type
<= MONO_TYPE_STRING
) || type
== MONO_TYPE_CLASS
))
2836 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i
, type
));
2838 if (!is_valid_coded_index (ctx
, HAS_CONSTANT_DESC
, data
[MONO_CONSTANT_PARENT
]))
2839 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i
, data
[MONO_CONSTANT_PARENT
]));
2841 if (!get_coded_index_token (HAS_CONSTANT_DESC
, data
[MONO_CONSTANT_PARENT
]))
2842 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i
));
2844 if (!is_valid_constant (ctx
, type
, data
[MONO_CONSTANT_VALUE
]))
2845 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i
, data
[MONO_CONSTANT_VALUE
]));
2850 verify_cattr_table (VerifyContext
*ctx
)
2852 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2853 guint32 data
[MONO_CUSTOM_ATTR_SIZE
];
2856 for (i
= 0; i
< table
->rows
; ++i
) {
2857 mono_metadata_decode_row (table
, i
, data
, MONO_CUSTOM_ATTR_SIZE
);
2859 if (!is_valid_coded_index (ctx
, HAS_CATTR_DESC
, data
[MONO_CUSTOM_ATTR_PARENT
]))
2860 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_PARENT
]));
2862 if (!is_valid_coded_index (ctx
, CATTR_TYPE_DESC
, data
[MONO_CUSTOM_ATTR_TYPE
]))
2863 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_PARENT
]));
2865 if (data
[MONO_CUSTOM_ATTR_VALUE
] && !is_valid_blob_object (ctx
, data
[MONO_CUSTOM_ATTR_VALUE
], 0))
2866 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i
, data
[MONO_CUSTOM_ATTR_VALUE
]));
2871 verify_cattr_table_full (VerifyContext
*ctx
)
2873 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2876 guint32 data
[MONO_CUSTOM_ATTR_SIZE
], mtoken
, size
;
2879 for (i
= 0; i
< table
->rows
; ++i
) {
2880 mono_metadata_decode_row (table
, i
, data
, MONO_CUSTOM_ATTR_SIZE
);
2882 if (!is_valid_cattr_blob (ctx
, data
[MONO_CUSTOM_ATTR_VALUE
]))
2883 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_VALUE
]));
2885 mtoken
= data
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
2886 switch (data
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
2887 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
2888 mtoken
|= MONO_TOKEN_METHOD_DEF
;
2890 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
2891 mtoken
|= MONO_TOKEN_MEMBER_REF
;
2894 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i
, data
[MONO_CUSTOM_ATTR_TYPE
]));
2897 ctor
= mono_get_method (ctx
->image
, mtoken
, NULL
);
2899 /*This can't fail since this is checked in is_valid_cattr_blob*/
2900 g_assert (decode_signature_header (ctx
, data
[MONO_CUSTOM_ATTR_VALUE
], &size
, &ptr
));
2902 if (!is_valid_cattr_content (ctx
, ctor
, ptr
, size
))
2903 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_VALUE
]));
2908 verify_field_marshal_table (VerifyContext
*ctx
)
2910 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDMARSHAL
];
2911 guint32 data
[MONO_FIELD_MARSHAL_SIZE
];
2914 for (i
= 0; i
< table
->rows
; ++i
) {
2915 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_MARSHAL_SIZE
);
2917 if (!is_valid_coded_index (ctx
, HAS_FIELD_MARSHAL_DESC
, data
[MONO_FIELD_MARSHAL_PARENT
]))
2918 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i
, data
[MONO_FIELD_MARSHAL_PARENT
]));
2920 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC
, data
[MONO_FIELD_MARSHAL_PARENT
]))
2921 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i
));
2923 if (!data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
])
2924 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i
));
2926 if (!is_valid_blob_object (ctx
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
], 1))
2927 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
]));
2932 verify_field_marshal_table_full (VerifyContext
*ctx
)
2934 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDMARSHAL
];
2935 guint32 data
[MONO_FIELD_MARSHAL_SIZE
];
2938 for (i
= 0; i
< table
->rows
; ++i
) {
2939 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_MARSHAL_SIZE
);
2941 if (!is_valid_marshal_spec (ctx
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
]))
2942 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
]));
2947 verify_decl_security_table (VerifyContext
*ctx
)
2949 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_DECLSECURITY
];
2950 guint32 data
[MONO_DECL_SECURITY_SIZE
];
2953 for (i
= 0; i
< table
->rows
; ++i
) {
2954 mono_metadata_decode_row (table
, i
, data
, MONO_DECL_SECURITY_SIZE
);
2956 if (!is_valid_coded_index (ctx
, HAS_DECL_SECURITY_DESC
, data
[MONO_DECL_SECURITY_PARENT
]))
2957 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i
, data
[MONO_DECL_SECURITY_PARENT
]));
2959 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC
, data
[MONO_DECL_SECURITY_PARENT
]))
2960 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i
));
2962 if (!data
[MONO_DECL_SECURITY_PERMISSIONSET
])
2963 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i
));
2968 verify_decl_security_table_full (VerifyContext
*ctx
)
2970 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_DECLSECURITY
];
2971 guint32 data
[MONO_DECL_SECURITY_SIZE
];
2974 for (i
= 0; i
< table
->rows
; ++i
) {
2975 mono_metadata_decode_row (table
, i
, data
, MONO_DECL_SECURITY_SIZE
);
2977 if (!is_valid_permission_set (ctx
, data
[MONO_DECL_SECURITY_PERMISSIONSET
]))
2978 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i
, data
[MONO_DECL_SECURITY_PERMISSIONSET
]));
2983 verify_class_layout_table (VerifyContext
*ctx
)
2985 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CLASSLAYOUT
];
2986 guint32 data
[MONO_CLASS_LAYOUT_SIZE
];
2989 for (i
= 0; i
< table
->rows
; ++i
) {
2990 mono_metadata_decode_row (table
, i
, data
, MONO_CLASS_LAYOUT_SIZE
);
2992 if (!data
[MONO_CLASS_LAYOUT_PARENT
] || data
[MONO_CLASS_LAYOUT_PARENT
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
2993 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i
, data
[MONO_TABLE_TYPEDEF
]));
2995 switch (data
[MONO_CLASS_LAYOUT_PACKING_SIZE
]) {
3007 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i
, data
[MONO_CLASS_LAYOUT_PACKING_SIZE
]));
3013 verify_field_layout_table (VerifyContext
*ctx
)
3015 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDLAYOUT
];
3016 guint32 data
[MONO_FIELD_LAYOUT_SIZE
];
3019 for (i
= 0; i
< table
->rows
; ++i
) {
3020 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_LAYOUT_SIZE
);
3022 if (!data
[MONO_FIELD_LAYOUT_FIELD
] || data
[MONO_FIELD_LAYOUT_FIELD
] > ctx
->image
->tables
[MONO_TABLE_FIELD
].rows
+ 1)
3023 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i
, data
[MONO_FIELD_LAYOUT_FIELD
]));
3028 verify_standalonesig_table (VerifyContext
*ctx
)
3030 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_STANDALONESIG
];
3031 guint32 data
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3034 for (i
= 0; i
< table
->rows
; ++i
) {
3035 mono_metadata_decode_row (table
, i
, data
, MONO_STAND_ALONE_SIGNATURE_SIZE
);
3037 if (data
[MONO_STAND_ALONE_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_STAND_ALONE_SIGNATURE
], 1))
3038 ADD_ERROR (ctx
, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i
, data
[MONO_STAND_ALONE_SIGNATURE
]));
3043 verify_standalonesig_table_full (VerifyContext
*ctx
)
3045 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_STANDALONESIG
];
3046 guint32 data
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3049 for (i
= 0; i
< table
->rows
; ++i
) {
3050 mono_metadata_decode_row (table
, i
, data
, MONO_STAND_ALONE_SIGNATURE_SIZE
);
3052 if (!is_valid_standalonesig_blob (ctx
, data
[MONO_STAND_ALONE_SIGNATURE
]))
3053 ADD_ERROR (ctx
, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i
, data
[MONO_STAND_ALONE_SIGNATURE
]));
3058 verify_eventmap_table (VerifyContext
*ctx
)
3060 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EVENTMAP
];
3061 guint32 data
[MONO_EVENT_MAP_SIZE
], eventlist
= 0;
3064 for (i
= 0; i
< table
->rows
; ++i
) {
3065 mono_metadata_decode_row (table
, i
, data
, MONO_EVENT_MAP_SIZE
);
3067 if (!data
[MONO_EVENT_MAP_PARENT
] || data
[MONO_EVENT_MAP_PARENT
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3068 ADD_ERROR (ctx
, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i
, data
[MONO_EVENT_MAP_PARENT
]));
3070 if (!data
[MONO_EVENT_MAP_EVENTLIST
] || data
[MONO_EVENT_MAP_EVENTLIST
] <= eventlist
)
3071 ADD_ERROR (ctx
, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i
, data
[MONO_EVENT_MAP_EVENTLIST
]));
3073 eventlist
= data
[MONO_EVENT_MAP_EVENTLIST
];
3077 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3079 verify_event_table (VerifyContext
*ctx
)
3081 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EVENT
];
3082 guint32 data
[MONO_EVENT_SIZE
];
3085 for (i
= 0; i
< table
->rows
; ++i
) {
3086 mono_metadata_decode_row (table
, i
, data
, MONO_EVENT_SIZE
);
3088 if (data
[MONO_EVENT_FLAGS
] & INVALID_EVENT_FLAGS_BITS
)
3089 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i
, data
[MONO_EVENT_FLAGS
]));
3091 if (!is_valid_non_empty_string (ctx
, data
[MONO_EVENT_NAME
]))
3092 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d Name field %08x", i
, data
[MONO_EVENT_NAME
]));
3094 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_EVENT_TYPE
]))
3095 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d EventType field %08x", i
, data
[MONO_EVENT_TYPE
]));
3100 verify_event_table_full (VerifyContext
*ctx
)
3102 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EVENT
];
3103 MonoTableInfo
*sema_table
= &ctx
->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
3104 guint32 data
[MONO_EVENT_SIZE
], sema_data
[MONO_METHOD_SEMA_SIZE
], token
;
3105 gboolean found_add
, found_remove
;
3108 for (i
= 0; i
< table
->rows
; ++i
) {
3109 mono_metadata_decode_row (table
, i
, data
, MONO_EVENT_SIZE
);
3111 token
= make_coded_token (HAS_SEMANTICS_DESC
, MONO_TABLE_EVENT
, i
);
3112 idx
= search_sorted_table (ctx
, MONO_TABLE_METHODSEMANTICS
, MONO_METHOD_SEMA_ASSOCIATION
, token
);
3114 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i
));
3116 //first we move to the first row for this event
3118 if (mono_metadata_decode_row_col (sema_table
, idx
- 1, MONO_METHOD_SEMA_ASSOCIATION
) != token
)
3122 //now move forward looking for AddOn and RemoveOn rows
3123 found_add
= found_remove
= FALSE
;
3124 while (idx
< sema_table
->rows
) {
3125 mono_metadata_decode_row (sema_table
, idx
, sema_data
, MONO_METHOD_SEMA_SIZE
);
3126 if (sema_data
[MONO_METHOD_SEMA_ASSOCIATION
] != token
)
3128 if (sema_data
[MONO_METHOD_SEMA_SEMANTICS
] & METHOD_SEMANTIC_ADD_ON
)
3130 if (sema_data
[MONO_METHOD_SEMA_SEMANTICS
] & METHOD_SEMANTIC_REMOVE_ON
)
3131 found_remove
= TRUE
;
3132 if (found_add
&& found_remove
)
3138 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i
));
3140 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i
));
3145 verify_propertymap_table (VerifyContext
*ctx
)
3147 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_PROPERTYMAP
];
3148 guint32 data
[MONO_PROPERTY_MAP_SIZE
], propertylist
= 0;
3151 for (i
= 0; i
< table
->rows
; ++i
) {
3152 mono_metadata_decode_row (table
, i
, data
, MONO_PROPERTY_MAP_SIZE
);
3154 if (!data
[MONO_PROPERTY_MAP_PARENT
] || data
[MONO_PROPERTY_MAP_PARENT
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3155 ADD_ERROR (ctx
, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i
, data
[MONO_PROPERTY_MAP_PARENT
]));
3157 if (!data
[MONO_PROPERTY_MAP_PROPERTY_LIST
] || data
[MONO_PROPERTY_MAP_PROPERTY_LIST
] <= propertylist
)
3158 ADD_ERROR (ctx
, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i
, data
[MONO_PROPERTY_MAP_PROPERTY_LIST
]));
3160 propertylist
= data
[MONO_PROPERTY_MAP_PROPERTY_LIST
];
3164 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3166 verify_property_table (VerifyContext
*ctx
)
3168 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_PROPERTY
];
3169 guint32 data
[MONO_PROPERTY_SIZE
];
3172 for (i
= 0; i
< table
->rows
; ++i
) {
3173 mono_metadata_decode_row (table
, i
, data
, MONO_PROPERTY_SIZE
);
3175 if (data
[MONO_PROPERTY_FLAGS
] & INVALID_PROPERTY_FLAGS_BITS
)
3176 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i
, data
[MONO_PROPERTY_FLAGS
]));
3178 if (!is_valid_non_empty_string (ctx
, data
[MONO_PROPERTY_NAME
]))
3179 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d Name field %08x", i
, data
[MONO_PROPERTY_NAME
]));
3181 if (!is_valid_property_sig_blob (ctx
, data
[MONO_PROPERTY_TYPE
]))
3182 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d Type field %08x", i
, data
[MONO_PROPERTY_TYPE
]));
3184 if ((data
[MONO_PROPERTY_FLAGS
] & PROPERTY_ATTRIBUTE_HAS_DEFAULT
) &&
3185 search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_PROPERTY
, i
)) == -1)
3186 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i
));
3192 verify_methodimpl_table (VerifyContext
*ctx
)
3194 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODIMPL
];
3195 guint32 data
[MONO_METHODIMPL_SIZE
];
3198 for (i
= 0; i
< table
->rows
; ++i
) {
3199 mono_metadata_decode_row (table
, i
, data
, MONO_METHODIMPL_SIZE
);
3201 if (!data
[MONO_METHODIMPL_CLASS
] || data
[MONO_METHODIMPL_CLASS
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3202 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i
, data
[MONO_TABLE_TYPEDEF
]));
3204 if (!get_coded_index_token (METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_BODY
]))
3205 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i
, data
[MONO_METHODIMPL_BODY
]));
3207 if (!is_valid_coded_index (ctx
, METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_BODY
]))
3208 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i
, data
[MONO_METHODIMPL_BODY
]));
3210 if (!get_coded_index_token (METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_DECLARATION
]))
3211 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i
, data
[MONO_METHODIMPL_DECLARATION
]));
3213 if (!is_valid_coded_index (ctx
, METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_DECLARATION
]))
3214 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i
, data
[MONO_METHODIMPL_DECLARATION
]));
3219 verify_moduleref_table (VerifyContext
*ctx
)
3221 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MODULEREF
];
3222 guint32 data
[MONO_MODULEREF_SIZE
];
3225 for (i
= 0; i
< table
->rows
; ++i
) {
3226 mono_metadata_decode_row (table
, i
, data
, MONO_MODULEREF_SIZE
);
3228 if (!is_valid_non_empty_string (ctx
, data
[MONO_MODULEREF_NAME
]))
3229 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i
, data
[MONO_TABLE_TYPEDEF
]));
3234 verify_typespec_table (VerifyContext
*ctx
)
3236 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPESPEC
];
3237 guint32 data
[MONO_TYPESPEC_SIZE
];
3240 for (i
= 0; i
< table
->rows
; ++i
) {
3241 mono_metadata_decode_row (table
, i
, data
, MONO_TYPESPEC_SIZE
);
3243 if (data
[MONO_TYPESPEC_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_TYPESPEC_SIGNATURE
], 1))
3244 ADD_ERROR (ctx
, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i
, data
[MONO_TYPESPEC_SIGNATURE
]));
3249 verify_typespec_table_full (VerifyContext
*ctx
)
3251 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPESPEC
];
3252 guint32 data
[MONO_TYPESPEC_SIZE
];
3255 for (i
= 0; i
< table
->rows
; ++i
) {
3256 mono_metadata_decode_row (table
, i
, data
, MONO_TYPESPEC_SIZE
);
3257 ctx
->token
= (i
+ 1) | MONO_TOKEN_TYPE_SPEC
;
3258 if (!is_valid_typespec_blob (ctx
, data
[MONO_TYPESPEC_SIGNATURE
]))
3259 ADD_ERROR (ctx
, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i
, data
[MONO_TYPESPEC_SIGNATURE
]));
3264 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10))
3266 verify_implmap_table (VerifyContext
*ctx
)
3268 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_IMPLMAP
];
3269 guint32 data
[MONO_IMPLMAP_SIZE
], cconv
;
3272 for (i
= 0; i
< table
->rows
; ++i
) {
3273 mono_metadata_decode_row (table
, i
, data
, MONO_IMPLMAP_SIZE
);
3275 if (data
[MONO_IMPLMAP_FLAGS
] & INVALID_IMPLMAP_FLAGS_BITS
)
3276 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i
, data
[MONO_IMPLMAP_FLAGS
]));
3278 cconv
= data
[MONO_IMPLMAP_FLAGS
] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK
;
3279 if (cconv
== 0 || cconv
== 0x0600 || cconv
== 0x0700)
3280 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i
, cconv
));
3282 if (!is_valid_coded_index (ctx
, MEMBER_FORWARDED_DESC
, data
[MONO_IMPLMAP_MEMBER
]))
3283 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i
, data
[MONO_IMPLMAP_MEMBER
]));
3285 if (get_coded_index_table (MEMBER_FORWARDED_DESC
, data
[MONO_IMPLMAP_MEMBER
]) != MONO_TABLE_METHOD
)
3286 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i
, data
[MONO_IMPLMAP_MEMBER
]));
3288 if (!get_coded_index_token (MEMBER_FORWARDED_DESC
, data
[MONO_IMPLMAP_MEMBER
]))
3289 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d null token", i
));
3291 if (!is_valid_non_empty_string (ctx
, data
[MONO_IMPLMAP_NAME
]))
3292 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i
, data
[MONO_IMPLMAP_NAME
]));
3294 if (!data
[MONO_IMPLMAP_SCOPE
] || data
[MONO_IMPLMAP_SCOPE
] > ctx
->image
->tables
[MONO_TABLE_MODULEREF
].rows
+ 1)
3295 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i
, data
[MONO_IMPLMAP_SCOPE
]));
3300 verify_fieldrva_table (VerifyContext
*ctx
)
3302 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDRVA
];
3303 guint32 data
[MONO_FIELD_RVA_SIZE
];
3306 for (i
= 0; i
< table
->rows
; ++i
) {
3307 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_RVA_SIZE
);
3309 if (!data
[MONO_FIELD_RVA_RVA
] || mono_cli_rva_image_map (ctx
->image
, data
[MONO_FIELD_RVA_RVA
]) == INVALID_ADDRESS
)
3310 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i
, data
[MONO_FIELD_RVA_RVA
]));
3312 if (!data
[MONO_FIELD_RVA_FIELD
] || data
[MONO_FIELD_RVA_FIELD
] > ctx
->image
->tables
[MONO_TABLE_FIELD
].rows
+ 1)
3313 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i
, data
[MONO_FIELD_RVA_FIELD
]));
3317 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 8) | (1 << 14) | (1 << 15))
3319 verify_assembly_table (VerifyContext
*ctx
)
3321 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_ASSEMBLY
];
3322 guint32 data
[MONO_ASSEMBLY_SIZE
], hash
;
3325 if (table
->rows
> 1)
3326 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table
->rows
));
3328 for (i
= 0; i
< table
->rows
; ++i
) {
3329 mono_metadata_decode_row (table
, i
, data
, MONO_ASSEMBLY_SIZE
);
3331 hash
= data
[MONO_ASSEMBLY_HASH_ALG
];
3332 if (!(hash
== 0 || hash
== 0x8003 || hash
== 0x8004))
3333 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i
, hash
));
3335 if (data
[MONO_ASSEMBLY_FLAGS
] & INVALID_ASSEMBLY_FLAGS_BITS
)
3336 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i
, data
[MONO_ASSEMBLY_FLAGS
]));
3338 if (data
[MONO_ASSEMBLY_PUBLIC_KEY
] && !is_valid_blob_object (ctx
, data
[MONO_ASSEMBLY_PUBLIC_KEY
], 1))
3339 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i
, data
[MONO_ASSEMBLY_FLAGS
]));
3341 if (!is_valid_non_empty_string (ctx
, data
[MONO_ASSEMBLY_NAME
]))
3342 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i
, data
[MONO_ASSEMBLY_NAME
]));
3344 if (data
[MONO_ASSEMBLY_CULTURE
] && !is_valid_string (ctx
, data
[MONO_ASSEMBLY_CULTURE
]))
3345 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i
, data
[MONO_ASSEMBLY_CULTURE
]));
3349 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~(1)
3351 verify_assemblyref_table (VerifyContext
*ctx
)
3353 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
3354 guint32 data
[MONO_ASSEMBLYREF_SIZE
];
3357 for (i
= 0; i
< table
->rows
; ++i
) {
3358 mono_metadata_decode_row (table
, i
, data
, MONO_ASSEMBLYREF_SIZE
);
3360 if (data
[MONO_ASSEMBLYREF_FLAGS
] & INVALID_ASSEMBLYREF_FLAGS_BITS
)
3361 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i
, data
[MONO_ASSEMBLYREF_FLAGS
]));
3363 if (data
[MONO_ASSEMBLYREF_PUBLIC_KEY
] && !is_valid_blob_object (ctx
, data
[MONO_ASSEMBLYREF_PUBLIC_KEY
], 1))
3364 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i
, data
[MONO_ASSEMBLYREF_PUBLIC_KEY
]));
3366 if (!is_valid_non_empty_string (ctx
, data
[MONO_ASSEMBLYREF_NAME
]))
3367 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i
, data
[MONO_ASSEMBLYREF_NAME
]));
3369 if (data
[MONO_ASSEMBLYREF_CULTURE
] && !is_valid_string (ctx
, data
[MONO_ASSEMBLYREF_CULTURE
]))
3370 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i
, data
[MONO_ASSEMBLYREF_CULTURE
]));
3372 if (data
[MONO_ASSEMBLYREF_HASH_VALUE
] && !is_valid_blob_object (ctx
, data
[MONO_ASSEMBLYREF_HASH_VALUE
], 1))
3373 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i
, data
[MONO_ASSEMBLYREF_HASH_VALUE
]));
3377 #define INVALID_FILE_FLAGS_BITS ~(1)
3379 verify_file_table (VerifyContext
*ctx
)
3381 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FILE
];
3382 guint32 data
[MONO_FILE_SIZE
];
3385 for (i
= 0; i
< table
->rows
; ++i
) {
3386 mono_metadata_decode_row (table
, i
, data
, MONO_FILE_SIZE
);
3388 if (data
[MONO_FILE_FLAGS
] & INVALID_FILE_FLAGS_BITS
)
3389 ADD_ERROR (ctx
, g_strdup_printf ("File table row %d has invalid Flags %08x", i
, data
[MONO_FILE_FLAGS
]));
3391 if (!is_valid_non_empty_string (ctx
, data
[MONO_FILE_NAME
]))
3392 ADD_ERROR (ctx
, g_strdup_printf ("File table row %d has invalid Name %08x", i
, data
[MONO_FILE_NAME
]));
3394 if (!data
[MONO_FILE_HASH_VALUE
] || !is_valid_blob_object (ctx
, data
[MONO_FILE_HASH_VALUE
], 1))
3395 ADD_ERROR (ctx
, g_strdup_printf ("File table row %d has invalid HashValue %08x", i
, data
[MONO_FILE_HASH_VALUE
]));
3399 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3401 verify_exportedtype_table (VerifyContext
*ctx
)
3403 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3404 guint32 data
[MONO_EXP_TYPE_SIZE
];
3407 for (i
= 0; i
< table
->rows
; ++i
) {
3408 mono_metadata_decode_row (table
, i
, data
, MONO_EXP_TYPE_SIZE
);
3410 if (data
[MONO_EXP_TYPE_FLAGS
] & INVALID_EXPORTED_TYPE_FLAGS_BITS
)
3411 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i
, data
[MONO_EXP_TYPE_FLAGS
]));
3413 if (!is_valid_non_empty_string (ctx
, data
[MONO_EXP_TYPE_NAME
]))
3414 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i
, data
[MONO_FILE_NAME
]));
3416 if (data
[MONO_EXP_TYPE_NAMESPACE
] && !is_valid_string (ctx
, data
[MONO_EXP_TYPE_NAMESPACE
]))
3417 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i
, data
[MONO_EXP_TYPE_NAMESPACE
]));
3419 if (!is_valid_coded_index (ctx
, IMPLEMENTATION_DESC
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]))
3420 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]));
3422 if (!get_coded_index_token (IMPLEMENTATION_DESC
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]))
3423 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has null Implementation token", i
));
3425 /*nested type can't have a namespace*/
3426 if (get_coded_index_table (IMPLEMENTATION_DESC
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]) == MONO_TABLE_EXPORTEDTYPE
&& data
[MONO_EXP_TYPE_NAMESPACE
])
3427 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i
));
3431 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3433 verify_manifest_resource_table (VerifyContext
*ctx
)
3435 MonoCLIImageInfo
*iinfo
= ctx
->image
->image_info
;
3436 MonoCLIHeader
*ch
= &iinfo
->cli_cli_header
;
3437 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
3438 guint32 data
[MONO_MANIFEST_SIZE
], impl_table
, token
, resources_size
;
3441 resources_size
= ch
->ch_resources
.size
;
3443 for (i
= 0; i
< table
->rows
; ++i
) {
3444 mono_metadata_decode_row (table
, i
, data
, MONO_MANIFEST_SIZE
);
3446 if (data
[MONO_MANIFEST_FLAGS
] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS
)
3447 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i
, data
[MONO_MANIFEST_FLAGS
]));
3449 if (data
[MONO_MANIFEST_FLAGS
] != 1 && data
[MONO_MANIFEST_FLAGS
] != 2)
3450 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i
, data
[MONO_MANIFEST_FLAGS
]));
3452 if (!is_valid_non_empty_string (ctx
, data
[MONO_MANIFEST_NAME
]))
3453 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i
, data
[MONO_MANIFEST_NAME
]));
3455 if (!is_valid_coded_index (ctx
, IMPLEMENTATION_DESC
, data
[MONO_MANIFEST_IMPLEMENTATION
]))
3456 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i
, data
[MONO_MANIFEST_IMPLEMENTATION
]));
3458 impl_table
= get_coded_index_table (IMPLEMENTATION_DESC
, data
[MONO_MANIFEST_IMPLEMENTATION
]);
3459 token
= get_coded_index_token (IMPLEMENTATION_DESC
, data
[MONO_MANIFEST_IMPLEMENTATION
]);
3461 if (impl_table
== MONO_TABLE_EXPORTEDTYPE
)
3462 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
])));
3464 if (impl_table
== MONO_TABLE_FILE
&& token
&& data
[MONO_MANIFEST_OFFSET
])
3465 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i
));
3467 if (!token
&& data
[MONO_MANIFEST_OFFSET
] >= resources_size
)
3468 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i
, data
[MONO_MANIFEST_OFFSET
]));
3473 verify_nested_class_table (VerifyContext
*ctx
)
3475 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_NESTEDCLASS
];
3476 guint32 data
[MONO_NESTED_CLASS_SIZE
];
3479 for (i
= 0; i
< table
->rows
; ++i
) {
3480 mono_metadata_decode_row (table
, i
, data
, MONO_NESTED_CLASS_SIZE
);
3482 if (!data
[MONO_NESTED_CLASS_NESTED
] || data
[MONO_NESTED_CLASS_NESTED
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
)
3483 ADD_ERROR (ctx
, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i
, data
[MONO_NESTED_CLASS_NESTED
]));
3484 if (!data
[MONO_NESTED_CLASS_ENCLOSING
] || data
[MONO_NESTED_CLASS_ENCLOSING
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
)
3485 ADD_ERROR (ctx
, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i
, data
[MONO_NESTED_CLASS_ENCLOSING
]));
3486 if (data
[MONO_NESTED_CLASS_ENCLOSING
] == data
[MONO_NESTED_CLASS_NESTED
])
3487 ADD_ERROR (ctx
, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i
, data
[MONO_NESTED_CLASS_ENCLOSING
]));
3491 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3493 verify_generic_param_table (VerifyContext
*ctx
)
3495 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_GENERICPARAM
];
3496 guint32 data
[MONO_GENERICPARAM_SIZE
], token
, last_token
= 0;
3497 int i
, param_number
= 0;
3499 for (i
= 0; i
< table
->rows
; ++i
) {
3500 mono_metadata_decode_row (table
, i
, data
, MONO_GENERICPARAM_SIZE
);
3502 if (data
[MONO_GENERICPARAM_FLAGS
] & INVALID_GENERIC_PARAM_FLAGS_BITS
)
3503 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i
, data
[MONO_GENERICPARAM_FLAGS
]));
3505 if ((data
[MONO_GENERICPARAM_FLAGS
] & MONO_GEN_PARAM_VARIANCE_MASK
) == 0x3)
3506 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i
));
3508 if (!is_valid_non_empty_string (ctx
, data
[MONO_GENERICPARAM_NAME
]))
3509 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i
, data
[MONO_GENERICPARAM_NAME
]));
3511 token
= data
[MONO_GENERICPARAM_OWNER
];
3513 if (!is_valid_coded_index (ctx
, TYPE_OR_METHODDEF_DESC
, token
))
3514 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i
, token
));
3516 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC
, token
))
3517 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has null Owner token", i
));
3519 if (token
!= last_token
) {
3524 if (data
[MONO_GENERICPARAM_NUMBER
] != param_number
)
3525 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
));
3532 verify_method_spec_table (VerifyContext
*ctx
)
3534 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODSPEC
];
3535 guint32 data
[MONO_METHODSPEC_SIZE
];
3538 for (i
= 0; i
< table
->rows
; ++i
) {
3539 mono_metadata_decode_row (table
, i
, data
, MONO_METHODSPEC_SIZE
);
3541 if (!is_valid_coded_index (ctx
, METHODDEF_OR_REF_DESC
, data
[MONO_METHODSPEC_METHOD
]))
3542 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i
, data
[MONO_METHODSPEC_METHOD
]));
3544 if (!get_coded_index_token (METHODDEF_OR_REF_DESC
, data
[MONO_METHODSPEC_METHOD
]))
3545 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has null Method token", i
));
3547 if (data
[MONO_METHODSPEC_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_METHODSPEC_SIGNATURE
], 1))
3548 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i
, data
[MONO_METHODSPEC_SIGNATURE
]));
3553 verify_method_spec_table_full (VerifyContext
*ctx
)
3555 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODSPEC
];
3556 guint32 data
[MONO_METHODSPEC_SIZE
];
3559 for (i
= 0; i
< table
->rows
; ++i
) {
3560 mono_metadata_decode_row (table
, i
, data
, MONO_METHODSPEC_SIZE
);
3562 if (!is_valid_methodspec_blob (ctx
, data
[MONO_METHODSPEC_SIGNATURE
]))
3563 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i
, data
[MONO_METHODSPEC_SIGNATURE
]));
3568 verify_generic_param_constraint_table (VerifyContext
*ctx
)
3570 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
3571 guint32 data
[MONO_GENPARCONSTRAINT_SIZE
];
3574 for (i
= 0; i
< table
->rows
; ++i
) {
3575 mono_metadata_decode_row (table
, i
, data
, MONO_GENPARCONSTRAINT_SIZE
);
3577 if (!data
[MONO_GENPARCONSTRAINT_GENERICPAR
] || data
[MONO_GENPARCONSTRAINT_GENERICPAR
] > ctx
->image
->tables
[MONO_TABLE_GENERICPARAM
].rows
)
3578 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i
, data
[MONO_TABLE_GENERICPARAM
]));
3580 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_GENPARCONSTRAINT_CONSTRAINT
]))
3581 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i
, data
[MONO_GENPARCONSTRAINT_CONSTRAINT
]));
3583 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_GENPARCONSTRAINT_CONSTRAINT
]))
3584 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i
));
3591 const char *name_space
;
3592 guint32 resolution_scope
;
3596 typedef_hash (gconstpointer _key
)
3598 const TypeDefUniqueId
*key
= _key
;
3599 return g_str_hash (key
->name
) ^ g_str_hash (key
->name_space
) ^ key
->resolution_scope
; /*XXX better salt the int key*/
3603 typedef_equals (gconstpointer _a
, gconstpointer _b
)
3605 const TypeDefUniqueId
*a
= _a
;
3606 const TypeDefUniqueId
*b
= _b
;
3607 return !strcmp (a
->name
, b
->name
) && !strcmp (a
->name_space
, b
->name_space
) && a
->resolution_scope
== b
->resolution_scope
;
3611 verify_typedef_table_global_constraints (VerifyContext
*ctx
)
3614 guint32 data
[MONO_TYPEDEF_SIZE
];
3615 guint32 nested_data
[MONO_NESTED_CLASS_SIZE
];
3616 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
3617 MonoTableInfo
*nested_table
= &ctx
->image
->tables
[MONO_TABLE_NESTEDCLASS
];
3618 GHashTable
*unique_types
= g_hash_table_new_full (&typedef_hash
, &typedef_equals
, g_free
, NULL
);
3620 for (i
= 0; i
< table
->rows
; ++i
) {
3622 TypeDefUniqueId
*type
= g_new (TypeDefUniqueId
, 1);
3623 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEDEF_SIZE
);
3625 type
->name
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEDEF_NAME
]);
3626 type
->name_space
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEDEF_NAMESPACE
]);
3627 type
->resolution_scope
= 0;
3629 visibility
= data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3630 if (visibility
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visibility
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
) {
3631 int res
= search_sorted_table (ctx
, MONO_TABLE_NESTEDCLASS
, MONO_NESTED_CLASS_NESTED
, i
+ 1);
3632 g_assert (res
>= 0);
3634 mono_metadata_decode_row (nested_table
, res
, nested_data
, MONO_NESTED_CLASS_SIZE
);
3635 type
->resolution_scope
= nested_data
[MONO_NESTED_CLASS_ENCLOSING
];
3638 if (g_hash_table_lookup (unique_types
, type
)) {
3639 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("TypeDef table row %d has duplicate for tuple (%s,%s,%x)", i
, type
->name
, type
->name_space
, type
->resolution_scope
));
3640 g_hash_table_destroy (unique_types
);
3644 g_hash_table_insert (unique_types
, type
, GUINT_TO_POINTER (1));
3647 g_hash_table_destroy (unique_types
);
3651 verify_typeref_table_global_constraints (VerifyContext
*ctx
)
3654 guint32 data
[MONO_TYPEREF_SIZE
];
3655 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEREF
];
3656 GHashTable
*unique_types
= g_hash_table_new_full (&typedef_hash
, &typedef_equals
, g_free
, NULL
);
3658 for (i
= 0; i
< table
->rows
; ++i
) {
3659 TypeDefUniqueId
*type
= g_new (TypeDefUniqueId
, 1);
3660 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEREF_SIZE
);
3662 type
->resolution_scope
= data
[MONO_TYPEREF_SCOPE
];
3663 type
->name
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEREF_NAME
]);
3664 type
->name_space
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEREF_NAMESPACE
]);
3666 if (g_hash_table_lookup (unique_types
, type
)) {
3667 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("TypeRef table row %d has duplicate for tuple (%s,%s,%x)", i
, type
->name
, type
->name_space
, type
->resolution_scope
));
3668 g_hash_table_destroy (unique_types
);
3672 g_hash_table_insert (unique_types
, type
, GUINT_TO_POINTER (1));
3675 g_hash_table_destroy (unique_types
);
3679 verify_tables_data_global_constraints (VerifyContext
*ctx
)
3681 verify_typedef_table_global_constraints (ctx
);
3685 verify_tables_data_global_constraints_full (VerifyContext
*ctx
)
3687 verify_typeref_table_global_constraints (ctx
);
3691 verify_tables_data (VerifyContext
*ctx
)
3693 OffsetAndSize tables_area
= get_metadata_stream (ctx
, &ctx
->image
->heap_tables
);
3694 guint32 size
= 0, tables_offset
;
3697 for (i
= 0; i
< 0x2D; ++i
) {
3698 MonoTableInfo
*table
= &ctx
->image
->tables
[i
];
3700 tmp_size
= size
+ (guint32
)table
->row_size
* (guint32
)table
->rows
;
3701 if (tmp_size
< size
) {
3709 ADD_ERROR (ctx
, g_strdup_printf ("table space is either empty or overflowed"));
3711 tables_offset
= ctx
->image
->tables_base
- ctx
->data
;
3712 if (!bounds_check_offset (&tables_area
, tables_offset
, size
))
3713 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
)));
3715 verify_module_table (ctx
);
3717 verify_typeref_table (ctx
);
3719 verify_typedef_table (ctx
);
3721 verify_field_table (ctx
);
3723 verify_method_table (ctx
);
3725 verify_param_table (ctx
);
3727 verify_interfaceimpl_table (ctx
);
3729 verify_memberref_table (ctx
);
3731 verify_constant_table (ctx
);
3733 verify_cattr_table (ctx
);
3735 verify_field_marshal_table (ctx
);
3737 verify_decl_security_table (ctx
);
3739 verify_class_layout_table (ctx
);
3741 verify_field_layout_table (ctx
);
3743 verify_standalonesig_table (ctx
);
3745 verify_eventmap_table (ctx
);
3747 verify_event_table (ctx
);
3749 verify_propertymap_table (ctx
);
3751 verify_property_table (ctx
);
3753 verify_methodimpl_table (ctx
);
3755 verify_moduleref_table (ctx
);
3757 verify_typespec_table (ctx
);
3759 verify_implmap_table (ctx
);
3761 verify_fieldrva_table (ctx
);
3763 verify_assembly_table (ctx
);
3765 verify_assemblyref_table (ctx
);
3767 verify_file_table (ctx
);
3769 verify_exportedtype_table (ctx
);
3771 verify_manifest_resource_table (ctx
);
3773 verify_nested_class_table (ctx
);
3775 verify_generic_param_table (ctx
);
3777 verify_method_spec_table (ctx
);
3779 verify_generic_param_constraint_table (ctx
);
3781 verify_tables_data_global_constraints (ctx
);
3785 init_verify_context (VerifyContext
*ctx
, MonoImage
*image
, GSList
**error_list
)
3787 memset (ctx
, 0, sizeof (VerifyContext
));
3789 ctx
->report_error
= error_list
!= NULL
;
3790 ctx
->report_warning
= FALSE
; //export this setting in the API
3792 ctx
->size
= image
->raw_data_len
;
3793 ctx
->data
= image
->raw_data
;
3797 cleanup_context (VerifyContext
*ctx
, GSList
**error_list
)
3799 g_free (ctx
->sections
);
3801 *error_list
= ctx
->errors
;
3803 mono_free_verify_list (ctx
->errors
);
3808 mono_verifier_verify_pe_data (MonoImage
*image
, GSList
**error_list
)
3812 if (!mono_verifier_is_enabled_for_image (image
))
3815 init_verify_context (&ctx
, image
, error_list
);
3816 ctx
.stage
= STAGE_PE
;
3818 verify_msdos_header (&ctx
);
3820 verify_pe_header (&ctx
);
3822 verify_pe_optional_header (&ctx
);
3824 load_section_table (&ctx
);
3826 load_data_directories (&ctx
);
3828 verify_import_table (&ctx
);
3830 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3831 verify_resources_table (&ctx
);
3834 return cleanup_context (&ctx
, error_list
);
3838 mono_verifier_verify_cli_data (MonoImage
*image
, GSList
**error_list
)
3842 if (!mono_verifier_is_enabled_for_image (image
))
3845 init_verify_context (&ctx
, image
, error_list
);
3846 ctx
.stage
= STAGE_CLI
;
3848 verify_cli_header (&ctx
);
3850 verify_metadata_header (&ctx
);
3852 verify_tables_schema (&ctx
);
3855 return cleanup_context (&ctx
, error_list
);
3860 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
3861 * Other verification checks are meant to be done lazily by the runtime. Those include:
3862 * blob items (signatures, method headers, custom attributes, etc)
3863 * type semantics related
3865 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
3867 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
3868 * operation still need more checking.
3871 mono_verifier_verify_table_data (MonoImage
*image
, GSList
**error_list
)
3875 if (!mono_verifier_is_enabled_for_image (image
))
3878 init_verify_context (&ctx
, image
, error_list
);
3879 ctx
.stage
= STAGE_TABLES
;
3881 verify_tables_data (&ctx
);
3883 return cleanup_context (&ctx
, error_list
);
3888 * Verifies all other constraints.
3891 mono_verifier_verify_full_table_data (MonoImage
*image
, GSList
**error_list
)
3895 if (!mono_verifier_is_enabled_for_image (image
))
3898 init_verify_context (&ctx
, image
, error_list
);
3899 ctx
.stage
= STAGE_TABLES
;
3901 verify_typedef_table_full (&ctx
);
3903 verify_field_table_full (&ctx
);
3905 verify_method_table_full (&ctx
);
3907 verify_memberref_table_full (&ctx
);
3909 verify_cattr_table_full (&ctx
);
3911 verify_field_marshal_table_full (&ctx
);
3913 verify_decl_security_table_full (&ctx
);
3915 verify_standalonesig_table_full (&ctx
);
3917 verify_event_table_full (&ctx
);
3919 verify_typespec_table_full (&ctx
);
3921 verify_method_spec_table_full (&ctx
);
3923 verify_tables_data_global_constraints_full (&ctx
);
3926 return cleanup_context (&ctx
, error_list
);
3930 mono_verifier_verify_field_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
3934 if (!mono_verifier_is_enabled_for_image (image
))
3937 init_verify_context (&ctx
, image
, error_list
);
3938 ctx
.stage
= STAGE_TABLES
;
3940 is_valid_field_signature (&ctx
, offset
);
3941 return cleanup_context (&ctx
, error_list
);
3945 mono_verifier_verify_method_header (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
3949 if (!mono_verifier_is_enabled_for_image (image
))
3952 init_verify_context (&ctx
, image
, error_list
);
3953 ctx
.stage
= STAGE_TABLES
;
3955 is_valid_method_header (&ctx
, offset
);
3956 return cleanup_context (&ctx
, error_list
);
3960 mono_verifier_verify_method_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
3964 if (!mono_verifier_is_enabled_for_image (image
))
3967 init_verify_context (&ctx
, image
, error_list
);
3968 ctx
.stage
= STAGE_TABLES
;
3970 is_valid_method_signature (&ctx
, offset
);
3971 return cleanup_context (&ctx
, error_list
);
3975 mono_verifier_verify_memberref_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
3979 if (!mono_verifier_is_enabled_for_image (image
))
3982 init_verify_context (&ctx
, image
, error_list
);
3983 ctx
.stage
= STAGE_TABLES
;
3985 is_valid_method_or_field_signature (&ctx
, offset
);
3986 return cleanup_context (&ctx
, error_list
);
3990 mono_verifier_verify_standalone_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
3994 if (!mono_verifier_is_enabled_for_image (image
))
3997 init_verify_context (&ctx
, image
, error_list
);
3998 ctx
.stage
= STAGE_TABLES
;
4000 is_valid_standalonesig_blob (&ctx
, offset
);
4001 return cleanup_context (&ctx
, error_list
);
4005 mono_verifier_verify_typespec_signature (MonoImage
*image
, guint32 offset
, guint32 token
, GSList
**error_list
)
4009 if (!mono_verifier_is_enabled_for_image (image
))
4012 init_verify_context (&ctx
, image
, error_list
);
4013 ctx
.stage
= STAGE_TABLES
;
4016 is_valid_typespec_blob (&ctx
, offset
);
4017 return cleanup_context (&ctx
, error_list
);
4021 mono_verifier_verify_methodspec_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4025 if (!mono_verifier_is_enabled_for_image (image
))
4028 init_verify_context (&ctx
, image
, error_list
);
4029 ctx
.stage
= STAGE_TABLES
;
4031 is_valid_methodspec_blob (&ctx
, offset
);
4032 return cleanup_context (&ctx
, error_list
);
4036 verify_user_string (VerifyContext
*ctx
, guint32 offset
)
4038 OffsetAndSize heap_us
= get_metadata_stream (ctx
, &ctx
->image
->heap_us
);
4039 guint32 entry_size
, bytes
;
4041 if (heap_us
.size
< offset
)
4042 ADD_ERROR (ctx
, g_strdup ("User string offset beyond heap_us size"));
4044 if (!decode_value (ctx
->data
+ offset
+ heap_us
.offset
, heap_us
.size
- heap_us
.offset
, &entry_size
, &bytes
))
4045 ADD_ERROR (ctx
, g_strdup ("Could not decode user string blob size"));
4047 if (CHECK_ADD4_OVERFLOW_UN (entry_size
, bytes
))
4048 ADD_ERROR (ctx
, g_strdup ("User string size overflow"));
4050 entry_size
+= bytes
;
4052 if (ADD_IS_GREATER_OR_OVF (offset
, entry_size
, heap_us
.size
))
4053 ADD_ERROR (ctx
, g_strdup ("User string oveflow heap_us"));
4057 mono_verifier_verify_string_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4061 if (!mono_verifier_is_enabled_for_image (image
))
4064 init_verify_context (&ctx
, image
, error_list
);
4065 ctx
.stage
= STAGE_TABLES
;
4067 verify_user_string (&ctx
, offset
);
4069 return cleanup_context (&ctx
, error_list
);
4073 mono_verifier_verify_cattr_blob (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4077 if (!mono_verifier_is_enabled_for_image (image
))
4080 init_verify_context (&ctx
, image
, error_list
);
4081 ctx
.stage
= STAGE_TABLES
;
4083 is_valid_cattr_blob (&ctx
, offset
);
4085 return cleanup_context (&ctx
, error_list
);
4089 mono_verifier_verify_cattr_content (MonoImage
*image
, MonoMethod
*ctor
, const guchar
*data
, guint32 size
, GSList
**error_list
)
4093 if (!mono_verifier_is_enabled_for_image (image
))
4096 init_verify_context (&ctx
, image
, error_list
);
4097 ctx
.stage
= STAGE_TABLES
;
4099 is_valid_cattr_content (&ctx
, ctor
, (const char*)data
, size
);
4101 return cleanup_context (&ctx
, error_list
);
4105 mono_verifier_is_sig_compatible (MonoImage
*image
, MonoMethod
*method
, MonoMethodSignature
*signature
)
4107 MonoMethodSignature
*original_sig
;
4108 if (!mono_verifier_is_enabled_for_image (image
))
4111 original_sig
= mono_method_signature (method
);
4112 if (original_sig
->call_convention
== MONO_CALL_VARARG
) {
4113 if (original_sig
->hasthis
!= signature
->hasthis
)
4115 if (original_sig
->call_convention
!= signature
->call_convention
)
4117 if (original_sig
->explicit_this
!= signature
->explicit_this
)
4119 if (original_sig
->call_convention
!= signature
->call_convention
)
4121 if (original_sig
->pinvoke
!= signature
->pinvoke
)
4123 if (original_sig
->sentinelpos
!= signature
->sentinelpos
)
4125 } else if (!mono_metadata_signature_equal (signature
, original_sig
)) {
4134 mono_verifier_verify_table_data (MonoImage
*image
, GSList
**error_list
)
4140 mono_verifier_verify_cli_data (MonoImage
*image
, GSList
**error_list
)
4146 mono_verifier_verify_pe_data (MonoImage
*image
, GSList
**error_list
)
4152 mono_verifier_verify_full_table_data (MonoImage
*image
, GSList
**error_list
)
4158 mono_verifier_verify_field_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4164 mono_verifier_verify_method_header (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4170 mono_verifier_verify_method_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4176 mono_verifier_verify_memberref_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4182 mono_verifier_verify_standalone_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4188 mono_verifier_verify_typespec_signature (MonoImage
*image
, guint32 offset
, guint32 token
, GSList
**error_list
)
4194 mono_verifier_verify_methodspec_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4200 mono_verifier_verify_string_signature (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4206 mono_verifier_verify_cattr_blob (MonoImage
*image
, guint32 offset
, GSList
**error_list
)
4212 mono_verifier_verify_cattr_content (MonoImage
*image
, MonoMethod
*ctor
, const guchar
*data
, guint32 size
, GSList
**error_list
)
4218 mono_verifier_is_sig_compatible (MonoImage
*image
, MonoMethod
*method
, MonoMethodSignature
*signature
)
4224 #endif /* DISABLE_VERIFIER */