3 * Metadata verfication support
6 * Mono Project (http://www.mono-project.com)
8 * Copyright (C) 2005-2008 Novell, Inc. (http://www.novell.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include <mono/metadata/exception-internals.h>
13 #include <mono/metadata/object-internals.h>
14 #include <mono/metadata/verify.h>
15 #include <mono/metadata/verify-internals.h>
16 #include <mono/metadata/opcodes.h>
17 #include <mono/metadata/tabledefs.h>
18 #include <mono/metadata/reflection.h>
19 #include <mono/metadata/reflection-internals.h>
20 #include <mono/metadata/debug-helpers.h>
21 #include <mono/metadata/mono-endian.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/metadata-internals.h>
24 #include <mono/metadata/class-internals.h>
25 #include <mono/metadata/class-init.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/security-manager.h>
28 #include <mono/metadata/security-core-clr.h>
29 #include <mono/metadata/cil-coff.h>
30 #include <mono/metadata/attrdefs.h>
31 #include <mono/utils/strenc.h>
32 #include <mono/utils/mono-error-internals.h>
33 #include <mono/utils/bsearch.h>
38 #ifndef DISABLE_VERIFIER
40 TODO add fail fast mode
41 TODO verify the entry point RVA and content.
42 TODO add section relocation support
43 TODO verify the relocation table, since we really don't use, no need so far.
44 TODO do full PECOFF resources verification
45 TODO verify in the CLI header entry point and resources
46 TODO implement null token typeref validation
47 TODO verify table wide invariants for typedef (sorting and uniqueness)
48 TODO implement proper authenticode data directory validation
49 TODO verify properties that require multiple tables to be valid
50 FIXME use subtraction based bounds checking to avoid overflows
51 FIXME get rid of metadata_streams and other fields from VerifyContext
54 #ifdef MONO_VERIFIER_DEBUG
55 #define VERIFIER_DEBUG(code) do { code; } while (0)
57 #define VERIFIER_DEBUG(code)
60 #define INVALID_OFFSET ((guint32)-1)
61 #define INVALID_ADDRESS 0xffffffff
71 RESOURCE_TABLE_IDX
= 2,
72 CERTIFICATE_TABLE_IDX
= 4,
73 RELOCATION_TABLE_IDX
= 5,
87 #define INVALID_TABLE (0xFF)
88 /*format: number of bits, number of tables, tables{n. tables} */
89 const static unsigned char coded_index_desc
[] = {
90 #define TYPEDEF_OR_REF_DESC (0)
97 #define HAS_CONSTANT_DESC (TYPEDEF_OR_REF_DESC + 5)
104 #define HAS_CATTR_DESC (HAS_CONSTANT_DESC + 5)
112 MONO_TABLE_INTERFACEIMPL
,
113 MONO_TABLE_MEMBERREF
,
115 MONO_TABLE_DECLSECURITY
,
118 MONO_TABLE_STANDALONESIG
,
119 MONO_TABLE_MODULEREF
,
122 MONO_TABLE_ASSEMBLYREF
,
124 MONO_TABLE_EXPORTEDTYPE
,
125 MONO_TABLE_MANIFESTRESOURCE
,
126 MONO_TABLE_GENERICPARAM
,
128 #define HAS_FIELD_MARSHAL_DESC (HAS_CATTR_DESC + 22)
134 #define HAS_DECL_SECURITY_DESC (HAS_FIELD_MARSHAL_DESC + 4)
141 #define MEMBERREF_PARENT_DESC (HAS_DECL_SECURITY_DESC + 5)
146 MONO_TABLE_MODULEREF
,
150 #define HAS_SEMANTICS_DESC (MEMBERREF_PARENT_DESC + 7)
156 #define METHODDEF_OR_REF_DESC (HAS_SEMANTICS_DESC + 4)
160 MONO_TABLE_MEMBERREF
,
162 #define MEMBER_FORWARDED_DESC (METHODDEF_OR_REF_DESC + 4)
168 #define IMPLEMENTATION_DESC (MEMBER_FORWARDED_DESC + 4)
172 MONO_TABLE_ASSEMBLYREF
,
173 MONO_TABLE_EXPORTEDTYPE
,
175 #define CATTR_TYPE_DESC (IMPLEMENTATION_DESC + 5)
181 MONO_TABLE_MEMBERREF
,
184 #define RES_SCOPE_DESC (CATTR_TYPE_DESC + 7)
188 MONO_TABLE_MODULEREF
,
189 MONO_TABLE_ASSEMBLYREF
,
192 #define TYPE_OR_METHODDEF_DESC (RES_SCOPE_DESC + 6)
202 guint32 translated_offset
;
214 guint32 rellocationsRVA
;
215 guint16 numberOfRelocations
;
230 gboolean report_error
;
231 gboolean report_warning
;
234 // Mono really only requires 15 here, but verifies the extra is zeroed.
235 DataDirectory data_directories
[16];
236 guint32 section_count
;
237 SectionHeader
*sections
;
238 guint pe64
; // short name for PE32+; actual PE64 proposal was rejected
240 OffsetAndSize metadata_streams
[5]; //offset from begin of the image
243 #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
245 MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
246 vinfo->info.status = __status; \
247 vinfo->info.message = ( __msg); \
248 vinfo->exception_type = (__exception); \
249 (__ctx)->errors = g_slist_prepend ((__ctx)->errors, vinfo); \
252 #define ADD_WARNING(__ctx, __msg) \
254 if ((__ctx)->report_warning) { \
255 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_WARNING, MONO_EXCEPTION_INVALID_PROGRAM); \
256 (__ctx)->valid = 0; \
261 #define ADD_ERROR_NO_RETURN(__ctx, __msg) \
263 if ((__ctx)->report_error) \
264 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
265 (__ctx)->valid = 0; \
268 #define ADD_ERROR(__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 FAIL(__ctx, __msg) \
278 if ((__ctx)->report_error) \
279 ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
280 (__ctx)->valid = 0; \
284 #define CHECK_STATE() do { if (!ctx.valid) goto cleanup; } while (0)
286 #define CHECK_ERROR() do { if (!ctx->valid) return; } while (0)
288 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
289 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
291 #if SIZEOF_VOID_P == 4
292 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
294 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
297 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
298 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
301 dword_align (const char *ptr
)
303 #if SIZEOF_VOID_P == 8
304 return (const char *) (((guint64
) (ptr
+ 3)) & ~3);
306 return (const char *) (((guint32
) (ptr
+ 3)) & ~3);
311 add_from_mono_error (VerifyContext
*ctx
, MonoError
*error
)
313 if (mono_error_ok (error
))
316 ADD_ERROR (ctx
, g_strdup (mono_error_get_message (error
)));
317 mono_error_cleanup (error
);
321 pe_signature_offset (VerifyContext
*ctx
)
323 return read32 (ctx
->data
+ 0x3c);
327 pe_header_offset (VerifyContext
*ctx
)
329 return read32 (ctx
->data
+ 0x3c) + 4;
333 bounds_check_virtual_address (VerifyContext
*ctx
, guint32 rva
, guint32 size
)
337 if (rva
+ size
< rva
) //overflow
340 if (ctx
->stage
> STAGE_PE
) {
341 MonoCLIImageInfo
*iinfo
= ctx
->image
->image_info
;
342 const int top
= iinfo
->cli_section_count
;
343 MonoSectionTable
*tables
= iinfo
->cli_section_tables
;
346 for (i
= 0; i
< top
; i
++) {
347 guint32 base
= tables
->st_virtual_address
;
348 guint32 end
= base
+ tables
->st_raw_data_size
;
350 if (rva
>= base
&& rva
+ size
<= end
)
353 /*if ((addr >= tables->st_virtual_address) &&
354 (addr < tables->st_virtual_address + tables->st_raw_data_size)){
356 return addr - tables->st_virtual_address + tables->st_raw_data_ptr;
366 for (i
= 0; i
< ctx
->section_count
; ++i
) {
367 guint32 base
= ctx
->sections
[i
].baseRVA
;
368 guint32 end
= ctx
->sections
[i
].baseRVA
+ ctx
->sections
[i
].size
;
369 if (rva
>= base
&& rva
+ size
<= end
)
376 bounds_check_datadir (DataDirectory
*dir
, guint32 offset
, guint32 size
)
378 if (dir
->translated_offset
> offset
)
380 if (dir
->size
< size
)
382 return offset
+ size
<= dir
->translated_offset
+ dir
->size
;
386 bounds_check_offset (OffsetAndSize
*off
, guint32 offset
, guint32 size
)
388 if (off
->offset
> offset
)
391 if (off
->size
< size
)
394 return offset
+ size
<= off
->offset
+ off
->size
;
398 translate_rva (VerifyContext
*ctx
, guint32 rva
)
402 if (ctx
->stage
> STAGE_PE
)
403 return mono_cli_rva_image_map (ctx
->image
, rva
);
408 for (i
= 0; i
< ctx
->section_count
; ++i
) {
409 guint32 base
= ctx
->sections
[i
].baseRVA
;
410 guint32 end
= ctx
->sections
[i
].baseRVA
+ ctx
->sections
[i
].size
;
411 if (rva
>= base
&& rva
<= end
) {
412 guint32 res
= (rva
- base
) + ctx
->sections
[i
].baseOffset
;
414 return res
>= ctx
->size
? INVALID_OFFSET
: res
;
418 return INVALID_OFFSET
;
422 verify_msdos_header (VerifyContext
*ctx
)
426 ADD_ERROR (ctx
, g_strdup ("Not enough space for the MS-DOS header"));
427 if (ctx
->data
[0] != 0x4d || ctx
->data
[1] != 0x5a)
428 ADD_ERROR (ctx
, g_strdup ("Invalid MS-DOS watermark"));
429 lfanew
= pe_signature_offset (ctx
);
430 if (lfanew
> ctx
->size
- 4)
431 ADD_ERROR (ctx
, g_strdup ("MS-DOS lfanew offset points to outside of the file"));
435 verify_pe_header (VerifyContext
*ctx
)
437 guint32 offset
= pe_signature_offset (ctx
);
438 const char *pe_header
= ctx
->data
+ offset
;
439 if (pe_header
[0] != 'P' || pe_header
[1] != 'E' ||pe_header
[2] != 0 ||pe_header
[3] != 0)
440 ADD_ERROR (ctx
, g_strdup ("Invalid PE header watermark"));
444 if (offset
> ctx
->size
- 20)
445 ADD_ERROR (ctx
, g_strdup ("File with truncated pe header"));
449 verify_pe_optional_header (VerifyContext
*ctx
)
451 guint32 offset
= pe_header_offset (ctx
);
452 guint32 header_size
, file_alignment
;
453 const char *pe_header
= ctx
->data
+ offset
;
454 const char *pe_optional_header
= pe_header
+ 20;
456 header_size
= read16 (pe_header
+ 16);
459 if (header_size
< 2) /*must be at least 2 or we won't be able to read magic*/
460 ADD_ERROR (ctx
, g_strdup ("Invalid PE optional header size"));
462 if (offset
> ctx
->size
- header_size
|| header_size
> ctx
->size
)
463 ADD_ERROR (ctx
, g_strdup ("Invalid PE optional header size"));
465 const guint16 magic
= read16 (pe_optional_header
);
467 if (magic
== 0x20B) {
468 // Some fields are the same location for PE32 and PE32+.
469 // A few are offset by 4, 8, or 12, but we do not use them.
470 // Others are offset by 16.
473 } else if (magic
!= 0x10b)
474 ADD_ERROR (ctx
, g_strdup_printf ("Invalid optional header magic %d", magic
));
476 // Much of this is over-verification.
478 // File align and section align do not matter to Mono.
480 // Mono requires at least 15 data directories. More than that are ignored,
481 // except to require zeros in the 16th.
483 // Mono requires at least 216 (or pe64:232) size.
485 /* LAMESPEC MS plays around this value and ignore it during validation
486 if (read32 (pe_optional_header + 28) != 0x400000)
487 ADD_ERROR (ctx, g_strdup_printf ("Invalid Image base %x", read32 (pe_optional_header + 28)));*/
488 if (read32 (pe_optional_header
+ 32) != 0x2000)
489 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Section Aligmnent %x", read32 (pe_optional_header
+ 32)));
490 file_alignment
= read32 (pe_optional_header
+ 36);
491 if (file_alignment
!= 0x200 && file_alignment
!= 0x1000)
492 ADD_ERROR (ctx
, g_strdup_printf ("Invalid file Aligmnent %x", file_alignment
));
493 /* All the junk in the middle is irrelevant, specially for mono. */
495 if (header_size
!= 224 + ctx
->pe64
)
496 ADD_ERROR (ctx
, g_strdup_printf ("Invalid optional header size %d", header_size
));
498 const guint number_of_rvas_and_sizes
= read32 (pe_optional_header
+ 92 + ctx
->pe64
);
500 // Data directories beyond 15 do not matter to mono.
501 if (number_of_rvas_and_sizes
> 0x10)
502 ADD_ERROR (ctx
, g_strdup_printf ("Too many data directories %x", number_of_rvas_and_sizes
));
506 load_section_table (VerifyContext
*ctx
)
509 SectionHeader
*sections
;
510 guint32 offset
= pe_header_offset (ctx
);
511 const char *ptr
= ctx
->data
+ offset
;
512 guint16 num_sections
= ctx
->section_count
= read16 (ptr
+ 2);
514 const guint optional_header_size
= read16 (ptr
+ 16);
515 offset
+= optional_header_size
+ 20;
516 ptr
+= optional_header_size
+ 20;
518 if (num_sections
* 40 > ctx
->size
- offset
)
519 ADD_ERROR (ctx
, g_strdup ("Invalid PE optional header size"));
521 sections
= ctx
->sections
= g_new0 (SectionHeader
, num_sections
);
522 for (i
= 0; i
< num_sections
; ++i
) {
523 sections
[i
].size
= read32 (ptr
+ 8);
524 sections
[i
].baseRVA
= read32 (ptr
+ 12);
525 sections
[i
].baseOffset
= read32 (ptr
+ 20);
526 sections
[i
].rellocationsRVA
= read32 (ptr
+ 24);
527 sections
[i
].numberOfRelocations
= read16 (ptr
+ 32);
531 ptr
= ctx
->data
+ offset
; /*reset it to the beggining*/
532 for (i
= 0; i
< num_sections
; ++i
) {
533 guint32 raw_size
, flags
;
534 if (sections
[i
].baseOffset
== 0)
535 ADD_ERROR (ctx
, g_strdup ("Metadata verifier doesn't handle sections with intialized data only"));
536 if (sections
[i
].baseOffset
>= ctx
->size
)
537 ADD_ERROR (ctx
, g_strdup_printf ("Invalid PointerToRawData %x points beyond EOF", sections
[i
].baseOffset
));
538 if (sections
[i
].size
> ctx
->size
- sections
[i
].baseOffset
)
539 ADD_ERROR (ctx
, g_strdup ("Invalid VirtualSize points beyond EOF"));
541 raw_size
= read32 (ptr
+ 16);
542 if (raw_size
< sections
[i
].size
)
543 ADD_ERROR (ctx
, g_strdup ("Metadata verifier doesn't handle sections with SizeOfRawData < VirtualSize"));
545 if (raw_size
> ctx
->size
- sections
[i
].baseOffset
)
546 ADD_ERROR (ctx
, g_strdup_printf ("Invalid SizeOfRawData %x points beyond EOF", raw_size
));
548 if (sections
[i
].rellocationsRVA
|| sections
[i
].numberOfRelocations
)
549 ADD_ERROR (ctx
, g_strdup_printf ("Metadata verifier doesn't handle section relocation"));
551 flags
= read32 (ptr
+ 36);
552 /*TODO 0xFE0000E0 is all flags from cil-coff.h OR'd. Make it a less magical number*/
553 if (flags
== 0 || (flags
& ~0xFE0000E0) != 0)
554 ADD_ERROR (ctx
, g_strdup_printf ("Invalid section flags %x", flags
));
561 is_valid_data_directory (int i
)
563 /*LAMESPEC 4 == certificate 6 == debug, MS uses both*/
564 return i
== 1 || i
== 2 || i
== 5 || i
== 12 || i
== 14 || i
== 4 || i
== 6;
568 load_data_directories (VerifyContext
*ctx
)
570 guint32 offset
= pe_header_offset (ctx
) + 116 + ctx
->pe64
;
571 const char *ptr
= ctx
->data
+ offset
;
574 for (i
= 0; i
< 16; ++i
, ptr
+= 8) {
575 guint32 rva
= read32 (ptr
);
576 guint32 size
= read32 (ptr
+ 4);
578 /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
579 if (i
== CERTIFICATE_TABLE_IDX
)
582 if ((rva
!= 0 || size
!= 0) && !is_valid_data_directory (i
))
583 ADD_ERROR (ctx
, g_strdup_printf ("Invalid data directory %d", i
));
585 if (rva
!= 0 && !bounds_check_virtual_address (ctx
, rva
, size
))
586 ADD_ERROR (ctx
, g_strdup_printf ("Invalid data directory %d rva/size pair %x/%x", i
, rva
, size
));
588 ctx
->data_directories
[i
].rva
= rva
;
589 ctx
->data_directories
[i
].size
= size
;
590 ctx
->data_directories
[i
].translated_offset
= translate_rva (ctx
, rva
);
594 #define SIZE_OF_MSCOREE (sizeof ("mscoree.dll"))
596 #define SIZE_OF_CORMAIN (sizeof ("_CorExeMain"))
599 verify_hint_name_table (VerifyContext
*ctx
, guint32 import_rva
, const char *table_name
)
602 guint32 hint_table_rva
;
604 import_rva
= translate_rva (ctx
, import_rva
);
605 g_assert (import_rva
!= INVALID_OFFSET
);
607 hint_table_rva
= read32 (ctx
->data
+ import_rva
);
608 if (!bounds_check_virtual_address (ctx
, hint_table_rva
, SIZE_OF_CORMAIN
+ 2))
609 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Hint/Name rva %d for %s", hint_table_rva
, table_name
));
611 hint_table_rva
= translate_rva (ctx
, hint_table_rva
);
612 g_assert (hint_table_rva
!= INVALID_OFFSET
);
613 ptr
= ctx
->data
+ hint_table_rva
+ 2;
615 if (memcmp ("_CorExeMain", ptr
, SIZE_OF_CORMAIN
) && memcmp ("_CorDllMain", ptr
, SIZE_OF_CORMAIN
))
616 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Hint / Name: '%s'", ptr
));
620 verify_import_table (VerifyContext
*ctx
)
622 DataDirectory it
= ctx
->data_directories
[IMPORT_TABLE_IDX
];
623 guint32 offset
= it
.translated_offset
;
624 const char *ptr
= ctx
->data
+ offset
;
625 guint32 name_rva
, ilt_rva
, iat_rva
;
627 g_assert (offset
!= INVALID_OFFSET
);
630 ADD_ERROR (ctx
, g_strdup_printf ("Import table size %d is smaller than 40", it
.size
));
632 ilt_rva
= read32 (ptr
);
633 if (ilt_rva
&& !bounds_check_virtual_address (ctx
, ilt_rva
, 8))
634 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Lookup Table rva %x", ilt_rva
));
636 name_rva
= read32 (ptr
+ 12);
637 if (name_rva
&& !bounds_check_virtual_address (ctx
, name_rva
, SIZE_OF_MSCOREE
))
638 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Table Name rva %x", name_rva
));
640 iat_rva
= read32 (ptr
+ 16);
642 if (!bounds_check_virtual_address (ctx
, iat_rva
, 8))
643 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Address Table rva %x", iat_rva
));
645 if (iat_rva
!= ctx
->data_directories
[IAT_IDX
].rva
)
646 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
));
650 name_rva
= translate_rva (ctx
, name_rva
);
651 g_assert (name_rva
!= INVALID_OFFSET
);
652 ptr
= ctx
->data
+ name_rva
;
654 if (memcmp ("mscoree.dll", ptr
, SIZE_OF_MSCOREE
))
655 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Import Table Name: '%s'", ptr
));
659 verify_hint_name_table (ctx
, ilt_rva
, "Import Lookup Table");
664 verify_hint_name_table (ctx
, iat_rva
, "Import Address Table");
668 verify_resources_table (VerifyContext
*ctx
)
670 DataDirectory it
= ctx
->data_directories
[RESOURCE_TABLE_IDX
];
672 guint16 named_entries
, id_entries
;
679 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
));
681 offset
= it
.translated_offset
;
682 ptr
= ctx
->data
+ offset
;
684 g_assert (offset
!= INVALID_OFFSET
);
686 named_entries
= read16 (ptr
+ 12);
687 id_entries
= read16 (ptr
+ 14);
689 if ((named_entries
+ id_entries
) * 8 + 16 > it
.size
)
690 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
));
692 /* XXX at least one unmanaged resource is added due to a call to AssemblyBuilder::DefineVersionInfoResource ()
693 if (named_entries || id_entries)
694 ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support full verification of PECOFF resources"));
698 /*----------nothing from here on can use data_directory---*/
701 get_data_dir (VerifyContext
*ctx
, int idx
)
703 MonoCLIImageInfo
*iinfo
= ctx
->image
->image_info
;
704 MonoPEDirEntry
*entry
= &iinfo
->cli_header
.datadir
.pe_export_table
;
708 res
.rva
= entry
->rva
;
709 res
.size
= entry
->size
;
710 res
.translated_offset
= translate_rva (ctx
, res
.rva
);
715 verify_cli_header (VerifyContext
*ctx
)
717 DataDirectory it
= get_data_dir (ctx
, CLI_HEADER_IDX
);
723 ADD_ERROR (ctx
, g_strdup_printf ("CLI header missing"));
726 ADD_ERROR (ctx
, g_strdup_printf ("Invalid cli header size in data directory %d must be 72", it
.size
));
728 offset
= it
.translated_offset
;
729 ptr
= ctx
->data
+ offset
;
731 g_assert (offset
!= INVALID_OFFSET
);
733 if (read16 (ptr
) != 72)
734 ADD_ERROR (ctx
, g_strdup_printf ("Invalid cli header size %d must be 72", read16 (ptr
)));
736 if (!bounds_check_virtual_address (ctx
, read32 (ptr
+ 8), read32 (ptr
+ 12)))
737 ADD_ERROR (ctx
, g_strdup_printf ("Invalid medatata section rva/size pair %x/%x", read32 (ptr
+ 8), read32 (ptr
+ 12)));
740 if (!read32 (ptr
+ 8) || !read32 (ptr
+ 12))
741 ADD_ERROR (ctx
, g_strdup_printf ("Missing medatata section in the CLI header"));
743 if ((read32 (ptr
+ 16) & ~0x0003000B) != 0)
744 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CLI header flags"));
747 for (i
= 0; i
< 6; ++i
) {
748 guint32 rva
= read32 (ptr
);
749 guint32 size
= read32 (ptr
+ 4);
751 if (rva
!= 0 && !bounds_check_virtual_address (ctx
, rva
, size
))
752 ADD_ERROR (ctx
, g_strdup_printf ("Invalid cli section %i rva/size pair %x/%x", i
, rva
, size
));
757 ADD_ERROR (ctx
, g_strdup_printf ("Metadata verifier doesn't support cli header section %d", i
));
762 pad4 (guint32 offset
)
764 if (offset
& 0x3) //pad to the next 4 byte boundary
765 offset
= (offset
& ~0x3) + 4;
770 verify_metadata_header (VerifyContext
*ctx
)
773 DataDirectory it
= get_data_dir (ctx
, CLI_HEADER_IDX
);
774 guint32 offset
, section_count
;
777 offset
= it
.translated_offset
;
778 ptr
= ctx
->data
+ offset
;
779 g_assert (offset
!= INVALID_OFFSET
);
781 //build a directory entry for the metadata root
783 it
.rva
= read32 (ptr
);
785 it
.size
= read32 (ptr
);
786 it
.translated_offset
= offset
= translate_rva (ctx
, it
.rva
);
788 ptr
= ctx
->data
+ offset
;
789 g_assert (offset
!= INVALID_OFFSET
);
792 ADD_ERROR (ctx
, g_strdup_printf ("Metadata root section is too small %d (at least 20 bytes required for initial decoding)", it
.size
));
794 if (read32 (ptr
) != 0x424A5342)
795 ADD_ERROR (ctx
, g_strdup_printf ("Invalid metadata signature, expected 0x424A5342 but got %08x", read32 (ptr
)));
797 offset
= pad4 (offset
+ 16 + read32 (ptr
+ 12));
799 if (!bounds_check_datadir (&it
, offset
, 4))
800 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
));
802 ptr
= ctx
->data
+ offset
; //move to streams header
804 section_count
= read16 (ptr
+ 2);
805 if (section_count
< 2)
806 ADD_ERROR (ctx
, g_strdup_printf ("Metadata root section must have at least 2 streams (#~ and #GUID)"));
811 for (i
= 0; i
< section_count
; ++i
) {
812 guint32 stream_off
, stream_size
;
813 int string_size
, stream_idx
;
815 if (!bounds_check_datadir (&it
, offset
, 8))
816 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
));
818 stream_off
= it
.translated_offset
+ read32 (ptr
);
819 stream_size
= read32 (ptr
+ 4);
821 if (!bounds_check_datadir (&it
, stream_off
, stream_size
))
822 ADD_ERROR (ctx
, g_strdup_printf ("Invalid stream header %d offset/size pair %x/%x", 0, stream_off
, stream_size
));
827 for (string_size
= 0; string_size
< 32; ++string_size
) {
828 if (!bounds_check_datadir (&it
, offset
++, 1))
829 ADD_ERROR (ctx
, g_strdup_printf ("Metadata root section is too small to decode stream header %d name", i
));
830 if (!ptr
[string_size
])
834 if (ptr
[string_size
])
835 ADD_ERROR (ctx
, g_strdup_printf ("Metadata stream header %d name larger than 32 bytes", i
));
837 if (!strncmp ("#Strings", ptr
, 9))
838 stream_idx
= STRINGS_STREAM
;
839 else if (!strncmp ("#US", ptr
, 4))
840 stream_idx
= USER_STRINGS_STREAM
;
841 else if (!strncmp ("#Blob", ptr
, 6))
842 stream_idx
= BLOB_STREAM
;
843 else if (!strncmp ("#GUID", ptr
, 6))
844 stream_idx
= GUID_STREAM
;
845 else if (!strncmp ("#~", ptr
, 3))
846 stream_idx
= TILDE_STREAM
;
848 ADD_WARNING (ctx
, g_strdup_printf ("Metadata stream header %d invalid name %s", i
, ptr
));
849 offset
= pad4 (offset
);
850 ptr
= ctx
->data
+ offset
;
854 if (ctx
->metadata_streams
[stream_idx
].offset
!= 0)
855 ADD_ERROR (ctx
, g_strdup_printf ("Duplicated metadata stream header %s", ptr
));
857 ctx
->metadata_streams
[stream_idx
].offset
= stream_off
;
858 ctx
->metadata_streams
[stream_idx
].size
= stream_size
;
860 offset
= pad4 (offset
);
861 ptr
= ctx
->data
+ offset
;
864 if (!ctx
->metadata_streams
[TILDE_STREAM
].size
)
865 ADD_ERROR (ctx
, g_strdup_printf ("Metadata #~ stream missing"));
866 if (!ctx
->metadata_streams
[GUID_STREAM
].size
)
867 ADD_ERROR (ctx
, g_strdup_printf ("Metadata guid stream missing"));
871 verify_tables_schema (VerifyContext
*ctx
)
873 OffsetAndSize tables_area
= ctx
->metadata_streams
[TILDE_STREAM
];
874 unsigned offset
= tables_area
.offset
;
875 const char *ptr
= ctx
->data
+ offset
;
876 guint64 valid_tables
;
880 if (tables_area
.size
< 24)
881 ADD_ERROR (ctx
, g_strdup_printf ("Table schemata size (%d) too small to for initial decoding (requires 24 bytes)", tables_area
.size
));
883 if (ptr
[4] != 2 && ptr
[4] != 1)
884 ADD_ERROR (ctx
, g_strdup_printf ("Invalid table schemata major version %d, expected 2", ptr
[4]));
886 ADD_ERROR (ctx
, g_strdup_printf ("Invalid table schemata minor version %d, expected 0", ptr
[5]));
888 if ((ptr
[6] & ~0x7) != 0)
889 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]));
891 valid_tables
= read64 (ptr
+ 8);
893 for (i
= 0; i
< 64; ++i
) {
894 if (!(valid_tables
& ((guint64
)1 << i
)))
897 /*MS Extensions: 0x3 0x5 0x7 0x13 0x16
898 Unused: 0x1E 0x1F 0x2D-0x3F
899 We don't care about the MS extensions.*/
900 if (i
== 0x3 || i
== 0x5 || i
== 0x7 || i
== 0x13 || i
== 0x16)
901 ADD_ERROR (ctx
, g_strdup_printf ("The metadata verifier doesn't support MS specific table %x", i
));
902 if (i
== 0x1E || i
== 0x1F || i
>= 0x2D)
903 ADD_ERROR (ctx
, g_strdup_printf ("Invalid table %x", i
));
907 if (tables_area
.size
< 24 + count
* 4)
908 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));
911 for (i
= 0; i
< 64; ++i
) {
912 if (valid_tables
& ((guint64
)1 << i
)) {
913 guint32 row_count
= read32 (ptr
);
914 if (row_count
> (1 << 24) - 1)
915 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Table %d row count: %d. Mono only supports 16777215 rows", i
, row_count
));
921 /*----------nothing from here on can use data_directory or metadata_streams ---*/
924 get_col_offset (VerifyContext
*ctx
, int table
, int column
)
926 guint32 bitfield
= ctx
->image
->tables
[table
].size_bitfield
;
930 offset
+= mono_metadata_table_size (bitfield
, column
);
936 get_col_size (VerifyContext
*ctx
, int table
, int column
)
938 return mono_metadata_table_size (ctx
->image
->tables
[table
].size_bitfield
, column
);
942 get_metadata_stream (VerifyContext
*ctx
, MonoStreamHeader
*header
)
945 res
.offset
= header
->data
- ctx
->data
;
946 res
.size
= header
->size
;
952 is_valid_string_full_with_image (MonoImage
*image
, guint32 offset
, gboolean allow_empty
)
954 guint32 heap_offset
= (char*)image
->heap_strings
.data
- m_image_get_raw_data (image
);
955 guint32 heap_size
= image
->heap_strings
.size
;
958 const char *data
= m_image_get_raw_data (image
) + heap_offset
;
960 if (offset
>= heap_size
)
962 if (CHECK_ADDP_OVERFLOW_UN (data
, offset
))
965 if (!mono_utf8_validate_and_len_with_bounds (data
+ offset
, heap_size
- offset
, &length
, NULL
))
967 return allow_empty
|| length
> 0;
972 is_valid_string_full (VerifyContext
*ctx
, guint32 offset
, gboolean allow_empty
)
974 return is_valid_string_full_with_image (ctx
->image
, offset
, allow_empty
);
978 is_valid_string (VerifyContext
*ctx
, guint32 offset
)
980 return is_valid_string_full (ctx
, offset
, TRUE
);
984 is_valid_non_empty_string (VerifyContext
*ctx
, guint32 offset
)
986 return is_valid_string_full (ctx
, offset
, FALSE
);
990 is_valid_guid (VerifyContext
*ctx
, guint32 offset
)
992 OffsetAndSize guids
= get_metadata_stream (ctx
, &ctx
->image
->heap_guid
);
993 return guids
.size
>= 8 && guids
.size
- 8 >= offset
;
997 get_coded_index_token (int token_kind
, guint32 coded_token
)
999 guint32 bits
= coded_index_desc
[token_kind
];
1000 return coded_token
>> bits
;
1004 get_coded_index_table (int kind
, guint32 coded_token
)
1006 guint32 idx
, bits
= coded_index_desc
[kind
];
1008 idx
= coded_token
& ((1 << bits
) - 1);
1009 return coded_index_desc
[kind
+ idx
];
1013 make_coded_token (int kind
, guint32 table
, guint32 table_idx
)
1015 guint32 bits
= coded_index_desc
[kind
++];
1016 guint32 tables
= coded_index_desc
[kind
++];
1018 for (i
= 0; i
< tables
; ++i
) {
1019 if (coded_index_desc
[kind
++] == table
)
1020 return ((table_idx
+ 1) << bits
) | i
;
1022 g_assert_not_reached ();
1027 is_valid_coded_index_with_image (MonoImage
*image
, int token_kind
, guint32 coded_token
)
1029 guint32 bits
= coded_index_desc
[token_kind
++];
1030 guint32 table_count
= coded_index_desc
[token_kind
++];
1031 guint32 table
= coded_token
& ((1 << bits
) - 1);
1032 guint32 token
= coded_token
>> bits
;
1034 if (table
>= table_count
)
1037 /*token_kind points to the first table idx*/
1038 table
= coded_index_desc
[token_kind
+ table
];
1040 if (table
== INVALID_TABLE
)
1042 return token
<= image
->tables
[table
].rows
;
1046 is_valid_coded_index (VerifyContext
*ctx
, int token_kind
, guint32 coded_token
)
1048 return is_valid_coded_index_with_image (ctx
->image
, token_kind
, coded_token
);
1055 MonoTableInfo
*table
;
1059 token_locator (const void *a
, const void *b
)
1061 RowLocator
*loc
= (RowLocator
*)a
;
1062 unsigned const char *row
= (unsigned const char *)b
;
1063 guint32 token
= loc
->col_size
== 2 ? read16 (row
+ loc
->col_offset
) : read32 (row
+ loc
->col_offset
);
1065 VERIFIER_DEBUG ( printf ("\tfound token %x at idx %d\n", token
, ((const char*)row
- loc
->table
->base
) / loc
->table
->row_size
) );
1066 return (int)loc
->token
- (int)token
;
1070 search_sorted_table (VerifyContext
*ctx
, int table
, int column
, guint32 coded_token
)
1072 MonoTableInfo
*tinfo
= &ctx
->image
->tables
[table
];
1074 const char *res
, *base
;
1075 locator
.token
= coded_token
;
1076 locator
.col_offset
= get_col_offset (ctx
, table
, column
);
1077 locator
.col_size
= get_col_size (ctx
, table
, column
);
1078 locator
.table
= tinfo
;
1082 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
) );
1083 res
= (const char *)mono_binary_search (&locator
, base
, tinfo
->rows
, tinfo
->row_size
, token_locator
);
1087 return (res
- base
) / tinfo
->row_size
;
1090 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1092 get_string_ptr (VerifyContext
*ctx
, guint offset
)
1094 return ctx
->image
->heap_strings
.data
+ offset
;
1097 /*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
1099 string_cmp (VerifyContext
*ctx
, const char *str
, guint offset
)
1102 return strcmp (str
, "");
1104 return strcmp (str
, get_string_ptr (ctx
, offset
));
1108 mono_verifier_is_corlib (MonoImage
*image
)
1110 gboolean trusted_location
= !mono_security_core_clr_enabled () ?
1111 TRUE
: mono_security_core_clr_is_platform_image (image
);
1113 return trusted_location
&& image
->module_name
&& !strcmp ("mscorlib.dll", image
->module_name
);
1117 typedef_is_system_object (VerifyContext
*ctx
, guint32
*data
)
1119 return mono_verifier_is_corlib (ctx
->image
) && !string_cmp (ctx
, "System", data
[MONO_TYPEDEF_NAMESPACE
]) && !string_cmp (ctx
, "Object", data
[MONO_TYPEDEF_NAME
]);
1123 decode_value (const char *_ptr
, unsigned available
, unsigned *value
, unsigned *size
)
1126 const unsigned char *ptr
= (const unsigned char *)_ptr
;
1134 if ((b
& 0x80) == 0) {
1137 } else if ((b
& 0x40) == 0) {
1141 *value
= ((b
& 0x3f) << 8 | ptr
[1]);
1146 *value
= ((b
& 0x1f) << 24) |
1156 decode_signature_header (VerifyContext
*ctx
, guint32 offset
, guint32
*size
, const char **first_byte
)
1158 MonoStreamHeader blob
= ctx
->image
->heap_blob
;
1159 guint32 value
, enc_size
;
1161 if (offset
>= blob
.size
)
1164 if (!decode_value (blob
.data
+ offset
, blob
.size
- offset
, &value
, &enc_size
))
1167 if (CHECK_ADD4_OVERFLOW_UN (offset
, enc_size
))
1172 if (ADD_IS_GREATER_OR_OVF (offset
, value
, blob
.size
))
1176 *first_byte
= blob
.data
+ offset
;
1181 safe_read (const char **_ptr
, const char *limit
, unsigned *dest
, int size
)
1183 const char *ptr
= *_ptr
;
1184 if (ptr
+ size
> limit
)
1188 *dest
= *((guint8
*)ptr
);
1192 *dest
= read16 (ptr
);
1196 *dest
= read32 (ptr
);
1205 safe_read_compressed_int (const char **_ptr
, const char *limit
, unsigned *dest
)
1208 const char *ptr
= *_ptr
;
1209 gboolean res
= decode_value (ptr
, limit
- ptr
, dest
, &size
);
1214 #define safe_read8(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 1)
1215 #define safe_read_cint(VAR, PTR, LIMIT) safe_read_compressed_int (&PTR, LIMIT, &VAR)
1216 #define safe_read16(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 2)
1217 #define safe_read32(VAR, PTR, LIMIT) safe_read (&PTR, LIMIT, &VAR, 4)
1220 parse_type (VerifyContext
*ctx
, const char **_ptr
, const char *end
);
1223 parse_method_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
, gboolean allow_sentinel
, gboolean allow_unmanaged
);
1226 parse_custom_mods (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1228 const char *ptr
= *_ptr
;
1233 if (!safe_read8 (type
, ptr
, end
))
1234 FAIL (ctx
, g_strdup ("CustomMod: Not enough room for the type"));
1236 if (type
!= MONO_TYPE_CMOD_REQD
&& type
!= MONO_TYPE_CMOD_OPT
) {
1241 if (!safe_read_cint (token
, ptr
, end
))
1242 FAIL (ctx
, g_strdup ("CustomMod: Not enough room for the token"));
1244 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, token
) || !get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
))
1245 FAIL (ctx
, g_strdup_printf ("CustomMod: invalid TypeDefOrRef token %x", token
));
1253 parse_array_shape (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1255 const char *ptr
= *_ptr
;
1257 unsigned size
, num
, i
;
1259 if (!safe_read8 (val
, ptr
, end
))
1260 FAIL (ctx
, g_strdup ("ArrayShape: Not enough room for Rank"));
1263 FAIL (ctx
, g_strdup ("ArrayShape: Invalid shape with zero Rank"));
1265 if (!safe_read_cint (size
, ptr
, end
))
1266 FAIL (ctx
, g_strdup ("ArrayShape: Not enough room for NumSizes"));
1268 for (i
= 0; i
< size
; ++i
) {
1269 if (!safe_read_cint (num
, ptr
, end
))
1270 FAIL (ctx
, g_strdup_printf ("ArrayShape: Not enough room for Size of rank %d", i
+ 1));
1273 if (!safe_read_cint (size
, ptr
, end
))
1274 FAIL (ctx
, g_strdup ("ArrayShape: Not enough room for NumLoBounds"));
1276 for (i
= 0; i
< size
; ++i
) {
1277 if (!safe_read_cint (num
, ptr
, end
))
1278 FAIL (ctx
, g_strdup_printf ("ArrayShape: Not enough room for LoBound of rank %d", i
+ 1));
1286 parse_generic_inst (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1288 const char *ptr
= *_ptr
;
1290 unsigned count
, token
, i
;
1292 if (!safe_read8 (type
, ptr
, end
))
1293 FAIL (ctx
, g_strdup ("GenericInst: Not enough room for kind"));
1295 if (type
!= MONO_TYPE_CLASS
&& type
!= MONO_TYPE_VALUETYPE
)
1296 FAIL (ctx
, g_strdup_printf ("GenericInst: Invalid GenericInst kind %x\n", type
));
1298 if (!safe_read_cint (token
, ptr
, end
))
1299 FAIL (ctx
, g_strdup ("GenericInst: Not enough room for type token"));
1301 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, token
) || !get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
))
1302 FAIL (ctx
, g_strdup_printf ("GenericInst: invalid TypeDefOrRef token %x", token
));
1305 if (mono_metadata_token_index (ctx
->token
) == get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
) &&
1306 mono_metadata_token_table (ctx
->token
) == get_coded_index_table (TYPEDEF_OR_REF_DESC
, token
))
1307 FAIL (ctx
, g_strdup_printf ("Type: Recurside generic instance specification (%x). A type signature can't reference itself", ctx
->token
));
1310 if (!safe_read_cint (count
, ptr
, end
))
1311 FAIL (ctx
, g_strdup ("GenericInst: Not enough room for argument count"));
1314 FAIL (ctx
, g_strdup ("GenericInst: Zero arguments generic instance"));
1316 for (i
= 0; i
< count
; ++i
) {
1317 if (!parse_custom_mods (ctx
, &ptr
, end
))
1318 FAIL (ctx
, g_strdup ("Type: Failed to parse pointer custom attr"));
1320 if (!parse_type (ctx
, &ptr
, end
))
1321 FAIL (ctx
, g_strdup_printf ("GenericInst: invalid generic argument %d", i
+ 1));
1328 parse_type (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1330 const char *ptr
= *_ptr
;
1334 if (!safe_read8 (type
, ptr
, end
))
1335 FAIL (ctx
, g_strdup ("Type: Not enough room for the type"));
1337 if (!((type
>= MONO_TYPE_BOOLEAN
&& type
<= MONO_TYPE_PTR
) ||
1338 (type
>= MONO_TYPE_VALUETYPE
&& type
<= MONO_TYPE_GENERICINST
) ||
1339 (type
>= MONO_TYPE_I
&& type
<= MONO_TYPE_U
) ||
1340 (type
>= MONO_TYPE_FNPTR
&& type
<= MONO_TYPE_MVAR
)))
1341 FAIL (ctx
, g_strdup_printf ("Type: Invalid type kind %x\n", type
));
1345 if (!parse_custom_mods (ctx
, &ptr
, end
))
1346 FAIL (ctx
, g_strdup ("Type: Failed to parse pointer custom attr"));
1348 if (!safe_read8 (type
, ptr
, end
))
1349 FAIL (ctx
, g_strdup ("Type: Not enough room to parse the pointer type"));
1351 if (type
!= MONO_TYPE_VOID
) {
1353 if (!parse_type (ctx
, &ptr
, end
))
1354 FAIL (ctx
, g_strdup ("Type: Could not parse pointer type"));
1358 case MONO_TYPE_VALUETYPE
:
1359 case MONO_TYPE_CLASS
:
1360 if (!safe_read_cint (token
, ptr
, end
))
1361 FAIL (ctx
, g_strdup ("Type: Not enough room for the type token"));
1363 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, token
) || !get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
))
1364 FAIL (ctx
, g_strdup_printf ("Type: invalid TypeDefOrRef token %x", token
));
1366 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
))
1367 FAIL (ctx
, g_strdup_printf ("Type: zero TypeDefOrRef token %x", token
));
1369 if (mono_metadata_token_index (ctx
->token
) == get_coded_index_token (TYPEDEF_OR_REF_DESC
, token
) &&
1370 mono_metadata_token_table (ctx
->token
) == get_coded_index_table (TYPEDEF_OR_REF_DESC
, token
))
1371 FAIL (ctx
, g_strdup_printf ("Type: Recursive type specification (%x). A type signature can't reference itself", ctx
->token
));
1376 case MONO_TYPE_MVAR
:
1377 if (!safe_read_cint (token
, ptr
, end
))
1378 FAIL (ctx
, g_strdup ("Type: Not enough room for to decode generic argument number"));
1381 case MONO_TYPE_ARRAY
:
1382 if (!parse_type (ctx
, &ptr
, end
))
1383 FAIL (ctx
, g_strdup ("Type: Could not parse array type"));
1384 if (!parse_array_shape (ctx
, &ptr
, end
))
1385 FAIL (ctx
, g_strdup ("Type: Could not parse array shape"));
1388 case MONO_TYPE_GENERICINST
:
1389 if (!parse_generic_inst (ctx
, &ptr
, end
))
1390 FAIL (ctx
, g_strdup ("Type: Could not parse generic inst"));
1393 case MONO_TYPE_FNPTR
:
1394 if (!parse_method_signature (ctx
, &ptr
, end
, TRUE
, TRUE
))
1395 FAIL (ctx
, g_strdup ("Type: Could not parse method pointer signature"));
1398 case MONO_TYPE_SZARRAY
:
1399 if (!parse_custom_mods (ctx
, &ptr
, end
))
1400 FAIL (ctx
, g_strdup ("Type: Failed to parse array element custom attr"));
1401 if (!parse_type (ctx
, &ptr
, end
))
1402 FAIL (ctx
, g_strdup ("Type: Could not parse array type"));
1410 parse_return_type (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1415 if (!parse_custom_mods (ctx
, _ptr
, end
))
1419 if (!safe_read8 (type
, ptr
, end
))
1420 FAIL (ctx
, g_strdup ("ReturnType: Not enough room for the type"));
1422 if (type
== MONO_TYPE_VOID
|| type
== MONO_TYPE_TYPEDBYREF
) {
1427 //it's a byref, update the cursor ptr
1428 if (type
== MONO_TYPE_BYREF
)
1431 return parse_type (ctx
, _ptr
, end
);
1435 parse_param (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1440 if (!parse_custom_mods (ctx
, _ptr
, end
))
1444 if (!safe_read8 (type
, ptr
, end
))
1445 FAIL (ctx
, g_strdup ("Param: Not enough room for the type"));
1447 if (type
== MONO_TYPE_TYPEDBYREF
) {
1452 //it's a byref, update the cursor ptr
1453 if (type
== MONO_TYPE_BYREF
) {
1455 if (!parse_custom_mods (ctx
, _ptr
, end
))
1459 return parse_type (ctx
, _ptr
, end
);
1463 parse_method_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
, gboolean allow_sentinel
, gboolean allow_unmanaged
)
1466 unsigned param_count
= 0, gparam_count
= 0, type
= 0, i
;
1467 const char *ptr
= *_ptr
;
1468 gboolean saw_sentinel
= FALSE
;
1470 if (!safe_read8 (cconv
, ptr
, end
))
1471 FAIL (ctx
, g_strdup ("MethodSig: Not enough room for the call conv"));
1474 FAIL (ctx
, g_strdup ("MethodSig: CallConv has 0x80 set"));
1476 if (allow_unmanaged
) {
1477 if ((cconv
& 0x0F) > MONO_CALL_VARARG
)
1478 FAIL (ctx
, g_strdup_printf ("MethodSig: CallConv is not valid, it's %x", cconv
& 0x0F));
1479 } else if ((cconv
& 0x0F) != MONO_CALL_DEFAULT
&& (cconv
& 0x0F) != MONO_CALL_VARARG
)
1480 FAIL (ctx
, g_strdup_printf ("MethodSig: CallConv is not Default or Vararg, it's %x", cconv
& 0x0F));
1482 if ((cconv
& 0x10) && !safe_read_cint (gparam_count
, ptr
, end
))
1483 FAIL (ctx
, g_strdup ("MethodSig: Not enough room for the generic param count"));
1485 if ((cconv
& 0x10) && gparam_count
== 0)
1486 FAIL (ctx
, g_strdup ("MethodSig: Signature with generics but zero arity"));
1488 if (allow_unmanaged
&& (cconv
& 0x10))
1489 FAIL (ctx
, g_strdup ("MethodSig: Standalone signature with generic params"));
1491 if (!safe_read_cint (param_count
, ptr
, end
))
1492 FAIL (ctx
, g_strdup ("MethodSig: Not enough room for the param count"));
1494 if (!parse_return_type (ctx
, &ptr
, end
))
1495 FAIL (ctx
, g_strdup ("MethodSig: Error parsing return type"));
1497 for (i
= 0; i
< param_count
; ++i
) {
1498 if (allow_sentinel
) {
1499 if (!safe_read8 (type
, ptr
, end
))
1500 FAIL (ctx
, g_strdup_printf ("MethodSig: Not enough room for param %d type", i
));
1502 if (type
== MONO_TYPE_SENTINEL
) {
1503 if ((cconv
& 0x0F) != MONO_CALL_VARARG
)
1504 FAIL (ctx
, g_strdup ("MethodSig: Found sentinel but signature is not vararg"));
1507 FAIL (ctx
, g_strdup ("MethodSig: More than one sentinel type"));
1509 saw_sentinel
= TRUE
;
1515 if (!parse_param (ctx
, &ptr
, end
))
1516 FAIL (ctx
, g_strdup_printf ("MethodSig: Error parsing arg %d", i
));
1524 parse_property_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1528 unsigned param_count
= 0, i
;
1529 const char *ptr
= *_ptr
;
1531 if (!safe_read8 (sig
, ptr
, end
))
1532 FAIL (ctx
, g_strdup ("PropertySig: Not enough room for signature"));
1534 if (sig
!= 0x08 && sig
!= 0x28)
1535 FAIL (ctx
, g_strdup_printf ("PropertySig: Signature is not 0x28 or 0x08: %x", sig
));
1537 if (!safe_read_cint (param_count
, ptr
, end
))
1538 FAIL (ctx
, g_strdup ("PropertySig: Not enough room for the param count"));
1540 if (!parse_custom_mods (ctx
, &ptr
, end
))
1543 if (!safe_read8 (type
, ptr
, end
))
1544 FAIL (ctx
, g_strdup ("PropertySig: Not enough room for the type"));
1546 //check if it's a byref. safe_read8 did update ptr, so we rollback if it's not a byref
1547 if (type
!= MONO_TYPE_BYREF
)
1550 if (!parse_type (ctx
, &ptr
, end
))
1551 FAIL (ctx
, g_strdup ("PropertySig: Could not parse property type"));
1553 for (i
= 0; i
< param_count
; ++i
) {
1554 if (!parse_custom_mods (ctx
, &ptr
, end
))
1555 FAIL (ctx
, g_strdup ("Type: Failed to parse pointer custom attr"));
1556 if (!parse_type (ctx
, &ptr
, end
))
1557 FAIL (ctx
, g_strdup_printf ("PropertySig: Error parsing arg %d", i
));
1565 parse_field (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1567 const char *ptr
= *_ptr
;
1568 unsigned signature
= 0;
1570 if (!safe_read8 (signature
, ptr
, end
))
1571 FAIL (ctx
, g_strdup ("Field: Not enough room for field signature"));
1573 if (signature
!= 0x06)
1574 FAIL (ctx
, g_strdup_printf ("Field: Invalid signature 0x%x, must be 6", signature
));
1576 if (!parse_custom_mods (ctx
, &ptr
, end
))
1579 if (safe_read8 (signature
, ptr
, end
)) {
1580 if (signature
!= MONO_TYPE_BYREF
)
1585 return parse_type (ctx
, _ptr
, end
);
1589 parse_locals_signature (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1592 unsigned locals_count
= 0, i
;
1593 const char *ptr
= *_ptr
;
1595 if (!safe_read8 (sig
, ptr
, end
))
1596 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for signature"));
1599 FAIL (ctx
, g_strdup_printf ("LocalsSig: Signature is not 0x28 or 0x08: %x", sig
));
1601 if (!safe_read_cint (locals_count
, ptr
, end
))
1602 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for the param count"));
1604 /* LAMEIMPL: MS sometimes generates empty local signatures and its verifier is ok with.
1605 if (locals_count == 0)
1606 FAIL (ctx, g_strdup ("LocalsSig: Signature with zero locals"));
1609 for (i
= 0; i
< locals_count
; ++i
) {
1610 if (!safe_read8 (sig
, ptr
, end
))
1611 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for type"));
1613 while (sig
== MONO_TYPE_CMOD_REQD
|| sig
== MONO_TYPE_CMOD_OPT
|| sig
== MONO_TYPE_PINNED
) {
1614 if (sig
!= MONO_TYPE_PINNED
&& !parse_custom_mods (ctx
, &ptr
, end
))
1615 FAIL (ctx
, g_strdup_printf ("LocalsSig: Error parsing local %d", i
));
1616 if (!safe_read8 (sig
, ptr
, end
))
1617 FAIL (ctx
, g_strdup ("LocalsSig: Not enough room for type"));
1620 if (sig
== MONO_TYPE_BYREF
) {
1621 if (!safe_read8 (sig
, ptr
, end
))
1622 FAIL (ctx
, g_strdup_printf ("Type: Not enough room for byref type for local %d", i
));
1623 if (sig
== MONO_TYPE_TYPEDBYREF
)
1624 FAIL (ctx
, g_strdup_printf ("Type: Invalid type typedref& for local %d", i
));
1627 if (sig
== MONO_TYPE_TYPEDBYREF
)
1632 if (!parse_type (ctx
, &ptr
, end
))
1633 FAIL (ctx
, g_strdup_printf ("LocalsSig: Error parsing local %d", i
));
1641 is_valid_field_signature (VerifyContext
*ctx
, guint32 offset
)
1644 unsigned signature
= 0;
1645 const char *ptr
= NULL
, *end
;
1647 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1648 FAIL (ctx
, g_strdup ("FieldSig: Could not decode signature header"));
1651 if (!safe_read8 (signature
, ptr
, end
))
1652 FAIL (ctx
, g_strdup ("FieldSig: Not enough room for the signature"));
1655 FAIL (ctx
, g_strdup_printf ("FieldSig: Invalid signature %x", signature
));
1658 return parse_field (ctx
, &ptr
, end
);
1662 is_valid_method_signature (VerifyContext
*ctx
, guint32 offset
)
1665 const char *ptr
= NULL
, *end
;
1667 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1668 FAIL (ctx
, g_strdup ("MethodSig: Could not decode signature header"));
1671 return parse_method_signature (ctx
, &ptr
, end
, FALSE
, FALSE
);
1675 is_valid_memberref_method_signature (VerifyContext
*ctx
, guint32 offset
)
1678 const char *ptr
= NULL
, *end
;
1680 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1681 FAIL (ctx
, g_strdup ("MemberRefSig: Could not decode signature header"));
1684 return parse_method_signature (ctx
, &ptr
, end
, TRUE
, FALSE
);
1689 is_valid_method_or_field_signature (VerifyContext
*ctx
, guint32 offset
)
1692 unsigned signature
= 0;
1693 const char *ptr
= NULL
, *end
;
1695 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1696 FAIL (ctx
, g_strdup ("MemberRefSig: Could not decode signature header"));
1699 if (!safe_read8 (signature
, ptr
, end
))
1700 FAIL (ctx
, g_strdup ("MemberRefSig: Not enough room for the call conv"));
1703 if (signature
== 0x06)
1704 return parse_field (ctx
, &ptr
, end
);
1706 return parse_method_signature (ctx
, &ptr
, end
, TRUE
, FALSE
);
1710 is_valid_cattr_blob (VerifyContext
*ctx
, guint32 offset
)
1713 unsigned prolog
= 0;
1714 const char *ptr
= NULL
, *end
;
1719 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
1720 FAIL (ctx
, g_strdup ("CustomAttribute: Could not decode signature header"));
1723 if (!safe_read16 (prolog
, ptr
, end
))
1724 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for prolog"));
1727 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog
));
1733 is_valid_cattr_type (MonoType
*type
)
1737 if (type
->type
== MONO_TYPE_OBJECT
|| (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_STRING
))
1740 if (type
->type
== MONO_TYPE_VALUETYPE
) {
1741 klass
= mono_class_from_mono_type_internal (type
);
1742 return klass
&& m_class_is_enumtype (klass
);
1745 if (type
->type
== MONO_TYPE_CLASS
)
1746 return mono_class_from_mono_type_internal (type
) == mono_defaults
.systemtype_class
;
1752 is_valid_ser_string_full (VerifyContext
*ctx
, const char **str_start
, guint32
*str_len
, const char **_ptr
, const char *end
)
1755 const char *ptr
= *_ptr
;
1761 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for string size"));
1763 MONO_DISABLE_WARNING (4310) // cast truncates constant value
1765 if (*ptr
== (char)0xFF) {
1769 MONO_RESTORE_WARNING
1771 if (!safe_read_cint (size
, ptr
, end
))
1772 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for string size"));
1774 if (ADDP_IS_GREATER_OR_OVF (ptr
, size
, end
))
1775 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for string"));
1785 is_valid_ser_string (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1787 const char *dummy_str
;
1789 return is_valid_ser_string_full (ctx
, &dummy_str
, &dummy_int
, _ptr
, end
);
1793 get_enum_by_encoded_name (VerifyContext
*ctx
, const char **_ptr
, const char *end
)
1798 const char *str_start
= NULL
;
1799 const char *ptr
= *_ptr
;
1801 guint32 str_len
= 0;
1803 if (!is_valid_ser_string_full (ctx
, &str_start
, &str_len
, &ptr
, end
))
1806 /*NULL or empty string*/
1807 if (str_start
== NULL
|| str_len
== 0) {
1808 ADD_ERROR_NO_RETURN (ctx
, g_strdup ("CustomAttribute: Null or empty enum name"));
1812 enum_name
= (char *)g_memdup (str_start
, str_len
+ 1);
1813 enum_name
[str_len
] = 0;
1814 type
= mono_reflection_type_from_name_checked (enum_name
, ctx
->image
, error
);
1815 if (!type
|| !is_ok (error
)) {
1816 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("CustomAttribute: Invalid enum class %s, due to %s", enum_name
, mono_error_get_message (error
)));
1818 mono_error_cleanup (error
);
1823 klass
= mono_class_from_mono_type_internal (type
);
1824 if (!klass
|| !m_class_is_enumtype (klass
)) {
1825 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("CustomAttribute:Class %s::%s is not an enum", m_class_get_name_space (klass
), m_class_get_name (klass
)));
1834 is_valid_fixed_param (VerifyContext
*ctx
, MonoType
*mono_type
, const char **_ptr
, const char *end
)
1837 const char *ptr
= *_ptr
;
1839 guint32 element_count
, i
;
1842 klass
= mono_type
->data
.klass
;
1843 type
= mono_type
->type
;
1847 case MONO_TYPE_BOOLEAN
:
1854 case MONO_TYPE_CHAR
:
1868 case MONO_TYPE_STRING
:
1870 return is_valid_ser_string (ctx
, _ptr
, end
);
1872 case MONO_TYPE_OBJECT
: {
1873 unsigned sub_type
= 0;
1874 if (!safe_read8 (sub_type
, ptr
, end
))
1875 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for array type"));
1877 if (sub_type
>= MONO_TYPE_BOOLEAN
&& sub_type
<= MONO_TYPE_STRING
) {
1881 if (sub_type
== MONO_TYPE_ENUM
) {
1882 klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
1886 klass
= m_class_get_element_class (klass
);
1887 type
= m_class_get_byval_arg (klass
)->type
;
1890 if (sub_type
== 0x50) { /*Type*/
1892 return is_valid_ser_string (ctx
, _ptr
, end
);
1894 if (sub_type
== MONO_TYPE_SZARRAY
) {
1895 MonoType simple_type
= {{0}};
1897 if (!safe_read8 (etype
, ptr
, end
))
1898 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for array element type"));
1900 if (etype
== MONO_TYPE_ENUM
) {
1901 klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
1904 } else if (etype
== 0x50 || etype
== MONO_TYPE_CLASS
) {
1905 klass
= mono_defaults
.systemtype_class
;
1906 } else if ((etype
>= MONO_TYPE_BOOLEAN
&& etype
<= MONO_TYPE_STRING
) || etype
== 0x51) {
1907 simple_type
.type
= etype
== 0x51 ? MONO_TYPE_OBJECT
: (MonoTypeEnum
)etype
;
1908 klass
= mono_class_from_mono_type_internal (&simple_type
);
1910 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype
));
1912 type
= MONO_TYPE_SZARRAY
;
1915 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid boxed object type %x", sub_type
));
1918 case MONO_TYPE_CLASS
:
1919 if (klass
&& m_class_is_enumtype (klass
)) {
1920 klass
= m_class_get_element_class (klass
);
1921 type
= m_class_get_byval_arg (klass
)->type
;
1925 if (klass
!= mono_defaults
.systemtype_class
)
1926 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",m_class_get_name_space (klass
), m_class_get_name (klass
)));
1928 return is_valid_ser_string (ctx
, _ptr
, end
);
1930 case MONO_TYPE_VALUETYPE
:
1931 if (!klass
|| !m_class_is_enumtype (klass
))
1932 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid valuetype parameter expected enum %s:%s ",m_class_get_name_space (klass
), m_class_get_name (klass
)));
1934 klass
= m_class_get_element_class (klass
);
1935 type
= m_class_get_byval_arg (klass
)->type
;
1938 case MONO_TYPE_SZARRAY
:
1939 mono_type
= m_class_get_byval_arg (klass
);
1940 if (!is_valid_cattr_type (mono_type
))
1941 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid array element type %s:%s ",m_class_get_name_space (klass
), m_class_get_name (klass
)));
1942 if (!safe_read32 (element_count
, ptr
, end
))
1943 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid class parameter type %s:%s ",m_class_get_name_space (klass
), m_class_get_name (klass
)));
1944 if (element_count
== 0xFFFFFFFFu
) {
1948 for (i
= 0; i
< element_count
; ++i
) {
1949 if (!is_valid_fixed_param (ctx
, mono_type
, &ptr
, end
))
1955 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid parameter type %x ", type
));
1958 if (ADDP_IS_GREATER_OR_OVF (ptr
, elem_size
, end
))
1959 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough space for element"));
1960 *_ptr
= ptr
+ elem_size
;
1965 is_valid_cattr_content (VerifyContext
*ctx
, MonoMethod
*ctor
, const char *ptr
, guint32 size
)
1968 unsigned prolog
= 0;
1970 MonoMethodSignature
*sig
;
1975 FAIL (ctx
, g_strdup ("CustomAttribute: Invalid constructor"));
1977 sig
= mono_method_signature_checked (ctor
, error
);
1978 if (!mono_error_ok (error
)) {
1979 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("CustomAttribute: Invalid constructor signature %s", mono_error_get_message (error
)));
1980 mono_error_cleanup (error
);
1984 if (sig
->sentinelpos
!= -1 || sig
->call_convention
== MONO_CALL_VARARG
)
1985 FAIL (ctx
, g_strdup ("CustomAttribute: Constructor cannot have VARAG signature"));
1989 if (!safe_read16 (prolog
, ptr
, end
))
1990 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for prolog"));
1993 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Prolog is 0x%x, expected 0x1", prolog
));
1995 args
= sig
->param_count
;
1996 for (i
= 0; i
< args
; ++i
) {
1997 MonoType
*arg_type
= sig
->params
[i
];
1998 if (!is_valid_fixed_param (ctx
, arg_type
, &ptr
, end
))
2002 if (!safe_read16 (num_named
, ptr
, end
))
2003 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough space for num_named field"));
2005 for (i
= 0; i
< num_named
; ++i
) {
2006 MonoType
*type
, simple_type
= {{0}};
2009 if (!safe_read8 (kind
, ptr
, end
))
2010 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d kind", i
));
2011 if (kind
!= 0x53 && kind
!= 0x54)
2012 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid named parameter %d kind %x", i
, kind
));
2013 if (!safe_read8 (kind
, ptr
, end
))
2014 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Not enough space for named parameter %d type", i
));
2016 if (kind
>= MONO_TYPE_BOOLEAN
&& kind
<= MONO_TYPE_STRING
) {
2017 simple_type
.type
= (MonoTypeEnum
)kind
;
2018 type
= &simple_type
;
2019 } else if (kind
== MONO_TYPE_ENUM
) {
2020 MonoClass
*klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
2023 type
= m_class_get_byval_arg (klass
);
2024 } else if (kind
== 0x50) {
2025 type
= m_class_get_byval_arg (mono_defaults
.systemtype_class
);
2026 } else if (kind
== 0x51) {
2027 type
= mono_get_object_type ();
2028 } else if (kind
== MONO_TYPE_SZARRAY
) {
2031 if (!safe_read8 (etype
, ptr
, end
))
2032 FAIL (ctx
, g_strdup ("CustomAttribute: Not enough room for array element type"));
2034 if (etype
== MONO_TYPE_ENUM
) {
2035 klass
= get_enum_by_encoded_name (ctx
, &ptr
, end
);
2038 } else if (etype
== 0x50 || etype
== MONO_TYPE_CLASS
) {
2039 klass
= mono_defaults
.systemtype_class
;
2040 } else if ((etype
>= MONO_TYPE_BOOLEAN
&& etype
<= MONO_TYPE_STRING
) || etype
== 0x51) {
2041 simple_type
.type
= etype
== 0x51 ? MONO_TYPE_OBJECT
: (MonoTypeEnum
)etype
;
2042 klass
= mono_class_from_mono_type_internal (&simple_type
);
2044 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid array element type %x", etype
));
2046 type
= m_class_get_byval_arg (mono_class_create_array (klass
, 1));
2048 FAIL (ctx
, g_strdup_printf ("CustomAttribute: Invalid named parameter type %x", kind
));
2051 if (!is_valid_ser_string (ctx
, &ptr
, end
))
2054 if (!is_valid_fixed_param (ctx
, type
, &ptr
, end
))
2063 is_valid_marshal_spec (VerifyContext
*ctx
, guint32 offset
)
2065 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
2066 //TODO do proper verification
2067 return blob
.size
>= 1 && blob
.size
- 1 >= offset
;
2071 is_valid_permission_set (VerifyContext
*ctx
, guint32 offset
)
2073 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
2074 //TODO do proper verification
2075 return blob
.size
>= 1 && blob
.size
- 1 >= offset
;
2079 is_valid_standalonesig_blob (VerifyContext
*ctx
, guint32 offset
)
2082 unsigned signature
= 0;
2083 const char *ptr
= NULL
, *end
;
2085 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2086 FAIL (ctx
, g_strdup ("StandAloneSig: Could not decode signature header"));
2089 if (!safe_read8 (signature
, ptr
, end
))
2090 FAIL (ctx
, g_strdup ("StandAloneSig: Not enough room for the call conv"));
2093 if (signature
== 0x07)
2094 return parse_locals_signature (ctx
, &ptr
, end
);
2096 /*F# and managed C++ produce standalonesig for fields even thou the spec doesn't mention it.*/
2097 if (signature
== 0x06)
2098 return parse_field (ctx
, &ptr
, end
);
2100 return parse_method_signature (ctx
, &ptr
, end
, TRUE
, TRUE
);
2104 is_valid_property_sig_blob (VerifyContext
*ctx
, guint32 offset
)
2107 const char *ptr
= NULL
, *end
;
2109 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2110 FAIL (ctx
, g_strdup ("PropertySig: Could not decode signature header"));
2113 return parse_property_signature (ctx
, &ptr
, end
);
2117 is_valid_typespec_blob (VerifyContext
*ctx
, guint32 offset
)
2120 const char *ptr
= NULL
, *end
;
2123 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2124 FAIL (ctx
, g_strdup ("TypeSpec: Could not decode signature header"));
2127 if (!parse_custom_mods (ctx
, &ptr
, end
))
2130 if (!safe_read8 (type
, ptr
, end
))
2131 FAIL (ctx
, g_strdup ("TypeSpec: Not enough room for type"));
2133 if (type
== MONO_TYPE_BYREF
) {
2134 if (!safe_read8 (type
, ptr
, end
))
2135 FAIL (ctx
, g_strdup ("TypeSpec: Not enough room for byref type"));
2136 if (type
== MONO_TYPE_TYPEDBYREF
)
2137 FAIL (ctx
, g_strdup ("TypeSpec: Invalid type typedref&"));
2140 if (type
== MONO_TYPE_TYPEDBYREF
)
2144 return parse_type (ctx
, &ptr
, end
);
2148 is_valid_methodspec_blob (VerifyContext
*ctx
, guint32 offset
)
2151 const char *ptr
= NULL
, *end
;
2153 unsigned count
= 0, i
;
2155 if (!decode_signature_header (ctx
, offset
, &size
, &ptr
))
2156 FAIL (ctx
, g_strdup ("MethodSpec: Could not decode signature header"));
2159 if (!safe_read8 (type
, ptr
, end
))
2160 FAIL (ctx
, g_strdup ("MethodSpec: Not enough room for call convention"));
2163 FAIL (ctx
, g_strdup_printf ("MethodSpec: Invalid call convention 0x%x, expected 0x0A", type
));
2165 if (!safe_read_cint (count
, ptr
, end
))
2166 FAIL (ctx
, g_strdup ("MethodSpec: Not enough room for parameter count"));
2169 FAIL (ctx
, g_strdup ("MethodSpec: Zero generic argument count"));
2171 for (i
= 0; i
< count
; ++i
) {
2172 if (!parse_custom_mods (ctx
, &ptr
, end
))
2174 if (!parse_type (ctx
, &ptr
, end
))
2175 FAIL (ctx
, g_strdup_printf ("MethodSpec: Could not parse parameter %d", i
+ 1));
2181 is_valid_blob_object (VerifyContext
*ctx
, guint32 offset
, guint32 minsize
)
2183 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
2184 guint32 entry_size
, bytes
;
2186 if (blob
.size
< offset
)
2189 if (!decode_value (ctx
->data
+ offset
+ blob
.offset
, blob
.size
- blob
.offset
, &entry_size
, &bytes
))
2192 if (entry_size
< minsize
)
2195 if (CHECK_ADD4_OVERFLOW_UN (entry_size
, bytes
))
2197 entry_size
+= bytes
;
2199 return !ADD_IS_GREATER_OR_OVF (offset
, entry_size
, blob
.size
);
2203 is_valid_constant (VerifyContext
*ctx
, guint32 type
, guint32 offset
)
2205 OffsetAndSize blob
= get_metadata_stream (ctx
, &ctx
->image
->heap_blob
);
2206 guint32 size
, entry_size
, bytes
;
2208 if (blob
.size
< offset
)
2209 FAIL (ctx
, g_strdup ("ContantValue: invalid offset"));
2211 if (!decode_value (ctx
->data
+ offset
+ blob
.offset
, blob
.size
- blob
.offset
, &entry_size
, &bytes
))
2212 FAIL (ctx
, g_strdup ("ContantValue: not enough space to decode size"));
2214 if (type
== MONO_TYPE_STRING
) {
2215 //String is encoded as: compressed_int:len len *bytes
2218 if (ADD_IS_GREATER_OR_OVF (offset
, entry_size
, blob
.size
))
2219 FAIL (ctx
, g_strdup_printf ("ContantValue: not enough space for string, required %d but got %d", entry_size
* 2, blob
.size
- offset
));
2225 case MONO_TYPE_BOOLEAN
:
2230 case MONO_TYPE_CHAR
:
2238 case MONO_TYPE_CLASS
:
2248 g_assert_not_reached ();
2251 if (size
!= entry_size
)
2252 FAIL (ctx
, g_strdup_printf ("ContantValue: Expected size %d but got %d", size
, entry_size
));
2256 if (ADD_IS_GREATER_OR_OVF (offset
, size
, blob
.size
))
2257 FAIL (ctx
, g_strdup_printf ("ContantValue: Not enough room for constant, required %d but have %d", size
, blob
.size
- offset
));
2259 if (type
== MONO_TYPE_CLASS
&& read32 (ctx
->data
+ blob
.offset
+ offset
))
2260 FAIL (ctx
, g_strdup_printf ("ContantValue: Type is class but value is not null"));
2264 #define FAT_HEADER_INVALID_FLAGS ~(0x3 | 0x8 | 0x10 | 0xF000)
2265 //only 0x01, 0x40 and 0x80 are allowed
2266 #define SECTION_HEADER_INVALID_FLAGS 0x3E
2269 is_valid_method_header (VerifyContext
*ctx
, guint32 rva
, guint32
*locals_token
)
2271 unsigned local_vars_tok
, code_size
, offset
= mono_cli_rva_image_map (ctx
->image
, rva
);
2272 unsigned header
= 0;
2273 unsigned fat_header
= 0, size
= 0, max_stack
;
2274 const char *ptr
= NULL
, *end
;
2278 if (offset
== INVALID_ADDRESS
)
2279 FAIL (ctx
, g_strdup ("MethodHeader: Invalid RVA"));
2281 ptr
= ctx
->data
+ offset
;
2282 end
= ctx
->data
+ ctx
->size
; /*no worries if it spawns multiple sections*/
2284 if (!safe_read8 (header
, ptr
, end
))
2285 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for header"));
2287 switch (header
& 0x3) {
2290 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid header type 0x%x", header
& 0x3));
2293 if (ADDP_IS_GREATER_OR_OVF (ptr
, header
, end
))
2294 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for method body. Required %d, but only %d is available", header
, (int)(end
- ptr
)));
2299 if (!safe_read16 (fat_header
, ptr
, end
))
2300 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for fat header"));
2302 size
= (fat_header
>> 12) & 0xF;
2304 FAIL (ctx
, g_strdup ("MethodHeader: header size must be 3"));
2306 if (!safe_read16 (max_stack
, ptr
, end
))
2307 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for max stack"));
2309 if (!safe_read32 (code_size
, ptr
, end
))
2310 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for code size"));
2312 if (!safe_read32 (local_vars_tok
, ptr
, end
))
2313 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for local vars tok"));
2315 if (local_vars_tok
) {
2316 if (((local_vars_tok
>> 24) & 0xFF) != 0x11)
2317 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid local vars signature table 0x%x", ((local_vars_tok
>> 24) & 0xFF)));
2318 if ((local_vars_tok
& 0xFFFFFF) > ctx
->image
->tables
[MONO_TABLE_STANDALONESIG
].rows
)
2319 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid local vars signature points to invalid row 0x%x", local_vars_tok
& 0xFFFFFF));
2320 if (!(local_vars_tok
& 0xFFFFFF))
2321 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid local vars signature with zero index"));
2322 *locals_token
= local_vars_tok
& 0xFFFFFF;
2325 if (fat_header
& FAT_HEADER_INVALID_FLAGS
)
2326 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid fat signature flags %x", fat_header
& FAT_HEADER_INVALID_FLAGS
));
2328 if (ADDP_IS_GREATER_OR_OVF (ptr
, code_size
, end
))
2329 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for code %d", code_size
));
2331 if (!(fat_header
& 0x08))
2337 unsigned section_header
= 0, section_size
= 0;
2340 ptr
= dword_align (ptr
);
2341 if (!safe_read32 (section_header
, ptr
, end
))
2342 FAIL (ctx
, g_strdup ("MethodHeader: Not enough room for data section header"));
2344 if (section_header
& SECTION_HEADER_INVALID_FLAGS
)
2345 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid section header flags 0x%x", section_header
& SECTION_HEADER_INVALID_FLAGS
));
2347 is_fat
= (section_header
& METHOD_HEADER_SECTION_FAT_FORMAT
) != 0;
2348 section_size
= (section_header
>> 8) & (is_fat
? 0xFFFFFF : 0xFF);
2350 if (section_size
< 4)
2351 FAIL (ctx
, g_strdup_printf ("MethodHeader: Section size too small"));
2353 if (ADDP_IS_GREATER_OR_OVF (ptr
, section_size
- 4, end
)) /*must be section_size -4 as ptr was incremented by safe_read32*/
2354 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for section content %d", section_size
));
2356 if (section_header
& METHOD_HEADER_SECTION_EHTABLE
) {
2357 guint32 i
, clauses
= section_size
/ (is_fat
? 24 : 12);
2359 LAMEIMPL: MS emits section_size without accounting for header size.
2360 Mono does as the spec says. section_size is header + section
2361 MS's peverify happily accepts both.
2363 if ((clauses
* (is_fat
? 24 : 12) != section_size
) && (clauses
* (is_fat
? 24 : 12) + 4 != section_size
))
2364 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)));
2366 /* only verify the class token is verified as the rest is done by the IL verifier*/
2367 for (i
= 0; i
< clauses
; ++i
) {
2368 unsigned flags
= *(unsigned char*)ptr
;
2369 unsigned class_token
= 0;
2370 ptr
+= (is_fat
? 20 : 8);
2371 if (!safe_read32 (class_token
, ptr
, end
))
2372 FAIL (ctx
, g_strdup_printf ("MethodHeader: Not enough room for section %d", i
));
2373 if (flags
== MONO_EXCEPTION_CLAUSE_NONE
&& class_token
) {
2374 guint table
= mono_metadata_token_table (class_token
);
2375 if (table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPESPEC
)
2376 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid section %d class token table %x", i
, table
));
2377 if (mono_metadata_token_index (class_token
) > ctx
->image
->tables
[table
].rows
)
2378 FAIL (ctx
, g_strdup_printf ("MethodHeader: Invalid section %d class token index %x", i
, mono_metadata_token_index (class_token
)));
2383 if (!(section_header
& METHOD_HEADER_SECTION_MORE_SECTS
))
2390 verify_module_table (VerifyContext
*ctx
)
2392 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MODULE
];
2393 guint32 data
[MONO_MODULE_SIZE
];
2395 if (table
->rows
!= 1)
2396 ADD_ERROR (ctx
, g_strdup_printf ("Module table must have exactly one row, but have %d", table
->rows
));
2398 mono_metadata_decode_row (table
, 0, data
, MONO_MODULE_SIZE
);
2400 if (!is_valid_non_empty_string (ctx
, data
[MONO_MODULE_NAME
]))
2401 ADD_ERROR (ctx
, g_strdup_printf ("Module has an invalid name, string index 0x%08x", data
[MONO_MODULE_NAME
]));
2403 if (!is_valid_guid (ctx
, data
[MONO_MODULE_MVID
]))
2404 ADD_ERROR (ctx
, g_strdup_printf ("Module has an invalid Mvid, guid index %x", data
[MONO_MODULE_MVID
]));
2406 if (data
[MONO_MODULE_ENC
] != 0)
2407 ADD_ERROR (ctx
, g_strdup_printf ("Module has a non zero Enc field %x", data
[MONO_MODULE_ENC
]));
2409 if (data
[MONO_MODULE_ENCBASE
] != 0)
2410 ADD_ERROR (ctx
, g_strdup_printf ("Module has a non zero EncBase field %x", data
[MONO_MODULE_ENCBASE
]));
2414 verify_typeref_table (VerifyContext
*ctx
)
2416 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEREF
];
2420 for (i
= 0; i
< table
->rows
; ++i
) {
2421 mono_verifier_verify_typeref_row (ctx
->image
, i
, error
);
2422 add_from_mono_error (ctx
, error
);
2426 /*bits 9,11,14,15,19,21,24-31 */
2427 #define INVALID_TYPEDEF_FLAG_BITS ((1 << 6) | (1 << 9) | (1 << 15) | (1 << 19) | (1 << 21) | 0xFF000000)
2429 verify_typedef_table (VerifyContext
*ctx
)
2431 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2432 guint32 data
[MONO_TYPEDEF_SIZE
];
2433 guint32 fieldlist
= 1, methodlist
= 1, visibility
;
2436 if (table
->rows
== 0)
2437 ADD_ERROR (ctx
, g_strdup_printf ("Typedef table must have exactly at least one row"));
2439 for (i
= 0; i
< table
->rows
; ++i
) {
2440 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEDEF_SIZE
);
2441 if (data
[MONO_TYPEDEF_FLAGS
] & INVALID_TYPEDEF_FLAG_BITS
)
2442 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid flags field 0x%08x rejected bits: 0x%08x", i
, data
[MONO_TYPEDEF_FLAGS
], data
[MONO_TYPEDEF_FLAGS
] & INVALID_TYPEDEF_FLAG_BITS
));
2444 if ((data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_LAYOUT_MASK
) == 0x18)
2445 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid class layout 0x18", i
));
2447 if ((data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == 0x30000)
2448 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i
));
2450 if ((data
[MONO_TYPEDEF_FLAGS
] & 0xC00000) != 0)
2451 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d mono doesn't support custom string format", i
));
2453 if ((data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_INTERFACE
) && (data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_ABSTRACT
) == 0)
2454 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for interface type must be abstract", i
));
2456 if (!data
[MONO_TYPEDEF_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_TYPEDEF_NAME
]))
2457 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid name token %08x", i
, data
[MONO_TYPEDEF_NAME
]));
2459 if (data
[MONO_TYPEREF_NAMESPACE
] && !is_valid_non_empty_string (ctx
, data
[MONO_TYPEREF_NAMESPACE
]))
2460 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d invalid namespace token %08x", i
, data
[MONO_TYPEREF_NAMESPACE
]));
2462 if (data
[MONO_TYPEDEF_EXTENDS
] && !is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_TYPEDEF_EXTENDS
]))
2463 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i
, data
[MONO_TYPEDEF_EXTENDS
]));
2465 if (data
[MONO_TYPEDEF_EXTENDS
] && !get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_TYPEDEF_EXTENDS
]))
2466 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d zero coded extend field coded index 0x%08x", i
, data
[MONO_TYPEDEF_EXTENDS
]));
2468 visibility
= data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2469 if ((visibility
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visibility
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
) &&
2470 search_sorted_table (ctx
, MONO_TABLE_NESTEDCLASS
, MONO_NESTED_CLASS_NESTED
, i
+ 1) == -1)
2471 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d has nested visibility but no rows in the NestedClass table", i
));
2473 if (data
[MONO_TYPEDEF_FIELD_LIST
] == 0)
2474 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i
));
2476 if (data
[MONO_TYPEDEF_FIELD_LIST
] > ctx
->image
->tables
[MONO_TABLE_FIELD
].rows
+ 1)
2477 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i
, data
[MONO_TYPEDEF_FIELD_LIST
]));
2479 if (data
[MONO_TYPEDEF_FIELD_LIST
] < fieldlist
)
2480 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
));
2482 if (data
[MONO_TYPEDEF_METHOD_LIST
] == 0)
2483 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i
));
2485 if (data
[MONO_TYPEDEF_METHOD_LIST
] > ctx
->image
->tables
[MONO_TABLE_METHOD
].rows
+ 1)
2486 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i
, data
[MONO_TYPEDEF_METHOD_LIST
]));
2488 if (data
[MONO_TYPEDEF_METHOD_LIST
] < methodlist
)
2489 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
));
2491 fieldlist
= data
[MONO_TYPEDEF_FIELD_LIST
];
2492 methodlist
= data
[MONO_TYPEDEF_METHOD_LIST
];
2497 verify_typedef_table_full (VerifyContext
*ctx
)
2499 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2500 guint32 data
[MONO_TYPEDEF_SIZE
];
2503 if (table
->rows
== 0)
2504 ADD_ERROR (ctx
, g_strdup_printf ("Typedef table must have exactly at least one row"));
2506 for (i
= 0; i
< table
->rows
; ++i
) {
2507 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEDEF_SIZE
);
2510 /*XXX it's ok if <module> extends object, or anything at all, actually. */
2511 /*if (data [MONO_TYPEDEF_EXTENDS] != 0)
2512 ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row 0 for the special <module> type must have a null extend field"));
2517 if (data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_INTERFACE
) {
2518 if (data
[MONO_TYPEDEF_EXTENDS
])
2519 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for interface type must have a null extend field", i
));
2521 gboolean is_sys_obj
= typedef_is_system_object (ctx
, data
);
2522 gboolean has_parent
= get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_TYPEDEF_EXTENDS
]) != 0;
2526 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for System.Object must have a null extend field", i
));
2529 ADD_ERROR (ctx
, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i
));
2537 #define INVALID_FIELD_FLAG_BITS ((1 << 3) | (1 << 11) | (1 << 14))
2539 verify_field_table (VerifyContext
*ctx
)
2541 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELD
];
2542 guint32 data
[MONO_FIELD_SIZE
], flags
, module_field_list
;
2545 module_field_list
= (guint32
)-1;
2546 if (ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
> 1) {
2547 MonoTableInfo
*type
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2548 module_field_list
= mono_metadata_decode_row_col (type
, 1, MONO_TYPEDEF_FIELD_LIST
);
2551 for (i
= 0; i
< table
->rows
; ++i
) {
2552 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_SIZE
);
2553 flags
= data
[MONO_FIELD_FLAGS
];
2555 if (flags
& INVALID_FIELD_FLAG_BITS
)
2556 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid flags field 0x%08x", i
, flags
));
2558 if ((flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == 0x7)
2559 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid field visibility 0x7", i
));
2561 if ((flags
& (FIELD_ATTRIBUTE_LITERAL
| FIELD_ATTRIBUTE_INIT_ONLY
)) == (FIELD_ATTRIBUTE_LITERAL
| FIELD_ATTRIBUTE_INIT_ONLY
))
2562 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d cannot be InitOnly and Literal at the same time", i
));
2564 if ((flags
& FIELD_ATTRIBUTE_RT_SPECIAL_NAME
) && !(flags
& FIELD_ATTRIBUTE_SPECIAL_NAME
))
2565 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is RTSpecialName but not SpecialName", i
));
2567 if ((flags
& FIELD_ATTRIBUTE_LITERAL
) && !(flags
& FIELD_ATTRIBUTE_STATIC
))
2568 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is Literal but not Static", i
));
2570 if ((flags
& FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL
) &&
2571 search_sorted_table (ctx
, MONO_TABLE_FIELDMARSHAL
, MONO_FIELD_MARSHAL_PARENT
, make_coded_token (HAS_FIELD_MARSHAL_DESC
, MONO_TABLE_FIELD
, i
)) == -1)
2572 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d has FieldMarshal but there is no corresponding row in the FieldMarshal table", i
));
2574 if ((flags
& FIELD_ATTRIBUTE_HAS_DEFAULT
) &&
2575 search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_FIELD
, i
)) == -1)
2576 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i
));
2578 if ((flags
& FIELD_ATTRIBUTE_LITERAL
) &&
2579 search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_FIELD
, i
)) == -1)
2580 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i
));
2582 if ((flags
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) &&
2583 search_sorted_table (ctx
, MONO_TABLE_FIELDRVA
, MONO_FIELD_RVA_FIELD
, i
+ 1) == -1)
2584 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i
));
2586 if (!data
[MONO_FIELD_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_FIELD_NAME
]))
2587 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid name token %08x", i
, data
[MONO_FIELD_NAME
]));
2589 if (data
[MONO_FIELD_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_FIELD_SIGNATURE
], 1))
2590 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid signature blob token 0x%x", i
, data
[MONO_FIELD_SIGNATURE
]));
2592 //TODO verify contant flag
2594 if (i
+ 1 < module_field_list
) {
2595 guint32 access
= flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
;
2596 if (!(flags
& FIELD_ATTRIBUTE_STATIC
))
2597 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i
));
2598 if (access
!= FIELD_ATTRIBUTE_COMPILER_CONTROLLED
&& access
!= FIELD_ATTRIBUTE_PRIVATE
&& access
!= FIELD_ATTRIBUTE_PUBLIC
)
2599 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i
, access
));
2605 verify_field_table_full (VerifyContext
*ctx
)
2607 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELD
];
2608 guint32 data
[MONO_FIELD_SIZE
];
2611 for (i
= 0; i
< table
->rows
; ++i
) {
2612 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_SIZE
);
2614 if (!data
[MONO_FIELD_SIGNATURE
] || !is_valid_field_signature (ctx
, data
[MONO_FIELD_SIGNATURE
]))
2615 ADD_ERROR (ctx
, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i
, data
[MONO_FIELD_SIGNATURE
]));
2619 /*bits 8,9,10,11,13,14,15*/
2620 #define INVALID_METHOD_IMPLFLAG_BITS ((1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
2622 verify_method_table (VerifyContext
*ctx
)
2624 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHOD
];
2625 guint32 data
[MONO_METHOD_SIZE
], flags
, implflags
, rva
, module_method_list
, access
, code_type
;
2626 guint32 paramlist
= 1;
2627 gboolean is_ctor
, is_cctor
;
2631 module_method_list
= (guint32
)-1;
2632 if (ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
> 1) {
2633 MonoTableInfo
*type
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
2634 module_method_list
= mono_metadata_decode_row_col (type
, 1, MONO_TYPEDEF_METHOD_LIST
);
2637 for (i
= 0; i
< table
->rows
; ++i
) {
2638 mono_metadata_decode_row (table
, i
, data
, MONO_METHOD_SIZE
);
2639 rva
= data
[MONO_METHOD_RVA
];
2640 implflags
= data
[MONO_METHOD_IMPLFLAGS
];
2641 flags
= data
[MONO_METHOD_FLAGS
];
2642 access
= flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
;
2643 code_type
= implflags
& METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK
;
2646 if (implflags
& INVALID_METHOD_IMPLFLAG_BITS
)
2647 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i
, implflags
));
2650 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i
));
2652 if (!data
[MONO_METHOD_NAME
] || !is_valid_non_empty_string (ctx
, data
[MONO_METHOD_NAME
]))
2653 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i
, data
[MONO_METHOD_NAME
]));
2655 name
= get_string_ptr (ctx
, data
[MONO_METHOD_NAME
]);
2656 is_ctor
= !strcmp (".ctor", name
);
2657 is_cctor
= !strcmp (".cctor", name
);
2659 if ((is_ctor
|| is_cctor
) &&
2660 search_sorted_table (ctx
, MONO_TABLE_GENERICPARAM
, MONO_GENERICPARAM_OWNER
, make_coded_token (TYPE_OR_METHODDEF_DESC
, MONO_TABLE_METHOD
, i
)) != -1)
2661 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i
));
2663 if ((flags
& METHOD_ATTRIBUTE_STATIC
) && (flags
& (METHOD_ATTRIBUTE_FINAL
| METHOD_ATTRIBUTE_VIRTUAL
| METHOD_ATTRIBUTE_NEW_SLOT
)))
2664 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i
));
2666 if (flags
& METHOD_ATTRIBUTE_ABSTRACT
) {
2667 if (flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
2668 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i
));
2669 if (flags
& METHOD_ATTRIBUTE_FINAL
)
2670 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is Abstract and Final", i
));
2671 if (!(flags
& METHOD_ATTRIBUTE_VIRTUAL
))
2672 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i
));
2675 if (access
== METHOD_ATTRIBUTE_COMPILER_CONTROLLED
&& (flags
& (METHOD_ATTRIBUTE_RT_SPECIAL_NAME
| METHOD_ATTRIBUTE_SPECIAL_NAME
)))
2676 ADD_WARNING (ctx
, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i
));
2678 if ((flags
& METHOD_ATTRIBUTE_RT_SPECIAL_NAME
) && !(flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
))
2679 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i
));
2681 //XXX no checks against cas stuff 10,11,12,13)
2683 //TODO check iface with .ctor (15,16)
2685 if (i
+ 1 < module_method_list
) {
2686 if (!(flags
& METHOD_ATTRIBUTE_STATIC
))
2687 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is a global method but not Static", i
));
2688 if (flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_VIRTUAL
))
2689 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i
));
2690 if (access
== METHOD_ATTRIBUTE_FAMILY
|| access
== METHOD_ATTRIBUTE_FAM_AND_ASSEM
|| access
== METHOD_ATTRIBUTE_FAM_OR_ASSEM
)
2691 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public, Private or Assembly", i
));
2694 //TODO check valuetype for synchronized
2696 if ((flags
& (METHOD_ATTRIBUTE_FINAL
| METHOD_ATTRIBUTE_NEW_SLOT
| METHOD_ATTRIBUTE_STRICT
)) && !(flags
& METHOD_ATTRIBUTE_VIRTUAL
))
2697 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i
));
2699 if (flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
2700 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
2701 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i
));
2702 if (!(flags
& METHOD_ATTRIBUTE_STATIC
))
2703 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl but not Static", i
));
2706 if (!(flags
& METHOD_ATTRIBUTE_ABSTRACT
) && !rva
&& !(flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) &&
2707 !(implflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) && code_type
!= METHOD_IMPL_ATTRIBUTE_RUNTIME
)
2708 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i
));
2710 if (access
== METHOD_ATTRIBUTE_COMPILER_CONTROLLED
&& !(rva
|| (flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)))
2711 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i
));
2713 //TODO check signature contents
2716 if ((flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_PINVOKE_IMPL
)) || (implflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
2717 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d has RVA != 0 but is either Abstract, InternalCall or PinvokeImpl", i
));
2718 if (code_type
== METHOD_IMPL_ATTRIBUTE_OPTIL
)
2719 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i
));
2721 if (!(flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_PINVOKE_IMPL
)) && !(implflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) && code_type
!= METHOD_IMPL_ATTRIBUTE_RUNTIME
)
2722 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i
));
2725 if ((flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)) {
2727 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i
));
2728 if (search_sorted_table (ctx
, MONO_TABLE_IMPLMAP
, MONO_IMPLMAP_MEMBER
, make_coded_token (MEMBER_FORWARDED_DESC
, MONO_TABLE_METHOD
, i
)) == -1)
2729 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i
));
2731 if (flags
& METHOD_ATTRIBUTE_RT_SPECIAL_NAME
&& !is_ctor
&& !is_cctor
)
2732 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i
));
2734 if ((is_ctor
|| is_cctor
) && !(flags
& METHOD_ATTRIBUTE_RT_SPECIAL_NAME
))
2735 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i
));
2737 if (data
[MONO_METHOD_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_METHOD_SIGNATURE
], 1))
2738 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid signature blob token 0x%x", i
, data
[MONO_METHOD_SIGNATURE
]));
2740 if (data
[MONO_METHOD_PARAMLIST
] == 0)
2741 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i
));
2743 if (data
[MONO_METHOD_PARAMLIST
] < paramlist
)
2744 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
));
2746 if (data
[MONO_METHOD_PARAMLIST
] > ctx
->image
->tables
[MONO_TABLE_PARAM
].rows
+ 1)
2747 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i
, data
[MONO_METHOD_PARAMLIST
]));
2749 paramlist
= data
[MONO_METHOD_PARAMLIST
];
2755 verify_method_table_full (VerifyContext
*ctx
)
2757 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHOD
];
2758 guint32 data
[MONO_METHOD_SIZE
], rva
, locals_token
;
2761 for (i
= 0; i
< table
->rows
; ++i
) {
2762 mono_metadata_decode_row (table
, i
, data
, MONO_METHOD_SIZE
);
2763 rva
= data
[MONO_METHOD_RVA
];
2765 if (!data
[MONO_METHOD_SIGNATURE
] || !is_valid_method_signature (ctx
, data
[MONO_METHOD_SIGNATURE
]))
2766 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d invalid signature token 0x%08x", i
, data
[MONO_METHOD_SIGNATURE
]));
2768 if (rva
&& !is_valid_method_header (ctx
, rva
, &locals_token
))
2769 ADD_ERROR (ctx
, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i
));
2774 get_next_param_count (VerifyContext
*ctx
, guint32
*current_method
)
2776 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHOD
];
2777 guint32 row
= *current_method
;
2778 guint32 paramlist
, tmp
;
2781 paramlist
= mono_metadata_decode_row_col (table
, row
++, MONO_METHOD_PARAMLIST
);
2782 while (row
< table
->rows
) {
2783 tmp
= mono_metadata_decode_row_col (table
, row
, MONO_METHOD_PARAMLIST
);
2784 if (tmp
> paramlist
) {
2785 *current_method
= row
;
2786 return tmp
- paramlist
;
2791 /*no more methods, all params apply to the last one*/
2792 *current_method
= table
->rows
;
2797 #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))
2799 verify_param_table (VerifyContext
*ctx
)
2801 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_PARAM
];
2802 guint32 data
[MONO_PARAM_SIZE
], flags
, sequence
= 0, remaining_params
, current_method
= 0;
2803 gboolean first_param
= TRUE
;
2806 if (ctx
->image
->tables
[MONO_TABLE_METHOD
].rows
== 0) {
2807 if (table
->rows
> 0)
2808 ADD_ERROR (ctx
, g_strdup ("Param table has rows while the method table has zero"));
2812 remaining_params
= get_next_param_count (ctx
, ¤t_method
);
2814 for (i
= 0; i
< table
->rows
; ++i
) {
2815 mono_metadata_decode_row (table
, i
, data
, MONO_PARAM_SIZE
);
2816 flags
= data
[MONO_PARAM_FLAGS
];
2818 if (flags
& INVALID_PARAM_FLAGS_BITS
)
2819 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i
, flags
));
2821 if (search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_PARAM
, i
)) == -1) {
2822 if (flags
& PARAM_ATTRIBUTE_HAS_DEFAULT
)
2823 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i
));
2825 if (!(flags
& PARAM_ATTRIBUTE_HAS_DEFAULT
))
2826 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i
));
2829 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)
2830 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i
));
2832 if (!is_valid_string (ctx
, data
[MONO_PARAM_NAME
]))
2833 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i
, data
[MONO_PARAM_NAME
]));
2835 if (!first_param
&& data
[MONO_PARAM_SEQUENCE
] <= sequence
)
2836 ADD_ERROR (ctx
, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i
, data
[MONO_PARAM_SEQUENCE
], sequence
));
2838 first_param
= FALSE
;
2839 sequence
= data
[MONO_PARAM_SEQUENCE
];
2840 if (--remaining_params
== 0) {
2841 remaining_params
= get_next_param_count (ctx
, ¤t_method
);
2848 verify_interfaceimpl_table (VerifyContext
*ctx
)
2850 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_INTERFACEIMPL
];
2851 guint32 data
[MONO_INTERFACEIMPL_SIZE
];
2854 for (i
= 0; i
< table
->rows
; ++i
) {
2855 mono_metadata_decode_row (table
, i
, data
, MONO_INTERFACEIMPL_SIZE
);
2856 if (data
[MONO_INTERFACEIMPL_CLASS
] && data
[MONO_INTERFACEIMPL_CLASS
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
)
2857 ADD_ERROR (ctx
, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i
, data
[MONO_INTERFACEIMPL_CLASS
]));
2859 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_INTERFACEIMPL_INTERFACE
]))
2860 ADD_ERROR (ctx
, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i
, data
[MONO_INTERFACEIMPL_INTERFACE
]));
2862 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_INTERFACEIMPL_INTERFACE
]))
2863 ADD_ERROR (ctx
, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i
));
2868 verify_memberref_table (VerifyContext
*ctx
)
2870 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MEMBERREF
];
2871 guint32 data
[MONO_MEMBERREF_SIZE
];
2874 for (i
= 0; i
< table
->rows
; ++i
) {
2875 mono_metadata_decode_row (table
, i
, data
, MONO_MEMBERREF_SIZE
);
2877 if (!is_valid_coded_index (ctx
, MEMBERREF_PARENT_DESC
, data
[MONO_MEMBERREF_CLASS
]))
2878 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Class field coded index 0x%08x", i
, data
[MONO_MEMBERREF_CLASS
]));
2880 if (!get_coded_index_token (MEMBERREF_PARENT_DESC
, data
[MONO_MEMBERREF_CLASS
]))
2881 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Class field coded is null", i
));
2883 if (!is_valid_non_empty_string (ctx
, data
[MONO_MEMBERREF_NAME
]))
2884 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Name field coded is invalid or empty 0x%08x", i
, data
[MONO_MEMBERREF_NAME
]));
2886 if (data
[MONO_MEMBERREF_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_MEMBERREF_SIGNATURE
], 1))
2887 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d invalid signature blob token 0x%x", i
, data
[MONO_MEMBERREF_SIGNATURE
]));
2893 verify_memberref_table_full (VerifyContext
*ctx
)
2895 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MEMBERREF
];
2896 guint32 data
[MONO_MEMBERREF_SIZE
];
2899 for (i
= 0; i
< table
->rows
; ++i
) {
2900 mono_metadata_decode_row (table
, i
, data
, MONO_MEMBERREF_SIZE
);
2902 if (!is_valid_method_or_field_signature (ctx
, data
[MONO_MEMBERREF_SIGNATURE
]))
2903 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MemberRef row %d Signature field 0x%08x", i
, data
[MONO_MEMBERREF_SIGNATURE
]));
2908 verify_constant_table (VerifyContext
*ctx
)
2910 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CONSTANT
];
2911 guint32 data
[MONO_CONSTANT_SIZE
], type
;
2914 for (i
= 0; i
< table
->rows
; ++i
) {
2915 mono_metadata_decode_row (table
, i
, data
, MONO_CONSTANT_SIZE
);
2916 type
= data
[MONO_CONSTANT_TYPE
];
2918 if (!((type
>= MONO_TYPE_BOOLEAN
&& type
<= MONO_TYPE_STRING
) || type
== MONO_TYPE_CLASS
))
2919 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Type field 0x%08x", i
, type
));
2921 if (!is_valid_coded_index (ctx
, HAS_CONSTANT_DESC
, data
[MONO_CONSTANT_PARENT
]))
2922 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Parent field coded index 0x%08x", i
, data
[MONO_CONSTANT_PARENT
]));
2924 if (!get_coded_index_token (HAS_CONSTANT_DESC
, data
[MONO_CONSTANT_PARENT
]))
2925 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Parent field coded is null", i
));
2927 if (!is_valid_constant (ctx
, type
, data
[MONO_CONSTANT_VALUE
]))
2928 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Constant row %d Value field 0x%08x", i
, data
[MONO_CONSTANT_VALUE
]));
2933 verify_cattr_table (VerifyContext
*ctx
)
2935 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2936 guint32 data
[MONO_CUSTOM_ATTR_SIZE
];
2939 for (i
= 0; i
< table
->rows
; ++i
) {
2940 mono_metadata_decode_row (table
, i
, data
, MONO_CUSTOM_ATTR_SIZE
);
2942 if (!is_valid_coded_index (ctx
, HAS_CATTR_DESC
, data
[MONO_CUSTOM_ATTR_PARENT
]))
2943 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d Parent field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_PARENT
]));
2945 if (!is_valid_coded_index (ctx
, CATTR_TYPE_DESC
, data
[MONO_CUSTOM_ATTR_TYPE
]) || !get_coded_index_token (CATTR_TYPE_DESC
, data
[MONO_CUSTOM_ATTR_TYPE
]))
2946 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d Type field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_TYPE
]));
2948 if (data
[MONO_CUSTOM_ATTR_VALUE
] && !is_valid_blob_object (ctx
, data
[MONO_CUSTOM_ATTR_VALUE
], 0))
2949 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d invalid value blob 0x%x", i
, data
[MONO_CUSTOM_ATTR_VALUE
]));
2954 verify_cattr_table_full (VerifyContext
*ctx
)
2957 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2960 guint32 data
[MONO_CUSTOM_ATTR_SIZE
], mtoken
, size
;
2963 for (i
= 0; i
< table
->rows
; ++i
) {
2964 mono_metadata_decode_row (table
, i
, data
, MONO_CUSTOM_ATTR_SIZE
);
2966 if (!is_valid_cattr_blob (ctx
, data
[MONO_CUSTOM_ATTR_VALUE
]))
2967 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute row %d Value field 0x%08x", i
, data
[MONO_CUSTOM_ATTR_VALUE
]));
2969 mtoken
= data
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
2970 switch (data
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
2971 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
2972 mtoken
|= MONO_TOKEN_METHOD_DEF
;
2974 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
2975 mtoken
|= MONO_TOKEN_MEMBER_REF
;
2978 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute constructor row %d Token 0x%08x", i
, data
[MONO_CUSTOM_ATTR_TYPE
]));
2981 ctor
= mono_get_method_checked (ctx
->image
, mtoken
, NULL
, NULL
, error
);
2984 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute content row %d Could not load ctor due to %s", i
, mono_error_get_message (error
)));
2985 mono_error_cleanup (error
);
2988 /*This can't fail since this is checked in is_valid_cattr_blob*/
2989 g_assert (decode_signature_header (ctx
, data
[MONO_CUSTOM_ATTR_VALUE
], &size
, &ptr
));
2991 if (!is_valid_cattr_content (ctx
, ctor
, ptr
, size
)) {
2992 char *ctor_name
= mono_method_full_name (ctor
, TRUE
);
2993 ADD_ERROR (ctx
, g_strdup_printf ("Invalid CustomAttribute content row %d Value field 0x%08x ctor: %s", i
, data
[MONO_CUSTOM_ATTR_VALUE
], ctor_name
));
3000 verify_field_marshal_table (VerifyContext
*ctx
)
3002 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDMARSHAL
];
3003 guint32 data
[MONO_FIELD_MARSHAL_SIZE
];
3006 for (i
= 0; i
< table
->rows
; ++i
) {
3007 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_MARSHAL_SIZE
);
3009 if (!is_valid_coded_index (ctx
, HAS_FIELD_MARSHAL_DESC
, data
[MONO_FIELD_MARSHAL_PARENT
]))
3010 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d Parent field 0x%08x", i
, data
[MONO_FIELD_MARSHAL_PARENT
]));
3012 if (!get_coded_index_token (HAS_FIELD_MARSHAL_DESC
, data
[MONO_FIELD_MARSHAL_PARENT
]))
3013 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d Parent field is null", i
));
3015 if (!data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
])
3016 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field is null", i
));
3018 if (!is_valid_blob_object (ctx
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
], 1))
3019 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d invalid NativeType blob 0x%x", i
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
]));
3024 verify_field_marshal_table_full (VerifyContext
*ctx
)
3026 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDMARSHAL
];
3027 guint32 data
[MONO_FIELD_MARSHAL_SIZE
];
3030 for (i
= 0; i
< table
->rows
; ++i
) {
3031 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_MARSHAL_SIZE
);
3033 if (!is_valid_marshal_spec (ctx
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
]))
3034 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldMarshal row %d NativeType field 0x%08x", i
, data
[MONO_FIELD_MARSHAL_NATIVE_TYPE
]));
3039 verify_decl_security_table (VerifyContext
*ctx
)
3041 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_DECLSECURITY
];
3042 guint32 data
[MONO_DECL_SECURITY_SIZE
];
3045 for (i
= 0; i
< table
->rows
; ++i
) {
3046 mono_metadata_decode_row (table
, i
, data
, MONO_DECL_SECURITY_SIZE
);
3048 if (!is_valid_coded_index (ctx
, HAS_DECL_SECURITY_DESC
, data
[MONO_DECL_SECURITY_PARENT
]))
3049 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d Parent field 0x%08x", i
, data
[MONO_DECL_SECURITY_PARENT
]));
3051 if (!get_coded_index_token (HAS_DECL_SECURITY_DESC
, data
[MONO_DECL_SECURITY_PARENT
]))
3052 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d Parent field is null", i
));
3054 if (!data
[MONO_DECL_SECURITY_PERMISSIONSET
])
3055 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field is null", i
));
3060 verify_decl_security_table_full (VerifyContext
*ctx
)
3062 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_DECLSECURITY
];
3063 guint32 data
[MONO_DECL_SECURITY_SIZE
];
3066 for (i
= 0; i
< table
->rows
; ++i
) {
3067 mono_metadata_decode_row (table
, i
, data
, MONO_DECL_SECURITY_SIZE
);
3069 if (!is_valid_permission_set (ctx
, data
[MONO_DECL_SECURITY_PERMISSIONSET
]))
3070 ADD_ERROR (ctx
, g_strdup_printf ("Invalid DeclSecurity row %d PermissionSet field 0x%08x", i
, data
[MONO_DECL_SECURITY_PERMISSIONSET
]));
3075 verify_class_layout_table (VerifyContext
*ctx
)
3077 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_CLASSLAYOUT
];
3078 guint32 data
[MONO_CLASS_LAYOUT_SIZE
];
3081 for (i
= 0; i
< table
->rows
; ++i
) {
3082 mono_metadata_decode_row (table
, i
, data
, MONO_CLASS_LAYOUT_SIZE
);
3084 if (!data
[MONO_CLASS_LAYOUT_PARENT
] || data
[MONO_CLASS_LAYOUT_PARENT
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3085 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ClassLayout row %d Parent field 0x%08x", i
, data
[MONO_TABLE_TYPEDEF
]));
3087 switch (data
[MONO_CLASS_LAYOUT_PACKING_SIZE
]) {
3099 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ClassLayout row %d Packing field %d", i
, data
[MONO_CLASS_LAYOUT_PACKING_SIZE
]));
3105 verify_field_layout_table (VerifyContext
*ctx
)
3107 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDLAYOUT
];
3108 guint32 data
[MONO_FIELD_LAYOUT_SIZE
];
3111 for (i
= 0; i
< table
->rows
; ++i
) {
3112 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_LAYOUT_SIZE
);
3114 if (!data
[MONO_FIELD_LAYOUT_FIELD
] || data
[MONO_FIELD_LAYOUT_FIELD
] > ctx
->image
->tables
[MONO_TABLE_FIELD
].rows
+ 1)
3115 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldLayout row %d Field field 0x%08x", i
, data
[MONO_FIELD_LAYOUT_FIELD
]));
3120 verify_standalonesig_table (VerifyContext
*ctx
)
3122 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_STANDALONESIG
];
3123 guint32 data
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3126 for (i
= 0; i
< table
->rows
; ++i
) {
3127 mono_metadata_decode_row (table
, i
, data
, MONO_STAND_ALONE_SIGNATURE_SIZE
);
3129 if (data
[MONO_STAND_ALONE_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_STAND_ALONE_SIGNATURE
], 1))
3130 ADD_ERROR (ctx
, g_strdup_printf ("Invalid StandAloneSig row %d invalid signature 0x%x", i
, data
[MONO_STAND_ALONE_SIGNATURE
]));
3135 verify_standalonesig_table_full (VerifyContext
*ctx
)
3137 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_STANDALONESIG
];
3138 guint32 data
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3141 for (i
= 0; i
< table
->rows
; ++i
) {
3142 mono_metadata_decode_row (table
, i
, data
, MONO_STAND_ALONE_SIGNATURE_SIZE
);
3144 if (!is_valid_standalonesig_blob (ctx
, data
[MONO_STAND_ALONE_SIGNATURE
]))
3145 ADD_ERROR (ctx
, g_strdup_printf ("Invalid StandAloneSig row %d Signature field 0x%08x", i
, data
[MONO_STAND_ALONE_SIGNATURE
]));
3150 verify_eventmap_table (VerifyContext
*ctx
)
3152 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EVENTMAP
];
3153 guint32 data
[MONO_EVENT_MAP_SIZE
], eventlist
= 0;
3156 for (i
= 0; i
< table
->rows
; ++i
) {
3157 mono_metadata_decode_row (table
, i
, data
, MONO_EVENT_MAP_SIZE
);
3159 if (!data
[MONO_EVENT_MAP_PARENT
] || data
[MONO_EVENT_MAP_PARENT
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3160 ADD_ERROR (ctx
, g_strdup_printf ("Invalid EventMap row %d Parent field 0x%08x", i
, data
[MONO_EVENT_MAP_PARENT
]));
3162 if (!data
[MONO_EVENT_MAP_EVENTLIST
] || data
[MONO_EVENT_MAP_EVENTLIST
] <= eventlist
)
3163 ADD_ERROR (ctx
, g_strdup_printf ("Invalid EventMap row %d EventList field %d", i
, data
[MONO_EVENT_MAP_EVENTLIST
]));
3165 eventlist
= data
[MONO_EVENT_MAP_EVENTLIST
];
3169 #define INVALID_EVENT_FLAGS_BITS ~((1 << 9) | (1 << 10))
3171 verify_event_table (VerifyContext
*ctx
)
3173 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EVENT
];
3174 guint32 data
[MONO_EVENT_SIZE
];
3177 for (i
= 0; i
< table
->rows
; ++i
) {
3178 mono_metadata_decode_row (table
, i
, data
, MONO_EVENT_SIZE
);
3180 if (data
[MONO_EVENT_FLAGS
] & INVALID_EVENT_FLAGS_BITS
)
3181 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d EventFlags field %08x", i
, data
[MONO_EVENT_FLAGS
]));
3183 if (!is_valid_non_empty_string (ctx
, data
[MONO_EVENT_NAME
]))
3184 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d Name field %08x", i
, data
[MONO_EVENT_NAME
]));
3186 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_EVENT_TYPE
]))
3187 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d EventType field %08x", i
, data
[MONO_EVENT_TYPE
]));
3192 verify_event_table_full (VerifyContext
*ctx
)
3194 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EVENT
];
3195 MonoTableInfo
*sema_table
= &ctx
->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
3196 guint32 data
[MONO_EVENT_SIZE
], sema_data
[MONO_METHOD_SEMA_SIZE
], token
;
3197 gboolean found_add
, found_remove
;
3200 for (i
= 0; i
< table
->rows
; ++i
) {
3201 mono_metadata_decode_row (table
, i
, data
, MONO_EVENT_SIZE
);
3203 token
= make_coded_token (HAS_SEMANTICS_DESC
, MONO_TABLE_EVENT
, i
);
3204 idx
= search_sorted_table (ctx
, MONO_TABLE_METHODSEMANTICS
, MONO_METHOD_SEMA_ASSOCIATION
, token
);
3206 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d has no AddOn or RemoveOn associated methods", i
));
3208 //first we move to the first row for this event
3210 if (mono_metadata_decode_row_col (sema_table
, idx
- 1, MONO_METHOD_SEMA_ASSOCIATION
) != token
)
3214 //now move forward looking for AddOn and RemoveOn rows
3215 found_add
= found_remove
= FALSE
;
3216 while (idx
< sema_table
->rows
) {
3217 mono_metadata_decode_row (sema_table
, idx
, sema_data
, MONO_METHOD_SEMA_SIZE
);
3218 if (sema_data
[MONO_METHOD_SEMA_ASSOCIATION
] != token
)
3220 if (sema_data
[MONO_METHOD_SEMA_SEMANTICS
] & METHOD_SEMANTIC_ADD_ON
)
3222 if (sema_data
[MONO_METHOD_SEMA_SEMANTICS
] & METHOD_SEMANTIC_REMOVE_ON
)
3223 found_remove
= TRUE
;
3224 if (found_add
&& found_remove
)
3230 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d has no AddOn associated method", i
));
3232 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Event row %d has no RemoveOn associated method", i
));
3237 verify_propertymap_table (VerifyContext
*ctx
)
3239 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_PROPERTYMAP
];
3240 guint32 data
[MONO_PROPERTY_MAP_SIZE
], propertylist
= 0;
3243 for (i
= 0; i
< table
->rows
; ++i
) {
3244 mono_metadata_decode_row (table
, i
, data
, MONO_PROPERTY_MAP_SIZE
);
3246 if (!data
[MONO_PROPERTY_MAP_PARENT
] || data
[MONO_PROPERTY_MAP_PARENT
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3247 ADD_ERROR (ctx
, g_strdup_printf ("Invalid PropertyMap row %d Parent field 0x%08x", i
, data
[MONO_PROPERTY_MAP_PARENT
]));
3249 if (!data
[MONO_PROPERTY_MAP_PROPERTY_LIST
] || data
[MONO_PROPERTY_MAP_PROPERTY_LIST
] <= propertylist
)
3250 ADD_ERROR (ctx
, g_strdup_printf ("Invalid PropertyMap row %d PropertyList field %d", i
, data
[MONO_PROPERTY_MAP_PROPERTY_LIST
]));
3252 propertylist
= data
[MONO_PROPERTY_MAP_PROPERTY_LIST
];
3256 #define INVALID_PROPERTY_FLAGS_BITS ~((1 << 9) | (1 << 10) | (1 << 12))
3258 verify_property_table (VerifyContext
*ctx
)
3260 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_PROPERTY
];
3261 guint32 data
[MONO_PROPERTY_SIZE
];
3264 for (i
= 0; i
< table
->rows
; ++i
) {
3265 mono_metadata_decode_row (table
, i
, data
, MONO_PROPERTY_SIZE
);
3267 if (data
[MONO_PROPERTY_FLAGS
] & INVALID_PROPERTY_FLAGS_BITS
)
3268 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d PropertyFlags field %08x", i
, data
[MONO_PROPERTY_FLAGS
]));
3270 if (!is_valid_non_empty_string (ctx
, data
[MONO_PROPERTY_NAME
]))
3271 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d Name field %08x", i
, data
[MONO_PROPERTY_NAME
]));
3273 if (!is_valid_property_sig_blob (ctx
, data
[MONO_PROPERTY_TYPE
]))
3274 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d Type field %08x", i
, data
[MONO_PROPERTY_TYPE
]));
3276 if ((data
[MONO_PROPERTY_FLAGS
] & PROPERTY_ATTRIBUTE_HAS_DEFAULT
) &&
3277 search_sorted_table (ctx
, MONO_TABLE_CONSTANT
, MONO_CONSTANT_PARENT
, make_coded_token (HAS_CONSTANT_DESC
, MONO_TABLE_PROPERTY
, i
)) == -1)
3278 ADD_ERROR (ctx
, g_strdup_printf ("Invalid Property row %d has HasDefault but there is no corresponding row in the Constant table", i
));
3284 verify_methodimpl_table (VerifyContext
*ctx
)
3286 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODIMPL
];
3287 guint32 data
[MONO_METHODIMPL_SIZE
];
3290 for (i
= 0; i
< table
->rows
; ++i
) {
3291 mono_metadata_decode_row (table
, i
, data
, MONO_METHODIMPL_SIZE
);
3293 if (!data
[MONO_METHODIMPL_CLASS
] || data
[MONO_METHODIMPL_CLASS
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
+ 1)
3294 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d Class field %08x", i
, data
[MONO_TABLE_TYPEDEF
]));
3296 if (!get_coded_index_token (METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_BODY
]))
3297 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i
, data
[MONO_METHODIMPL_BODY
]));
3299 if (!is_valid_coded_index (ctx
, METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_BODY
]))
3300 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodBody field %08x", i
, data
[MONO_METHODIMPL_BODY
]));
3302 if (!get_coded_index_token (METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_DECLARATION
]))
3303 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i
, data
[MONO_METHODIMPL_DECLARATION
]));
3305 if (!is_valid_coded_index (ctx
, METHODDEF_OR_REF_DESC
, data
[MONO_METHODIMPL_DECLARATION
]))
3306 ADD_ERROR (ctx
, g_strdup_printf ("Invalid MethodImpl row %d MethodDeclaration field %08x", i
, data
[MONO_METHODIMPL_DECLARATION
]));
3311 verify_moduleref_table (VerifyContext
*ctx
)
3313 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MODULEREF
];
3314 guint32 data
[MONO_MODULEREF_SIZE
];
3317 for (i
= 0; i
< table
->rows
; ++i
) {
3318 mono_metadata_decode_row (table
, i
, data
, MONO_MODULEREF_SIZE
);
3320 if (!is_valid_non_empty_string (ctx
, data
[MONO_MODULEREF_NAME
]))
3321 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ModuleRef row %d name field %08x", i
, data
[MONO_MODULEREF_NAME
]));
3326 verify_typespec_table (VerifyContext
*ctx
)
3328 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPESPEC
];
3329 guint32 data
[MONO_TYPESPEC_SIZE
];
3332 for (i
= 0; i
< table
->rows
; ++i
) {
3333 mono_metadata_decode_row (table
, i
, data
, MONO_TYPESPEC_SIZE
);
3335 if (data
[MONO_TYPESPEC_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_TYPESPEC_SIGNATURE
], 1))
3336 ADD_ERROR (ctx
, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i
, data
[MONO_TYPESPEC_SIGNATURE
]));
3341 verify_typespec_table_full (VerifyContext
*ctx
)
3343 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPESPEC
];
3344 guint32 data
[MONO_TYPESPEC_SIZE
];
3347 for (i
= 0; i
< table
->rows
; ++i
) {
3348 mono_metadata_decode_row (table
, i
, data
, MONO_TYPESPEC_SIZE
);
3349 ctx
->token
= (i
+ 1) | MONO_TOKEN_TYPE_SPEC
;
3350 if (!is_valid_typespec_blob (ctx
, data
[MONO_TYPESPEC_SIGNATURE
]))
3351 ADD_ERROR (ctx
, g_strdup_printf ("Invalid TypeSpec row %d Signature field %08x", i
, data
[MONO_TYPESPEC_SIGNATURE
]));
3356 #define INVALID_IMPLMAP_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 12) | (1 << 13))
3358 verify_implmap_table (VerifyContext
*ctx
)
3360 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_IMPLMAP
];
3361 guint32 data
[MONO_IMPLMAP_SIZE
], cconv
;
3364 for (i
= 0; i
< table
->rows
; ++i
) {
3365 mono_metadata_decode_row (table
, i
, data
, MONO_IMPLMAP_SIZE
);
3367 if (data
[MONO_IMPLMAP_FLAGS
] & INVALID_IMPLMAP_FLAGS_BITS
)
3368 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Flags field %08x", i
, data
[MONO_IMPLMAP_FLAGS
]));
3370 cconv
= data
[MONO_IMPLMAP_FLAGS
] & PINVOKE_ATTRIBUTE_CALL_CONV_MASK
;
3371 if (cconv
== 0 || cconv
== 0x0600 || cconv
== 0x0700)
3372 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Invalid call conv field %x", i
, cconv
));
3374 if (!is_valid_coded_index (ctx
, MEMBER_FORWARDED_DESC
, data
[MONO_IMPLMAP_MEMBER
]))
3375 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Invalid MemberForward token %x", i
, data
[MONO_IMPLMAP_MEMBER
]));
3377 if (get_coded_index_table (MEMBER_FORWARDED_DESC
, data
[MONO_IMPLMAP_MEMBER
]) != MONO_TABLE_METHOD
)
3378 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d only methods are supported token %x", i
, data
[MONO_IMPLMAP_MEMBER
]));
3380 if (!get_coded_index_token (MEMBER_FORWARDED_DESC
, data
[MONO_IMPLMAP_MEMBER
]))
3381 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d null token", i
));
3383 if (!is_valid_non_empty_string (ctx
, data
[MONO_IMPLMAP_NAME
]))
3384 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d ImportName Token %x", i
, data
[MONO_IMPLMAP_NAME
]));
3386 if (!data
[MONO_IMPLMAP_SCOPE
] || data
[MONO_IMPLMAP_SCOPE
] > ctx
->image
->tables
[MONO_TABLE_MODULEREF
].rows
)
3387 ADD_ERROR (ctx
, g_strdup_printf ("Invalid ImplMap row %d Invalid ImportScope token %x", i
, data
[MONO_IMPLMAP_SCOPE
]));
3392 verify_fieldrva_table (VerifyContext
*ctx
)
3394 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FIELDRVA
];
3395 guint32 data
[MONO_FIELD_RVA_SIZE
];
3398 for (i
= 0; i
< table
->rows
; ++i
) {
3399 mono_metadata_decode_row (table
, i
, data
, MONO_FIELD_RVA_SIZE
);
3401 if (!data
[MONO_FIELD_RVA_RVA
] || mono_cli_rva_image_map (ctx
->image
, data
[MONO_FIELD_RVA_RVA
]) == INVALID_ADDRESS
)
3402 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldRVA row %d RVA %08x", i
, data
[MONO_FIELD_RVA_RVA
]));
3404 if (!data
[MONO_FIELD_RVA_FIELD
] || data
[MONO_FIELD_RVA_FIELD
] > ctx
->image
->tables
[MONO_TABLE_FIELD
].rows
+ 1)
3405 ADD_ERROR (ctx
, g_strdup_printf ("Invalid FieldRVA row %d Field %08x", i
, data
[MONO_FIELD_RVA_FIELD
]));
3409 #define INVALID_ASSEMBLY_FLAGS_BITS ~((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 14) | (1 << 15))
3411 verify_assembly_table (VerifyContext
*ctx
)
3413 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_ASSEMBLY
];
3414 guint32 data
[MONO_ASSEMBLY_SIZE
], hash
;
3417 if (table
->rows
> 1)
3418 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table can have zero or one rows, but now %d", table
->rows
));
3420 for (i
= 0; i
< table
->rows
; ++i
) {
3421 mono_metadata_decode_row (table
, i
, data
, MONO_ASSEMBLY_SIZE
);
3423 hash
= data
[MONO_ASSEMBLY_HASH_ALG
];
3424 if (!(hash
== 0 || hash
== 0x8003 || hash
== 0x8004))
3425 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid HashAlgId %x", i
, hash
));
3427 if (data
[MONO_ASSEMBLY_FLAGS
] & INVALID_ASSEMBLY_FLAGS_BITS
)
3428 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid Flags %08x", i
, data
[MONO_ASSEMBLY_FLAGS
]));
3430 if (data
[MONO_ASSEMBLY_PUBLIC_KEY
] && !is_valid_blob_object (ctx
, data
[MONO_ASSEMBLY_PUBLIC_KEY
], 1))
3431 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid PublicKey %08x", i
, data
[MONO_ASSEMBLY_FLAGS
]));
3433 if (!is_valid_non_empty_string (ctx
, data
[MONO_ASSEMBLY_NAME
]))
3434 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid Name %08x", i
, data
[MONO_ASSEMBLY_NAME
]));
3436 if (data
[MONO_ASSEMBLY_CULTURE
] && !is_valid_string (ctx
, data
[MONO_ASSEMBLY_CULTURE
]))
3437 ADD_ERROR (ctx
, g_strdup_printf ("Assembly table row %d has invalid Culture %08x", i
, data
[MONO_ASSEMBLY_CULTURE
]));
3441 #define INVALID_ASSEMBLYREF_FLAGS_BITS ~((1 << 0) | (1 << 8) | (1 << 14) | (1 << 15))
3443 verify_assemblyref_table (VerifyContext
*ctx
)
3445 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
3446 guint32 data
[MONO_ASSEMBLYREF_SIZE
];
3449 for (i
= 0; i
< table
->rows
; ++i
) {
3450 mono_metadata_decode_row (table
, i
, data
, MONO_ASSEMBLYREF_SIZE
);
3452 if (data
[MONO_ASSEMBLYREF_FLAGS
] & INVALID_ASSEMBLYREF_FLAGS_BITS
)
3453 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid Flags %08x", i
, data
[MONO_ASSEMBLYREF_FLAGS
]));
3455 if (data
[MONO_ASSEMBLYREF_PUBLIC_KEY
] && !is_valid_blob_object (ctx
, data
[MONO_ASSEMBLYREF_PUBLIC_KEY
], 1))
3456 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid PublicKeyOrToken %08x", i
, data
[MONO_ASSEMBLYREF_PUBLIC_KEY
]));
3458 if (!is_valid_non_empty_string (ctx
, data
[MONO_ASSEMBLYREF_NAME
]))
3459 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid Name %08x", i
, data
[MONO_ASSEMBLYREF_NAME
]));
3461 if (data
[MONO_ASSEMBLYREF_CULTURE
] && !is_valid_string (ctx
, data
[MONO_ASSEMBLYREF_CULTURE
]))
3462 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid Culture %08x", i
, data
[MONO_ASSEMBLYREF_CULTURE
]));
3464 if (data
[MONO_ASSEMBLYREF_HASH_VALUE
] && !is_valid_blob_object (ctx
, data
[MONO_ASSEMBLYREF_HASH_VALUE
], 1))
3465 ADD_ERROR (ctx
, g_strdup_printf ("AssemblyRef table row %d has invalid HashValue %08x", i
, data
[MONO_ASSEMBLYREF_HASH_VALUE
]));
3469 #define INVALID_FILE_FLAGS_BITS ~(1)
3471 verify_file_table (VerifyContext
*ctx
)
3473 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_FILE
];
3474 guint32 data
[MONO_FILE_SIZE
];
3477 for (i
= 0; i
< table
->rows
; ++i
) {
3478 mono_metadata_decode_row (table
, i
, data
, MONO_FILE_SIZE
);
3480 if (data
[MONO_FILE_FLAGS
] & INVALID_FILE_FLAGS_BITS
)
3481 ADD_ERROR (ctx
, g_strdup_printf ("File table row %d has invalid Flags %08x", i
, data
[MONO_FILE_FLAGS
]));
3483 if (!is_valid_non_empty_string (ctx
, data
[MONO_FILE_NAME
]))
3484 ADD_ERROR (ctx
, g_strdup_printf ("File table row %d has invalid Name %08x", i
, data
[MONO_FILE_NAME
]));
3486 if (!data
[MONO_FILE_HASH_VALUE
] || !is_valid_blob_object (ctx
, data
[MONO_FILE_HASH_VALUE
], 1))
3487 ADD_ERROR (ctx
, g_strdup_printf ("File table row %d has invalid HashValue %08x", i
, data
[MONO_FILE_HASH_VALUE
]));
3491 #define INVALID_EXPORTED_TYPE_FLAGS_BITS (INVALID_TYPEDEF_FLAG_BITS & ~TYPE_ATTRIBUTE_FORWARDER)
3493 verify_exportedtype_table (VerifyContext
*ctx
)
3495 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3496 guint32 data
[MONO_EXP_TYPE_SIZE
];
3499 for (i
= 0; i
< table
->rows
; ++i
) {
3500 mono_metadata_decode_row (table
, i
, data
, MONO_EXP_TYPE_SIZE
);
3502 if (data
[MONO_EXP_TYPE_FLAGS
] & INVALID_EXPORTED_TYPE_FLAGS_BITS
)
3503 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid Flags %08x", i
, data
[MONO_EXP_TYPE_FLAGS
]));
3505 if (!is_valid_non_empty_string (ctx
, data
[MONO_EXP_TYPE_NAME
]))
3506 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid TypeName %08x", i
, data
[MONO_FILE_NAME
]));
3508 if (data
[MONO_EXP_TYPE_NAMESPACE
] && !is_valid_string (ctx
, data
[MONO_EXP_TYPE_NAMESPACE
]))
3509 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid TypeNamespace %08x", i
, data
[MONO_EXP_TYPE_NAMESPACE
]));
3511 if (!is_valid_coded_index (ctx
, IMPLEMENTATION_DESC
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]))
3512 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has invalid Implementation token %08x", i
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]));
3514 if (!get_coded_index_token (IMPLEMENTATION_DESC
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]))
3515 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has null Implementation token", i
));
3517 /*nested type can't have a namespace*/
3518 if (get_coded_index_table (IMPLEMENTATION_DESC
, data
[MONO_EXP_TYPE_IMPLEMENTATION
]) == MONO_TABLE_EXPORTEDTYPE
&& data
[MONO_EXP_TYPE_NAMESPACE
])
3519 ADD_ERROR (ctx
, g_strdup_printf ("ExportedType table row %d has denotes a nested type but has a non null TypeNamespace", i
));
3523 #define INVALID_MANIFEST_RESOURCE_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2))
3525 verify_manifest_resource_table (VerifyContext
*ctx
)
3527 MonoCLIImageInfo
*iinfo
= ctx
->image
->image_info
;
3528 MonoCLIHeader
*ch
= &iinfo
->cli_cli_header
;
3529 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
3530 guint32 data
[MONO_MANIFEST_SIZE
], impl_table
, token
, resources_size
;
3533 resources_size
= ch
->ch_resources
.size
;
3535 for (i
= 0; i
< table
->rows
; ++i
) {
3536 mono_metadata_decode_row (table
, i
, data
, MONO_MANIFEST_SIZE
);
3538 if (data
[MONO_MANIFEST_FLAGS
] & INVALID_MANIFEST_RESOURCE_FLAGS_BITS
)
3539 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Flags %08x", i
, data
[MONO_MANIFEST_FLAGS
]));
3541 if (data
[MONO_MANIFEST_FLAGS
] != 1 && data
[MONO_MANIFEST_FLAGS
] != 2)
3542 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Flags VisibilityMask %08x", i
, data
[MONO_MANIFEST_FLAGS
]));
3544 if (!is_valid_non_empty_string (ctx
, data
[MONO_MANIFEST_NAME
]))
3545 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Name %08x", i
, data
[MONO_MANIFEST_NAME
]));
3547 if (!is_valid_coded_index (ctx
, IMPLEMENTATION_DESC
, data
[MONO_MANIFEST_IMPLEMENTATION
]))
3548 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d has invalid Implementation token %08x", i
, data
[MONO_MANIFEST_IMPLEMENTATION
]));
3550 impl_table
= get_coded_index_table (IMPLEMENTATION_DESC
, data
[MONO_MANIFEST_IMPLEMENTATION
]);
3551 token
= get_coded_index_token (IMPLEMENTATION_DESC
, data
[MONO_MANIFEST_IMPLEMENTATION
]);
3553 if (impl_table
== MONO_TABLE_EXPORTEDTYPE
)
3554 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
])));
3556 if (impl_table
== MONO_TABLE_FILE
&& token
&& data
[MONO_MANIFEST_OFFSET
])
3557 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d points to a file but has non-zero offset", i
));
3559 if (!token
&& data
[MONO_MANIFEST_OFFSET
] >= resources_size
)
3560 ADD_ERROR (ctx
, g_strdup_printf ("ManifestResource table row %d invalid Offset field %08x ", i
, data
[MONO_MANIFEST_OFFSET
]));
3565 verify_nested_class_table (VerifyContext
*ctx
)
3567 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_NESTEDCLASS
];
3568 guint32 data
[MONO_NESTED_CLASS_SIZE
];
3571 for (i
= 0; i
< table
->rows
; ++i
) {
3572 mono_metadata_decode_row (table
, i
, data
, MONO_NESTED_CLASS_SIZE
);
3574 if (!data
[MONO_NESTED_CLASS_NESTED
] || data
[MONO_NESTED_CLASS_NESTED
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
)
3575 ADD_ERROR (ctx
, g_strdup_printf ("NestedClass table row %d has invalid NestedClass token %08x", i
, data
[MONO_NESTED_CLASS_NESTED
]));
3576 if (!data
[MONO_NESTED_CLASS_ENCLOSING
] || data
[MONO_NESTED_CLASS_ENCLOSING
] > ctx
->image
->tables
[MONO_TABLE_TYPEDEF
].rows
)
3577 ADD_ERROR (ctx
, g_strdup_printf ("NestedClass table row %d has invalid EnclosingClass token %08x", i
, data
[MONO_NESTED_CLASS_ENCLOSING
]));
3578 if (data
[MONO_NESTED_CLASS_ENCLOSING
] == data
[MONO_NESTED_CLASS_NESTED
])
3579 ADD_ERROR (ctx
, g_strdup_printf ("NestedClass table row %d has same token for NestedClass and EnclosingClass %08x", i
, data
[MONO_NESTED_CLASS_ENCLOSING
]));
3583 #define INVALID_GENERIC_PARAM_FLAGS_BITS ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
3585 verify_generic_param_table (VerifyContext
*ctx
)
3587 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_GENERICPARAM
];
3588 guint32 data
[MONO_GENERICPARAM_SIZE
], token
, last_token
= 0;
3589 int i
, param_number
= 0;
3591 for (i
= 0; i
< table
->rows
; ++i
) {
3592 mono_metadata_decode_row (table
, i
, data
, MONO_GENERICPARAM_SIZE
);
3594 if (data
[MONO_GENERICPARAM_FLAGS
] & INVALID_GENERIC_PARAM_FLAGS_BITS
)
3595 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid Flags token %08x", i
, data
[MONO_GENERICPARAM_FLAGS
]));
3597 if ((data
[MONO_GENERICPARAM_FLAGS
] & MONO_GEN_PARAM_VARIANCE_MASK
) == 0x3)
3598 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid VarianceMask 0x3", i
));
3600 if (!is_valid_non_empty_string (ctx
, data
[MONO_GENERICPARAM_NAME
]))
3601 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid Name token %08x", i
, data
[MONO_GENERICPARAM_NAME
]));
3603 token
= data
[MONO_GENERICPARAM_OWNER
];
3605 if (!is_valid_coded_index (ctx
, TYPE_OR_METHODDEF_DESC
, token
))
3606 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has invalid Owner token %08x", i
, token
));
3608 if (!get_coded_index_token (TYPE_OR_METHODDEF_DESC
, token
))
3609 ADD_ERROR (ctx
, g_strdup_printf ("GenericParam table row %d has null Owner token", i
));
3611 if (token
!= last_token
) {
3616 if (data
[MONO_GENERICPARAM_NUMBER
] != param_number
)
3617 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
));
3624 verify_method_spec_table (VerifyContext
*ctx
)
3626 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODSPEC
];
3627 guint32 data
[MONO_METHODSPEC_SIZE
];
3630 for (i
= 0; i
< table
->rows
; ++i
) {
3631 mono_metadata_decode_row (table
, i
, data
, MONO_METHODSPEC_SIZE
);
3633 if (!is_valid_coded_index (ctx
, METHODDEF_OR_REF_DESC
, data
[MONO_METHODSPEC_METHOD
]))
3634 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has invalid Method token %08x", i
, data
[MONO_METHODSPEC_METHOD
]));
3636 if (!get_coded_index_token (METHODDEF_OR_REF_DESC
, data
[MONO_METHODSPEC_METHOD
]))
3637 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has null Method token", i
));
3639 if (data
[MONO_METHODSPEC_SIGNATURE
] && !is_valid_blob_object (ctx
, data
[MONO_METHODSPEC_SIGNATURE
], 1))
3640 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has invalid signature token %08x", i
, data
[MONO_METHODSPEC_SIGNATURE
]));
3645 verify_method_spec_table_full (VerifyContext
*ctx
)
3647 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODSPEC
];
3648 guint32 data
[MONO_METHODSPEC_SIZE
];
3651 for (i
= 0; i
< table
->rows
; ++i
) {
3652 mono_metadata_decode_row (table
, i
, data
, MONO_METHODSPEC_SIZE
);
3654 if (!is_valid_methodspec_blob (ctx
, data
[MONO_METHODSPEC_SIGNATURE
]))
3655 ADD_ERROR (ctx
, g_strdup_printf ("MethodSpec table row %d has invalid Instantiation token %08x", i
, data
[MONO_METHODSPEC_SIGNATURE
]));
3660 verify_generic_param_constraint_table (VerifyContext
*ctx
)
3662 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
3663 guint32 data
[MONO_GENPARCONSTRAINT_SIZE
];
3665 guint32 last_owner
= 0, last_constraint
= 0;
3667 for (i
= 0; i
< table
->rows
; ++i
) {
3668 mono_metadata_decode_row (table
, i
, data
, MONO_GENPARCONSTRAINT_SIZE
);
3670 if (!data
[MONO_GENPARCONSTRAINT_GENERICPAR
] || data
[MONO_GENPARCONSTRAINT_GENERICPAR
] > ctx
->image
->tables
[MONO_TABLE_GENERICPARAM
].rows
)
3671 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has invalid Owner token %08x", i
, data
[MONO_GENPARCONSTRAINT_GENERICPAR
]));
3673 if (!is_valid_coded_index (ctx
, TYPEDEF_OR_REF_DESC
, data
[MONO_GENPARCONSTRAINT_CONSTRAINT
]))
3674 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has invalid Constraint token %08x", i
, data
[MONO_GENPARCONSTRAINT_CONSTRAINT
]));
3676 if (!get_coded_index_token (TYPEDEF_OR_REF_DESC
, data
[MONO_GENPARCONSTRAINT_CONSTRAINT
]))
3677 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has null Constraint token", i
));
3679 if (last_owner
> data
[MONO_GENPARCONSTRAINT_GENERICPAR
])
3680 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d is not properly sorted. Previous value of the owner column is 0x%08x current value is 0x%08x", i
, last_owner
, data
[MONO_GENPARCONSTRAINT_GENERICPAR
]));
3682 if (last_owner
== data
[MONO_GENPARCONSTRAINT_GENERICPAR
]) {
3683 if (last_constraint
== data
[MONO_GENPARCONSTRAINT_CONSTRAINT
])
3684 ADD_ERROR (ctx
, g_strdup_printf ("GenericParamConstraint table row %d has duplicate constraint 0x%08x", i
, last_constraint
));
3686 last_owner
= data
[MONO_GENPARCONSTRAINT_GENERICPAR
];
3688 last_constraint
= data
[MONO_GENPARCONSTRAINT_CONSTRAINT
];
3695 const char *name_space
;
3696 guint32 resolution_scope
;
3700 typedef_hash (gconstpointer _key
)
3702 const TypeDefUniqueId
*key
= (const TypeDefUniqueId
*)_key
;
3703 return g_str_hash (key
->name
) ^ g_str_hash (key
->name_space
) ^ key
->resolution_scope
; /*XXX better salt the int key*/
3707 typedef_equals (gconstpointer _a
, gconstpointer _b
)
3709 const TypeDefUniqueId
*a
= (const TypeDefUniqueId
*)_a
;
3710 const TypeDefUniqueId
*b
= (const TypeDefUniqueId
*)_b
;
3711 return !strcmp (a
->name
, b
->name
) && !strcmp (a
->name_space
, b
->name_space
) && a
->resolution_scope
== b
->resolution_scope
;
3715 verify_typedef_table_global_constraints (VerifyContext
*ctx
)
3718 guint32 data
[MONO_TYPEDEF_SIZE
];
3719 guint32 nested_data
[MONO_NESTED_CLASS_SIZE
];
3720 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEDEF
];
3721 MonoTableInfo
*nested_table
= &ctx
->image
->tables
[MONO_TABLE_NESTEDCLASS
];
3722 GHashTable
*unique_types
= g_hash_table_new_full (&typedef_hash
, &typedef_equals
, g_free
, NULL
);
3724 for (i
= 0; i
< table
->rows
; ++i
) {
3726 TypeDefUniqueId
*type
= g_new (TypeDefUniqueId
, 1);
3727 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEDEF_SIZE
);
3729 type
->name
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEDEF_NAME
]);
3730 type
->name_space
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEDEF_NAMESPACE
]);
3731 type
->resolution_scope
= 0;
3733 visibility
= data
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3734 if (visibility
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visibility
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
) {
3735 int res
= search_sorted_table (ctx
, MONO_TABLE_NESTEDCLASS
, MONO_NESTED_CLASS_NESTED
, i
+ 1);
3736 g_assert (res
>= 0);
3738 mono_metadata_decode_row (nested_table
, res
, nested_data
, MONO_NESTED_CLASS_SIZE
);
3739 type
->resolution_scope
= nested_data
[MONO_NESTED_CLASS_ENCLOSING
];
3742 if (g_hash_table_lookup (unique_types
, type
)) {
3743 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
));
3744 g_hash_table_destroy (unique_types
);
3748 g_hash_table_insert (unique_types
, type
, GUINT_TO_POINTER (1));
3751 g_hash_table_destroy (unique_types
);
3755 verify_typeref_table_global_constraints (VerifyContext
*ctx
)
3758 guint32 data
[MONO_TYPEREF_SIZE
];
3759 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_TYPEREF
];
3760 GHashTable
*unique_types
= g_hash_table_new_full (&typedef_hash
, &typedef_equals
, g_free
, NULL
);
3762 for (i
= 0; i
< table
->rows
; ++i
) {
3763 TypeDefUniqueId
*type
= g_new (TypeDefUniqueId
, 1);
3764 mono_metadata_decode_row (table
, i
, data
, MONO_TYPEREF_SIZE
);
3766 type
->resolution_scope
= data
[MONO_TYPEREF_SCOPE
];
3767 type
->name
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEREF_NAME
]);
3768 type
->name_space
= mono_metadata_string_heap (ctx
->image
, data
[MONO_TYPEREF_NAMESPACE
]);
3770 if (g_hash_table_lookup (unique_types
, type
)) {
3771 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
));
3772 g_hash_table_destroy (unique_types
);
3776 g_hash_table_insert (unique_types
, type
, GUINT_TO_POINTER (1));
3779 g_hash_table_destroy (unique_types
);
3784 guint32 method_declaration
;
3785 } MethodImplUniqueId
;
3788 methodimpl_hash (gconstpointer _key
)
3790 const MethodImplUniqueId
*key
= (const MethodImplUniqueId
*)_key
;
3791 return key
->klass
^ key
->method_declaration
;
3795 methodimpl_equals (gconstpointer _a
, gconstpointer _b
)
3797 const MethodImplUniqueId
*a
= (const MethodImplUniqueId
*)_a
;
3798 const MethodImplUniqueId
*b
= (const MethodImplUniqueId
*)_b
;
3799 return a
->klass
== b
->klass
&& a
->method_declaration
== b
->method_declaration
;
3803 verify_methodimpl_table_global_constraints (VerifyContext
*ctx
)
3806 guint32 data
[MONO_METHODIMPL_SIZE
];
3807 MonoTableInfo
*table
= &ctx
->image
->tables
[MONO_TABLE_METHODIMPL
];
3808 GHashTable
*unique_impls
= g_hash_table_new_full (&methodimpl_hash
, &methodimpl_equals
, g_free
, NULL
);
3810 for (i
= 0; i
< table
->rows
; ++i
) {
3811 MethodImplUniqueId
*impl
= g_new (MethodImplUniqueId
, 1);
3812 mono_metadata_decode_row (table
, i
, data
, MONO_METHODIMPL_SIZE
);
3814 impl
->klass
= data
[MONO_METHODIMPL_CLASS
];
3815 impl
->method_declaration
= data
[MONO_METHODIMPL_DECLARATION
];
3817 if (g_hash_table_lookup (unique_impls
, impl
)) {
3818 ADD_ERROR_NO_RETURN (ctx
, g_strdup_printf ("MethodImpl table row %d has duplicate for tuple (0x%x, 0x%x)", i
, impl
->klass
, impl
->method_declaration
));
3819 g_hash_table_destroy (unique_impls
);
3823 g_hash_table_insert (unique_impls
, impl
, GUINT_TO_POINTER (1));
3826 g_hash_table_destroy (unique_impls
);
3831 verify_tables_data_global_constraints (VerifyContext
*ctx
)
3833 verify_typedef_table_global_constraints (ctx
);
3837 verify_tables_data_global_constraints_full (VerifyContext
*ctx
)
3839 verify_typeref_table (ctx
);
3840 verify_typeref_table_global_constraints (ctx
);
3841 verify_methodimpl_table_global_constraints (ctx
);
3845 verify_tables_data (VerifyContext
*ctx
)
3847 OffsetAndSize tables_area
= get_metadata_stream (ctx
, &ctx
->image
->heap_tables
);
3848 guint32 size
= 0, tables_offset
;
3851 for (i
= 0; i
< 0x2D; ++i
) {
3852 MonoTableInfo
*table
= &ctx
->image
->tables
[i
];
3854 tmp_size
= size
+ (guint32
)table
->row_size
* (guint32
)table
->rows
;
3855 if (tmp_size
< size
) {
3863 ADD_ERROR (ctx
, g_strdup_printf ("table space is either empty or overflowed"));
3865 tables_offset
= ctx
->image
->tables_base
- ctx
->data
;
3866 if (!bounds_check_offset (&tables_area
, tables_offset
, size
))
3867 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
)));
3869 verify_module_table (ctx
);
3871 /*Obfuscators love to place broken stuff in the typeref table
3872 verify_typeref_table (ctx);
3874 verify_typedef_table (ctx
);
3876 verify_field_table (ctx
);
3878 verify_method_table (ctx
);
3880 verify_param_table (ctx
);
3882 verify_interfaceimpl_table (ctx
);
3884 verify_memberref_table (ctx
);
3886 verify_constant_table (ctx
);
3888 verify_cattr_table (ctx
);
3890 verify_field_marshal_table (ctx
);
3892 verify_decl_security_table (ctx
);
3894 verify_class_layout_table (ctx
);
3896 verify_field_layout_table (ctx
);
3898 verify_standalonesig_table (ctx
);
3900 verify_eventmap_table (ctx
);
3902 verify_event_table (ctx
);
3904 verify_propertymap_table (ctx
);
3906 verify_property_table (ctx
);
3908 verify_methodimpl_table (ctx
);
3910 verify_moduleref_table (ctx
);
3912 verify_typespec_table (ctx
);
3914 verify_implmap_table (ctx
);
3916 verify_fieldrva_table (ctx
);
3918 verify_assembly_table (ctx
);
3920 verify_assemblyref_table (ctx
);
3922 verify_file_table (ctx
);
3924 verify_exportedtype_table (ctx
);
3926 verify_manifest_resource_table (ctx
);
3928 verify_nested_class_table (ctx
);
3930 verify_generic_param_table (ctx
);
3932 verify_method_spec_table (ctx
);
3934 verify_generic_param_constraint_table (ctx
);
3936 verify_tables_data_global_constraints (ctx
);
3940 init_verify_context (VerifyContext
*ctx
, MonoImage
*image
)
3942 memset (ctx
, 0, sizeof (VerifyContext
));
3944 ctx
->report_error
= TRUE
;
3945 ctx
->report_warning
= FALSE
; //export this setting in the API
3947 ctx
->size
= m_image_get_raw_data_len (image
);
3948 ctx
->data
= m_image_get_raw_data (image
);
3952 cleanup_context (VerifyContext
*ctx
, MonoError
*error
)
3954 g_free (ctx
->sections
);
3956 MonoVerifyInfo
*info
= (MonoVerifyInfo
*)ctx
->errors
->data
;
3957 mono_error_set_bad_image (error
, ctx
->image
, "%s", info
->message
);
3958 mono_free_verify_list (ctx
->errors
);
3964 mono_verifier_verify_pe_data (MonoImage
*image
, MonoError
*error
)
3970 if (!mono_verifier_is_enabled_for_image (image
))
3973 init_verify_context (&ctx
, image
);
3974 ctx
.stage
= STAGE_PE
;
3976 verify_msdos_header (&ctx
);
3978 verify_pe_header (&ctx
);
3980 verify_pe_optional_header (&ctx
);
3982 load_section_table (&ctx
);
3984 load_data_directories (&ctx
);
3986 verify_import_table (&ctx
);
3988 /*No need to check the IAT directory entry, it's content is indirectly verified by verify_import_table*/
3989 verify_resources_table (&ctx
);
3992 return cleanup_context (&ctx
, error
);
3996 mono_verifier_verify_cli_data (MonoImage
*image
, MonoError
*error
)
4002 if (!mono_verifier_is_enabled_for_image (image
))
4005 init_verify_context (&ctx
, image
);
4006 ctx
.stage
= STAGE_CLI
;
4008 verify_cli_header (&ctx
);
4010 verify_metadata_header (&ctx
);
4012 verify_tables_schema (&ctx
);
4015 return cleanup_context (&ctx
, error
);
4020 * Verifies basic table constraints such as global table invariants (sorting, field monotonicity, etc).
4021 * Other verification checks are meant to be done lazily by the runtime. Those include:
4022 * blob items (signatures, method headers, custom attributes, etc)
4023 * type semantics related
4025 * stuff that should not block other pieces from running such as bad types/methods/fields/etc.
4027 * The whole idea is that if this succeed the runtime is free to play around safely but any complex
4028 * operation still need more checking.
4031 mono_verifier_verify_table_data (MonoImage
*image
, MonoError
*error
)
4037 if (!mono_verifier_is_enabled_for_image (image
))
4040 init_verify_context (&ctx
, image
);
4041 ctx
.stage
= STAGE_TABLES
;
4043 verify_tables_data (&ctx
);
4045 return cleanup_context (&ctx
, error
);
4050 * Verifies all other constraints.
4053 mono_verifier_verify_full_table_data (MonoImage
*image
, MonoError
*error
)
4059 if (!mono_verifier_is_enabled_for_image (image
))
4062 init_verify_context (&ctx
, image
);
4063 ctx
.stage
= STAGE_TABLES
;
4065 verify_typedef_table_full (&ctx
);
4067 verify_field_table_full (&ctx
);
4069 verify_method_table_full (&ctx
);
4071 verify_memberref_table_full (&ctx
);
4073 verify_cattr_table_full (&ctx
);
4075 verify_field_marshal_table_full (&ctx
);
4077 verify_decl_security_table_full (&ctx
);
4079 verify_standalonesig_table_full (&ctx
);
4081 verify_event_table_full (&ctx
);
4083 verify_typespec_table_full (&ctx
);
4085 verify_method_spec_table_full (&ctx
);
4087 verify_tables_data_global_constraints_full (&ctx
);
4090 return cleanup_context (&ctx
, error
);
4094 mono_verifier_verify_field_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4100 if (!mono_verifier_is_enabled_for_image (image
))
4103 init_verify_context (&ctx
, image
);
4104 ctx
.stage
= STAGE_TABLES
;
4106 is_valid_field_signature (&ctx
, offset
);
4107 return cleanup_context (&ctx
, error
);
4111 mono_verifier_verify_method_header (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4114 guint32 locals_token
;
4118 if (!mono_verifier_is_enabled_for_image (image
))
4121 init_verify_context (&ctx
, image
);
4122 ctx
.stage
= STAGE_TABLES
;
4124 is_valid_method_header (&ctx
, offset
, &locals_token
);
4126 guint32 sig_offset
= mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_STANDALONESIG
], locals_token
- 1, MONO_STAND_ALONE_SIGNATURE
);
4127 is_valid_standalonesig_blob (&ctx
, sig_offset
);
4130 return cleanup_context (&ctx
, error
);
4134 mono_verifier_verify_method_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4140 if (!mono_verifier_is_enabled_for_image (image
))
4143 init_verify_context (&ctx
, image
);
4144 ctx
.stage
= STAGE_TABLES
;
4146 is_valid_method_signature (&ctx
, offset
);
4147 /*XXX This returns a bad image exception, it might be the case that the right exception is method load.*/
4148 return cleanup_context (&ctx
, error
);
4152 mono_verifier_verify_memberref_method_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4158 if (!mono_verifier_is_enabled_for_image (image
))
4161 init_verify_context (&ctx
, image
);
4162 ctx
.stage
= STAGE_TABLES
;
4164 is_valid_memberref_method_signature (&ctx
, offset
);
4165 return cleanup_context (&ctx
, error
);
4169 mono_verifier_verify_memberref_field_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4175 if (!mono_verifier_is_enabled_for_image (image
))
4178 init_verify_context (&ctx
, image
);
4179 ctx
.stage
= STAGE_TABLES
;
4181 is_valid_field_signature (&ctx
, offset
);
4182 return cleanup_context (&ctx
, error
);
4186 mono_verifier_verify_standalone_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4192 if (!mono_verifier_is_enabled_for_image (image
))
4195 init_verify_context (&ctx
, image
);
4196 ctx
.stage
= STAGE_TABLES
;
4198 is_valid_standalonesig_blob (&ctx
, offset
);
4199 return cleanup_context (&ctx
, error
);
4203 mono_verifier_verify_typespec_signature (MonoImage
*image
, guint32 offset
, guint32 token
, MonoError
*error
)
4210 if (!mono_verifier_is_enabled_for_image (image
))
4213 init_verify_context (&ctx
, image
);
4214 ctx
.stage
= STAGE_TABLES
;
4217 is_valid_typespec_blob (&ctx
, offset
);
4218 return cleanup_context (&ctx
, error
);
4222 mono_verifier_verify_methodspec_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4228 if (!mono_verifier_is_enabled_for_image (image
))
4231 init_verify_context (&ctx
, image
);
4232 ctx
.stage
= STAGE_TABLES
;
4234 is_valid_methodspec_blob (&ctx
, offset
);
4235 return cleanup_context (&ctx
, error
);
4239 verify_user_string (VerifyContext
*ctx
, guint32 offset
)
4241 OffsetAndSize heap_us
= get_metadata_stream (ctx
, &ctx
->image
->heap_us
);
4242 guint32 entry_size
, bytes
;
4244 if (heap_us
.size
< offset
)
4245 ADD_ERROR (ctx
, g_strdup ("User string offset beyond heap_us size"));
4247 if (!decode_value (ctx
->data
+ offset
+ heap_us
.offset
, heap_us
.size
- heap_us
.offset
, &entry_size
, &bytes
))
4248 ADD_ERROR (ctx
, g_strdup ("Could not decode user string blob size"));
4250 if (CHECK_ADD4_OVERFLOW_UN (entry_size
, bytes
))
4251 ADD_ERROR (ctx
, g_strdup ("User string size overflow"));
4253 entry_size
+= bytes
;
4255 if (ADD_IS_GREATER_OR_OVF (offset
, entry_size
, heap_us
.size
))
4256 ADD_ERROR (ctx
, g_strdup ("User string oveflow heap_us"));
4260 mono_verifier_verify_string_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4266 if (!mono_verifier_is_enabled_for_image (image
))
4269 init_verify_context (&ctx
, image
);
4270 ctx
.stage
= STAGE_TABLES
;
4272 verify_user_string (&ctx
, offset
);
4274 return cleanup_context (&ctx
, error
);
4278 mono_verifier_verify_cattr_blob (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4284 if (!mono_verifier_is_enabled_for_image (image
))
4287 init_verify_context (&ctx
, image
);
4288 ctx
.stage
= STAGE_TABLES
;
4290 is_valid_cattr_blob (&ctx
, offset
);
4292 return cleanup_context (&ctx
, error
);
4296 //FIXME this should raise a System.Reflection.CustomAttributeFormatException
4298 mono_verifier_verify_cattr_content (MonoImage
*image
, MonoMethod
*ctor
, const guchar
*data
, guint32 size
, MonoError
*error
)
4304 if (!mono_verifier_is_enabled_for_image (image
))
4307 init_verify_context (&ctx
, image
);
4308 ctx
.stage
= STAGE_TABLES
;
4310 is_valid_cattr_content (&ctx
, ctor
, (const char*)data
, size
);
4312 return cleanup_context (&ctx
, error
);
4316 mono_verifier_is_sig_compatible (MonoImage
*image
, MonoMethod
*method
, MonoMethodSignature
*signature
)
4318 MonoMethodSignature
*original_sig
;
4319 if (!mono_verifier_is_enabled_for_image (image
))
4322 original_sig
= mono_method_signature_internal (method
);
4323 if (original_sig
->call_convention
== MONO_CALL_VARARG
) {
4324 if (original_sig
->hasthis
!= signature
->hasthis
)
4326 if (original_sig
->call_convention
!= signature
->call_convention
)
4328 if (original_sig
->explicit_this
!= signature
->explicit_this
)
4330 if (original_sig
->pinvoke
!= signature
->pinvoke
)
4332 if (original_sig
->sentinelpos
!= signature
->sentinelpos
)
4334 } else if (!mono_metadata_signature_equal (signature
, original_sig
)) {
4342 mono_verifier_verify_typeref_row (MonoImage
*image
, guint32 row
, MonoError
*error
)
4344 MonoTableInfo
*table
= &image
->tables
[MONO_TABLE_TYPEREF
];
4345 guint32 data
[MONO_TYPEREF_SIZE
];
4349 if (!mono_verifier_is_enabled_for_image (image
))
4352 if (row
>= table
->rows
) {
4353 mono_error_set_bad_image (error
, image
, "Invalid typeref row %d - table has %d rows", row
, table
->rows
);
4357 mono_metadata_decode_row (table
, row
, data
, MONO_TYPEREF_SIZE
);
4358 if (!is_valid_coded_index_with_image (image
, RES_SCOPE_DESC
, data
[MONO_TYPEREF_SCOPE
])) {
4359 mono_error_set_bad_image (error
, image
, "Invalid typeref row %d coded index 0x%08x", row
, data
[MONO_TYPEREF_SCOPE
]);
4363 if (!get_coded_index_token (RES_SCOPE_DESC
, data
[MONO_TYPEREF_SCOPE
])) {
4364 mono_error_set_bad_image (error
, image
, "The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", row
);
4368 if (!data
[MONO_TYPEREF_NAME
] || !is_valid_string_full_with_image (image
, data
[MONO_TYPEREF_NAME
], FALSE
)) {
4369 mono_error_set_bad_image (error
, image
, "Invalid typeref row %d name token 0x%08x", row
, data
[MONO_TYPEREF_NAME
]);
4373 if (data
[MONO_TYPEREF_NAMESPACE
] && !is_valid_string_full_with_image (image
, data
[MONO_TYPEREF_NAMESPACE
], FALSE
)) {
4374 mono_error_set_bad_image (error
, image
, "Invalid typeref row %d namespace token 0x%08x", row
, data
[MONO_TYPEREF_NAMESPACE
]);
4381 /*Perform additional verification including metadata ones*/
4383 mono_verifier_verify_methodimpl_row (MonoImage
*image
, guint32 row
, MonoError
*error
)
4385 MonoMethod
*declaration
, *body
;
4386 MonoMethodSignature
*body_sig
, *decl_sig
;
4387 MonoTableInfo
*table
= &image
->tables
[MONO_TABLE_METHODIMPL
];
4388 guint32 data
[MONO_METHODIMPL_SIZE
];
4392 if (!mono_verifier_is_enabled_for_image (image
))
4395 if (row
>= table
->rows
) {
4396 mono_error_set_bad_image (error
, image
, "Invalid methodimpl row %d - table has %d rows", row
, table
->rows
);
4400 mono_metadata_decode_row (table
, row
, data
, MONO_METHODIMPL_SIZE
);
4402 body
= mono_method_from_method_def_or_ref (image
, data
[MONO_METHODIMPL_BODY
], NULL
, error
);
4406 declaration
= mono_method_from_method_def_or_ref (image
, data
[MONO_METHODIMPL_DECLARATION
], NULL
, error
);
4411 mono_class_setup_supertypes (class);
4412 if (!mono_class_has_parent (class, body->klass)) {
4413 mono_error_set_bad_image (error, image, "Invalid methodimpl body doesn't belong to parent for row %x", row);
4417 if (!(body_sig
= mono_method_signature_checked (body
, error
))) {
4421 if (!(decl_sig
= mono_method_signature_checked (declaration
, error
))) {
4425 if (!mono_verifier_is_signature_compatible (decl_sig
, body_sig
)) {
4426 mono_error_set_bad_image (error
, image
, "Invalid methodimpl body signature not compatible with declaration row %x", row
);
4435 mono_verifier_verify_table_data (MonoImage
*image
, MonoError
*error
)
4442 mono_verifier_verify_cli_data (MonoImage
*image
, MonoError
*error
)
4449 mono_verifier_verify_pe_data (MonoImage
*image
, MonoError
*error
)
4456 mono_verifier_verify_full_table_data (MonoImage
*image
, MonoError
*error
)
4463 mono_verifier_verify_field_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4470 mono_verifier_verify_method_header (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4477 mono_verifier_verify_method_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4484 mono_verifier_verify_standalone_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4491 mono_verifier_verify_typespec_signature (MonoImage
*image
, guint32 offset
, guint32 token
, MonoError
*error
)
4498 mono_verifier_verify_methodspec_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4505 mono_verifier_verify_string_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4512 mono_verifier_verify_cattr_blob (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4519 mono_verifier_verify_cattr_content (MonoImage
*image
, MonoMethod
*ctor
, const guchar
*data
, guint32 size
, MonoError
*error
)
4526 mono_verifier_is_sig_compatible (MonoImage
*image
, MonoMethod
*method
, MonoMethodSignature
*signature
)
4533 mono_verifier_verify_typeref_row (MonoImage
*image
, guint32 row
, MonoError
*error
)
4540 mono_verifier_verify_methodimpl_row (MonoImage
*image
, guint32 row
, MonoError
*error
)
4547 mono_verifier_verify_memberref_method_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4554 mono_verifier_verify_memberref_field_signature (MonoImage
*image
, guint32 offset
, MonoError
*error
)
4560 #endif /* DISABLE_VERIFIER */