diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 3f54dbff556af2..8594e62c9a0e6b 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -518,7 +518,6 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, } CONTRACTL_END; - mdToken mdLinkRef; DWORD dwResourceFlags; DWORD dwOffset; @@ -567,30 +566,31 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, } - switch(TypeFromToken(mdLinkRef)) { + switch(TypeFromToken(mdLinkRef)) + { case mdtAssemblyRef: { if (pAssembly == NULL) return FALSE; AssemblySpec spec; - spec.InitializeSpec(mdLinkRef, GetMDImport(), pAssembly); - DomainAssembly* pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED); + spec.InitializeSpec(mdLinkRef, pAssembly->GetMDImport(), pAssembly); + Assembly* pLoadedAssembly = spec.LoadAssembly(FILE_LOADED); if (dwLocation) { if (pAssemblyRef) - *pAssemblyRef = pDomainAssembly->GetAssembly(); + *pAssemblyRef = pLoadedAssembly; *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly } - return GetResource(szName, - cbResource, - pbInMemoryResource, - pAssemblyRef, - szFileName, - dwLocation, - pDomainAssembly->GetAssembly()); + return pLoadedAssembly->GetResource( + szName, + cbResource, + pbInMemoryResource, + pAssemblyRef, + szFileName, + dwLocation); } case mdtFile: diff --git a/src/tests/Loader/ResourceResolve/ManifestResourceAssemblyRef.il b/src/tests/Loader/ResourceResolve/ManifestResourceAssemblyRef.il new file mode 100644 index 00000000000000..c4891a07551f14 --- /dev/null +++ b/src/tests/Loader/ResourceResolve/ManifestResourceAssemblyRef.il @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) +} + +.assembly extern ResourceAssembly +{ + .publickeytoken = (00 00 00 00 00 00 00 00) +} + +.assembly ManifestResourceAssemblyRef { } + +.mresource public 'MyResource' +{ + .assembly extern 'ResourceAssembly' +} diff --git a/src/tests/Loader/ResourceResolve/ManifestResourceAssemblyRef.ilproj b/src/tests/Loader/ResourceResolve/ManifestResourceAssemblyRef.ilproj new file mode 100644 index 00000000000000..bfc5d0bb00df9b --- /dev/null +++ b/src/tests/Loader/ResourceResolve/ManifestResourceAssemblyRef.ilproj @@ -0,0 +1,8 @@ + + + library + + + + + diff --git a/src/tests/Loader/ResourceResolve/ResourceAssembly.csproj b/src/tests/Loader/ResourceResolve/ResourceAssembly.csproj new file mode 100644 index 00000000000000..e014b87610bd87 --- /dev/null +++ b/src/tests/Loader/ResourceResolve/ResourceAssembly.csproj @@ -0,0 +1,8 @@ + + + Library + + + + + diff --git a/src/tests/Loader/ResourceResolve/ResourceResolve.cs b/src/tests/Loader/ResourceResolve/ResourceResolve.cs new file mode 100644 index 00000000000000..2cf30a36216ffe --- /dev/null +++ b/src/tests/Loader/ResourceResolve/ResourceResolve.cs @@ -0,0 +1,47 @@ +// 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.Reflection; +using Xunit; + +[ConditionalClass(typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNotNativeAot))] +public unsafe class ResourceResolve +{ + [Fact] + [SkipOnMono("AssemblyRef manifest resource is not supported")] + public static void AssemblyRef() + { + string resourceName = "MyResource"; + Assembly assembly = typeof(ResourceResolve).Assembly; + + // Manifest resource is not in the current assembly + Stream stream = assembly.GetManifestResourceStream(resourceName); + Assert.Null(stream); + + // Handler returns assembly with a manifest resource assembly ref that + // points to another assembly with the resource + ResolveEventHandler handler = (sender, args) => + { + if (args.Name == resourceName && args.RequestingAssembly == assembly) + return Assembly.Load("ManifestResourceAssemblyRef"); + + return null; + }; + AppDomain.CurrentDomain.ResourceResolve += handler; + stream = assembly.GetManifestResourceStream(resourceName); + AppDomain.CurrentDomain.ResourceResolve -= handler; + Assert.NotNull(stream); + + // Verify that the stream matches the expected one in the resource assembly + Assembly resourceAssembly = Assembly.Load("ResourceAssembly"); + Stream expected = resourceAssembly.GetManifestResourceStream(resourceName); + Assert.Equal(expected.Length, stream.Length); + Span expectedBytes = new byte[expected.Length]; + expected.Read(expectedBytes); + Span streamBytes = new byte[stream.Length]; + stream.Read(streamBytes); + Assert.Equal(expectedBytes, streamBytes); + } +} diff --git a/src/tests/Loader/ResourceResolve/ResourceResolve.csproj b/src/tests/Loader/ResourceResolve/ResourceResolve.csproj new file mode 100644 index 00000000000000..5fc4c77bada41d --- /dev/null +++ b/src/tests/Loader/ResourceResolve/ResourceResolve.csproj @@ -0,0 +1,10 @@ + + + + + + + + + +