From 1eb40e251b54d41b8998e78353b680801257d340 Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Fri, 18 Sep 2020 13:50:31 -0400 Subject: [PATCH 1/3] Add LoaderLinkTest --- .../LoaderLinkTest.Dynamic.csproj | 11 +++++++ .../SharedInterfaceImplementation.cs | 14 ++++++++ .../LoaderLinkTest.Shared/ISharedInterface.cs | 12 +++++++ .../LoaderLinkTest.Shared.csproj | 8 +++++ .../tests/LoaderLinkTest.cs | 33 +++++++++++++++++++ .../tests/System.Runtime.Loader.Tests.csproj | 5 ++- 6 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj new file mode 100644 index 00000000000000..7fdc93128a864e --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj @@ -0,0 +1,11 @@ + + + $(NetCoreAppCurrent) + + + + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs new file mode 100644 index 00000000000000..3087d8a6daa9cf --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +using LoaderLinkTest.Shared; + +namespace LoaderLinkTest.Dynamic +{ + public class SharedInterfaceImplementation : ISharedInterface + { + public string TestString => "Hello"; + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs new file mode 100644 index 00000000000000..3c381e1bc2d3c1 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace LoaderLinkTest.Shared +{ + public interface ISharedInterface + { + string TestString { get; } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj new file mode 100644 index 00000000000000..2adb5cb89d9747 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj @@ -0,0 +1,8 @@ + + + $(NetCoreAppCurrent) + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs new file mode 100644 index 00000000000000..c7daa91333664a --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using Xunit; + +using LoaderLinkTest.Shared; + +namespace LoaderLinkTest +{ + public class LoaderLinkTest + { + [Fact] + public static void EnsureTypesLinked() // https://github.com/dotnet/runtime/issues/42207 + { + string parentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + byte[] bytes = File.ReadAllBytes(Path.Combine(parentDir != null ? parentDir : "/", "LoaderLinkTest.Dynamic.dll")); + Assembly asm = Assembly.Load(bytes); + var dynamicType = asm.GetType("LoaderLinkTest.Dynamic.SharedInterfaceImplementation", true); + var sharedInterface = dynamicType.GetInterfaces().First(e => e.Name == nameof(ISharedInterface)); + Assert.Equal(typeof(ISharedInterface).Assembly, sharedInterface.Assembly); + Assert.Equal(typeof(ISharedInterface), sharedInterface); + + var instance = Activator.CreateInstance(dynamicType); + Assert.True(instance is ISharedInterface); + + Assert.NotNull(((ISharedInterface)instance).TestString); // cast should not fail + } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index f43714d9365d9a..ae825641dab5e3 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -14,6 +14,7 @@ + @@ -29,8 +30,10 @@ + + - \ No newline at end of file + From 09de6b7b21660e086acd86f6da697080f53b572b Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Fri, 18 Sep 2020 13:50:51 -0400 Subject: [PATCH 2/3] Disable LoadFromAssemblyName_ValidTrustedPlatformAssembly on Browser --- .../System.Runtime.Loader/tests/AssemblyLoadContextTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs b/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs index 3979d76aeadb74..a5186e1d22b92c 100644 --- a/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs @@ -105,6 +105,7 @@ public static void LoadFromAssemblyName_AssemblyNotFound() } [Fact] + [PlatformSpecific(~TestPlatforms.Browser)] public static void LoadFromAssemblyName_ValidTrustedPlatformAssembly() { var asmName = typeof(System.Linq.Enumerable).Assembly.GetName(); From 29fcbe1a97d0f9fc13733631eea64508245aab80 Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Fri, 18 Sep 2020 13:51:12 -0400 Subject: [PATCH 3/3] Fix mono netcore bundle loading algorithm --- src/mono/mono/metadata/assembly-internals.h | 3 +- src/mono/mono/metadata/assembly.c | 62 +++++++++++++++------ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/mono/mono/metadata/assembly-internals.h b/src/mono/mono/metadata/assembly-internals.h index 29a3334c3315ce..486cfa3ed681ce 100644 --- a/src/mono/mono/metadata/assembly-internals.h +++ b/src/mono/mono/metadata/assembly-internals.h @@ -16,7 +16,8 @@ #else #define MONO_ASSEMBLY_CORLIB_NAME "System.Private.CoreLib" #endif -#define MONO_ASSEMBLY_CORLIB_RESOURCE_NAME (MONO_ASSEMBLY_CORLIB_NAME ".resources") +#define MONO_ASSEMBLY_RESOURCE_SUFFIX ".resources" +#define MONO_ASSEMBLY_CORLIB_RESOURCE_NAME (MONO_ASSEMBLY_CORLIB_NAME MONO_ASSEMBLY_RESOURCE_SUFFIX) /* Flag bits for mono_assembly_names_equal_flags (). */ typedef enum { diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index 1cf6d950ce3f25..f7569ffc51ad09 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -1684,23 +1684,27 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M * Try these until one of them succeeds (by returning a non-NULL reference): * 1. Check if it's already loaded by the ALC. * - * 2. If we have a bundle registered, search the images for a matching name. + * 2. If it's a non-default ALC, call the Load() method. * - * 3. If it's a non-default ALC, call the Load() method. - * - * 4. If the ALC is not the default and this is not a satellite request, + * 3. If the ALC is not the default and this is not a satellite request, * check if it's already loaded by the default ALC. * - * 5. If the ALC is the default or this is not a satellite request, + * 4. If we have a bundle registered and this is not a satellite request, search the images for a matching name + * and load into the default ALC. + * + * 5. If we have a bundle registered and this is a satellite request, search the images for a matching name + * and load into the parent assembly's ALC. + * + * 6. If the ALC is the default or this is not a satellite request, * check the TPA list, APP_PATHS, and ApplicationBase. * - * 6. If this is a satellite request, call the ALC ResolveSatelliteAssembly method. + * 7. If this is a satellite request, call the ALC ResolveSatelliteAssembly method. * - * 7. Call the ALC Resolving event. + * 8. Call the ALC Resolving event. * - * 8. Call the ALC AssemblyResolve event (except for corlib satellite assemblies). + * 9. Call the ALC AssemblyResolve event (except for corlib satellite assemblies). * - * 9. Return NULL. + * 10. Return NULL. */ reference = mono_assembly_loaded_internal (alc, aname, FALSE); @@ -1709,14 +1713,6 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M goto leave; } - if (bundles != NULL) { - reference = search_bundle_for_assembly (alc, aname); - if (reference) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the bundle: '%s'.", aname->name); - goto leave; - } - } - if (!is_default) { reference = mono_alc_invoke_resolve_using_load_nofail (alc, aname); if (reference) { @@ -1733,6 +1729,38 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M } } + if (bundles != NULL && !is_satellite) { + reference = search_bundle_for_assembly (mono_domain_default_alc (mono_alc_domain (alc)), aname); + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the bundle: '%s'.", aname->name); + goto leave; + } + } + + if (bundles != NULL && is_satellite) { + // Satellite assembly byname requests should be loaded in the same ALC as their parent assembly + size_t name_len = strlen (aname->name); + char *parent_name = NULL; + MonoAssemblyLoadContext *parent_alc = NULL; + if (g_str_has_suffix (aname->name, MONO_ASSEMBLY_RESOURCE_SUFFIX)) + parent_name = g_strdup_printf ("%s.dll", g_strndup (aname->name, name_len - strlen (MONO_ASSEMBLY_RESOURCE_SUFFIX))); + + if (parent_name) { + MonoAssemblyOpenRequest req; + mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, alc); + MonoAssembly *parent_assembly = mono_assembly_request_open (parent_name, &req, NULL); + parent_alc = mono_assembly_get_alc (parent_assembly); + } + + if (parent_alc) + reference = search_bundle_for_assembly (parent_alc, aname); + + if (reference) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Satellite assembly found in the bundle: '%s'.", aname->name); + goto leave; + } + } + if (is_default || !is_satellite) { reference = invoke_assembly_preload_hook (mono_domain_default_alc (mono_alc_domain (alc)), aname, assemblies_path); if (reference) {