X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fimage.c;h=0c507f5c1da1301a5ba886ac032240700bb0b143;hb=53ac1b026b125b8deab7d4be09e3ef7142f577d1;hp=4fc6f218e1708a0ccc7c676f069f8743ef2f277b;hpb=fe1f6c80bea4338a0f2d0b6974160194324b7d78;p=mono.git diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 4fc6f218e17..0c507f5c1da 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -27,7 +27,6 @@ #include "loader.h" #include "marshal.h" #include "coree.h" -#include #include #include #include @@ -46,6 +45,7 @@ #ifdef HAVE_UNISTD_H #include #endif +#include #define INVALID_ADDRESS 0xffffffff @@ -520,7 +520,7 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) image->heap_tables.size = read32 (ptr + 4); ptr += 8 + 3; image->uncompressed_metadata = TRUE; - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly '%s' has the non-standard metadata heap #-.\nRecompile it correctly (without the /incremental switch or in Release mode).\n", image->name); + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly '%s' has the non-standard metadata heap #-.\nRecompile it correctly (without the /incremental switch or in Release mode).", image->name); } else if (strncmp (ptr + 8, "#Pdb", 5) == 0) { image->heap_pdb.data = image->raw_metadata + read32 (ptr); image->heap_pdb.size = read32 (ptr + 4); @@ -594,6 +594,23 @@ load_tables (MonoImage *image) /* They must be the same */ g_assert ((const void *) image->tables_base == (const void *) rows); + if (image->heap_pdb.size) { + /* + * Obtain token sizes from the pdb stream. + */ + /* 24 = guid + entry point */ + int pos = 24; + image->referenced_tables = read64 (image->heap_pdb.data + pos); + pos += 8; + image->referenced_table_rows = g_new0 (int, 64); + for (int i = 0; i < 64; ++i) { + if (image->referenced_tables & ((guint64)1 << i)) { + image->referenced_table_rows [i] = read32 (image->heap_pdb.data + pos); + pos += 4; + } + } + } + mono_metadata_compute_table_bases (image); return TRUE; } @@ -674,7 +691,7 @@ mono_image_load_module_checked (MonoImage *image, int idx, MonoError *error) GList *list_iter, *valid_modules = NULL; MonoImageOpenStatus status; - mono_error_init (error); + error_init (error); if ((image->module_count == 0) || (idx > image->module_count || idx <= 0)) return NULL; @@ -721,7 +738,7 @@ mono_image_load_module_checked (MonoImage *image, int idx, MonoError *error) return NULL; } - image->modules [idx - 1] = image; + image->modules [idx - 1] = moduleImage; #ifdef HOST_WIN32 if (image->modules [idx - 1]->is_module_handle) @@ -1077,6 +1094,109 @@ install_pe_loader (void) mono_install_image_loader (&pe_loader); } +/* +Ignored assemblies. + +There are some assemblies we need to ignore because they include an implementation that doesn't work under mono. +Mono provides its own implementation of those assemblies so it's safe to do so. + +The ignored_assemblies list is generated using tools/nuget-hash-extractor and feeding the problematic nugets to it. + +Right now the list of nugets are the ones that provide the assemblies in $ignored_assemblies_names. + +This is to be removed once a proper fix is shipped through nuget. + +*/ + +typedef enum { + SYS_RT_INTEROP_RUNTIME_INFO = 0, //System.Runtime.InteropServices.RuntimeInformation + SYS_GLOBALIZATION_EXT = 1, //System.Globalization.Extensions + SYS_IO_COMPRESSION = 2, //System.IO.Compression + SYS_NET_HTTP = 3, //System.Net.Http + SYS_TEXT_ENC_CODEPAGES = 4, //System.Text.Encoding.CodePages + SYS_REF_DISP_PROXY = 5, //System.Reflection.DispatchProxy + SYS_VALUE_TUPLE = 6, //System.ValueTuple +} IgnoredAssemblyNames; + +typedef struct { + int hash; + int assembly_name; + const char guid [40]; +} IgnoredAssembly; + +const char *ignored_assemblies_names[] = { + "System.Runtime.InteropServices.RuntimeInformation.dll", + "System.Globalization.Extensions.dll", + "System.IO.Compression.dll", + "System.Net.Http.dll", + "System.Text.Encoding.CodePages.dll", + "System.Reflection.DispatchProxy.dll", + "System.ValueTuple.dll" +}; + +#define IGNORED_ASSEMBLY(HASH, NAME, GUID, VER_STR) { .hash = HASH, .assembly_name = NAME, .guid = GUID } + +static const IgnoredAssembly ignored_assemblies [] = { + IGNORED_ASSEMBLY (0x1136045D, SYS_GLOBALIZATION_EXT, "475DBF02-9F68-44F1-8FB5-C9F69F1BD2B1", "4.0.0 net46"), + IGNORED_ASSEMBLY (0x358C9723, SYS_GLOBALIZATION_EXT, "5FCD54F0-4B97-4259-875D-30E481F02EA2", "4.0.1 net46"), + IGNORED_ASSEMBLY (0x450A096A, SYS_GLOBALIZATION_EXT, "E9FCFF5B-4DE1-4BDC-9CE8-08C640FC78CC", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x1CBD59A2, SYS_IO_COMPRESSION, "44FCA06C-A510-4B3E-BDBF-D08D697EF65A", "4.1.0 net46"), + IGNORED_ASSEMBLY (0x5E393C29, SYS_IO_COMPRESSION, "3A58A219-266B-47C3-8BE8-4E4F394147AB", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x27726A90, SYS_NET_HTTP, "269B562C-CC15-4736-B1B1-68D4A43CAA98", "4.1.0 net46"), + IGNORED_ASSEMBLY (0x10CADA75, SYS_NET_HTTP, "EA2EC6DC-51DD-479C-BFC2-E713FB9E7E47", "4.1.1 net46"), + IGNORED_ASSEMBLY (0x8437178B, SYS_NET_HTTP, "C0E04D9C-70CF-48A6-A179-FBFD8CE69FD0", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x4A15555E, SYS_REF_DISP_PROXY, "E40AFEB4-CABE-4124-8412-B46AB79C92FD", "4.0.0 net46"), + IGNORED_ASSEMBLY (0xD20D9783, SYS_REF_DISP_PROXY, "2A69F0AD-B86B-40F2-8E4C-5B671E47479F", "4.0.1 netstandard1.3"), + IGNORED_ASSEMBLY (0xA33A7E68, SYS_REF_DISP_PROXY, "D4E8D2DB-BD65-4168-99EA-D2C1BDEBF9CC", "4.3.0 netstandard1.3"), + IGNORED_ASSEMBLY (0x46A4A1C5, SYS_RT_INTEROP_RUNTIME_INFO, "F13660F8-9D0D-419F-BA4E-315693DD26EA", "4.0.0 net45"), + IGNORED_ASSEMBLY (0xD07383BB, SYS_RT_INTEROP_RUNTIME_INFO, "DD91439F-3167-478E-BD2C-BF9C036A1395", "4.3.0 net45"), + IGNORED_ASSEMBLY (0x911D9EC3, SYS_TEXT_ENC_CODEPAGES, "C142254F-DEB5-46A7-AE43-6F10320D1D1F", "4.0.1 net46"), + IGNORED_ASSEMBLY (0xFA686A38, SYS_TEXT_ENC_CODEPAGES, "FD178CD4-EF4F-44D5-9C3F-812B1E25126B", "4.3.0 net46"), + IGNORED_ASSEMBLY (0x75B4B041, SYS_VALUE_TUPLE, "F81A4140-A898-4E2B-B6E9-55CE78C273EC", "4.3.0 netstandard1.0"), +}; + +/* +Equivalent C# code: + static void Main () { + string str = "..."; + int h = 5381; + for (int i = 0; i < str.Length; ++i) + h = ((h << 5) + h) ^ str[i]; + + Console.WriteLine ("{0:X}", h); + } +*/ +static int +hash_guid (const char *str) +{ + int h = 5381; + while (*str) { + h = ((h << 5) + h) ^ *str; + ++str; + } + + return h; +} + +static gboolean +is_problematic_image (MonoImage *image) +{ + int h = hash_guid (image->guid); + + //TODO make this more cache effiecient. + // Either sort by hash and bseach or use SoA and make the linear search more cache efficient. + for (int i = 0; i < G_N_ELEMENTS (ignored_assemblies); ++i) { + if (ignored_assemblies [i].hash == h && !strcmp (image->guid, ignored_assemblies [i].guid)) { + const char *needle = ignored_assemblies_names [ignored_assemblies [i].assembly_name]; + size_t needle_len = strlen (needle); + size_t asm_len = strlen (image->name); + if (asm_len > needle_len && !g_ascii_strcasecmp (image->name + (asm_len - needle_len), needle)) + return TRUE; + } + } + return FALSE; +} + static MonoImage * do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status, gboolean care_about_cli, gboolean care_about_pecoff) @@ -1132,6 +1252,16 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status, if (!mono_image_load_cli_data (image)) goto invalid_image; + if (!image->ref_only && is_problematic_image (image)) { + if (image->load_from_context) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Loading problematic image %s", image->name); + } else { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Denying load of problematic image %s", image->name); + *status = MONO_IMAGE_IMAGE_INVALID; + goto invalid_image; + } + } + if (image->loader == &pe_loader && !image->metadata_only && !mono_verifier_verify_table_data (image, &errors)) goto invalid_image; @@ -1159,7 +1289,7 @@ invalid_image: static MonoImage * do_mono_image_open (const char *fname, MonoImageOpenStatus *status, - gboolean care_about_cli, gboolean care_about_pecoff, gboolean refonly, gboolean metadata_only) + gboolean care_about_cli, gboolean care_about_pecoff, gboolean refonly, gboolean metadata_only, gboolean load_from_context) { MonoCLIImageInfo *iinfo; MonoImage *image; @@ -1203,6 +1333,7 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status, image->name = mono_path_resolve_symlinks (fname); image->ref_only = refonly; image->metadata_only = metadata_only; + image->load_from_context = load_from_context; image->ref_count = 1; /* if MONO_SECURITY_MODE_CORE_CLR is set then determine if this image is platform code */ image->core_clr_platform_code = mono_security_core_clr_determine_platform_image (image); @@ -1399,6 +1530,12 @@ mono_image_open_from_module_handle (HMODULE module_handle, char* fname, gboolean MonoImage * mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean refonly) +{ + return mono_image_open_a_lot (fname, status, refonly, FALSE); +} + +MonoImage * +mono_image_open_a_lot (const char *fname, MonoImageOpenStatus *status, gboolean refonly, gboolean load_from_context) { MonoImage *image; GHashTable *loaded_images = get_loaded_images_hash (refonly); @@ -1441,7 +1578,7 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r fname_utf16 = g_utf8_to_utf16 (absfname, -1, NULL, NULL, NULL); module_handle = MonoLoadImage (fname_utf16); if (status && module_handle == NULL) - last_error = GetLastError (); + last_error = mono_w32error_get_last (); /* mono_image_open_from_module_handle is called by _CorDllMain. */ image = g_hash_table_lookup (loaded_images, absfname); @@ -1498,7 +1635,7 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r mono_images_unlock (); // Image not loaded, load it now - image = do_mono_image_open (fname, status, TRUE, TRUE, refonly, FALSE); + image = do_mono_image_open (fname, status, TRUE, TRUE, refonly, FALSE, load_from_context); if (image == NULL) return NULL; @@ -1537,7 +1674,7 @@ mono_pe_file_open (const char *fname, MonoImageOpenStatus *status) { g_return_val_if_fail (fname != NULL, NULL); - return do_mono_image_open (fname, status, FALSE, TRUE, FALSE, FALSE); + return do_mono_image_open (fname, status, FALSE, TRUE, FALSE, FALSE, FALSE); } /** @@ -1554,7 +1691,7 @@ mono_image_open_raw (const char *fname, MonoImageOpenStatus *status) { g_return_val_if_fail (fname != NULL, NULL); - return do_mono_image_open (fname, status, FALSE, FALSE, FALSE, FALSE); + return do_mono_image_open (fname, status, FALSE, FALSE, FALSE, FALSE, FALSE); } /* @@ -1565,7 +1702,7 @@ mono_image_open_raw (const char *fname, MonoImageOpenStatus *status) MonoImage * mono_image_open_metadata_only (const char *fname, MonoImageOpenStatus *status) { - return do_mono_image_open (fname, status, TRUE, TRUE, FALSE, TRUE); + return do_mono_image_open (fname, status, TRUE, TRUE, FALSE, TRUE, FALSE); } void @@ -2221,7 +2358,7 @@ mono_image_load_file_for_image_checked (MonoImage *image, int fileidx, MonoError const char *fname; guint32 fname_id; - mono_error_init (error); + error_init (error); if (fileidx < 1 || fileidx > t->rows) return NULL; @@ -2477,6 +2614,8 @@ mono_image_has_authenticode_entry (MonoImage *image) { MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info; MonoDotNetHeader *header = &iinfo->cli_header; + if (!header) + return FALSE; MonoPEDirEntry *de = &header->datadir.pe_certificate_table; // the Authenticode "pre" (non ASN.1) header is 8 bytes long return ((de->rva != 0) && (de->size > 8));