Skip to content

Commit 2a19c9d

Browse files
authored
Fix getting resource when ResourceResolve returns assembly with resource that is an assembly ref (#112810)
When getting a resource where `ResourceResolve` handler returns an assembly with a manifest resource that is an assembly ref, we incorrectly resolved the reference on the original assembly instead of the assembly returned by the handler and then also looked for the resource on the original assembly again instead of using the referenced assembly. This change includes a test for this case using IL. The manifest resource file (as opposed to assembly ref) case is already covered in libraries tests.
1 parent bbc02a5 commit 2a19c9d

File tree

6 files changed

+102
-10
lines changed

6 files changed

+102
-10
lines changed

src/coreclr/vm/peassembly.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,6 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource,
508508
}
509509
CONTRACTL_END;
510510

511-
512511
mdToken mdLinkRef;
513512
DWORD dwResourceFlags;
514513
DWORD dwOffset;
@@ -557,14 +556,15 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource,
557556
}
558557

559558

560-
switch(TypeFromToken(mdLinkRef)) {
559+
switch(TypeFromToken(mdLinkRef))
560+
{
561561
case mdtAssemblyRef:
562562
{
563563
if (pAssembly == NULL)
564564
return FALSE;
565565

566566
AssemblySpec spec;
567-
spec.InitializeSpec(mdLinkRef, GetMDImport(), pAssembly);
567+
spec.InitializeSpec(mdLinkRef, pAssembly->GetMDImport(), pAssembly);
568568
Assembly* pLoadedAssembly = spec.LoadAssembly(FILE_LOADED);
569569

570570
if (dwLocation) {
@@ -574,13 +574,13 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource,
574574
*dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
575575
}
576576

577-
return GetResource(szName,
578-
cbResource,
579-
pbInMemoryResource,
580-
pAssemblyRef,
581-
szFileName,
582-
dwLocation,
583-
pLoadedAssembly);
577+
return pLoadedAssembly->GetResource(
578+
szName,
579+
cbResource,
580+
pbInMemoryResource,
581+
pAssemblyRef,
582+
szFileName,
583+
dwLocation);
584584
}
585585

586586
case mdtFile:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
.assembly extern System.Runtime
5+
{
6+
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
7+
}
8+
9+
.assembly extern ResourceAssembly
10+
{
11+
.publickeytoken = (00 00 00 00 00 00 00 00)
12+
}
13+
14+
.assembly ManifestResourceAssemblyRef { }
15+
16+
.mresource public 'MyResource'
17+
{
18+
.assembly extern 'ResourceAssembly'
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk.IL">
2+
<PropertyGroup>
3+
<OutputType>library</OutputType>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="ManifestResourceAssemblyRef.il" />
7+
</ItemGroup>
8+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Library</OutputType>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<EmbeddedResource LogicalName="MyResource" Include="$(MSBuildProjectFile)" />
7+
</ItemGroup>
8+
</Project>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.IO;
6+
using System.Reflection;
7+
using Xunit;
8+
9+
[ConditionalClass(typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNotNativeAot))]
10+
public unsafe class ResourceResolve
11+
{
12+
[Fact]
13+
[SkipOnMono("AssemblyRef manifest resource is not supported")]
14+
public static void AssemblyRef()
15+
{
16+
string resourceName = "MyResource";
17+
Assembly assembly = typeof(ResourceResolve).Assembly;
18+
19+
// Manifest resource is not in the current assembly
20+
Stream stream = assembly.GetManifestResourceStream(resourceName);
21+
Assert.Null(stream);
22+
23+
// Handler returns assembly with a manifest resource assembly ref that
24+
// points to another assembly with the resource
25+
ResolveEventHandler handler = (sender, args) =>
26+
{
27+
if (args.Name == resourceName && args.RequestingAssembly == assembly)
28+
return Assembly.Load("ManifestResourceAssemblyRef");
29+
30+
return null;
31+
};
32+
AppDomain.CurrentDomain.ResourceResolve += handler;
33+
stream = assembly.GetManifestResourceStream(resourceName);
34+
AppDomain.CurrentDomain.ResourceResolve -= handler;
35+
Assert.NotNull(stream);
36+
37+
// Verify that the stream matches the expected one in the resource assembly
38+
Assembly resourceAssembly = Assembly.Load("ResourceAssembly");
39+
Stream expected = resourceAssembly.GetManifestResourceStream(resourceName);
40+
Assert.Equal(expected.Length, stream.Length);
41+
Span<byte> expectedBytes = new byte[expected.Length];
42+
expected.Read(expectedBytes);
43+
Span<byte> streamBytes = new byte[stream.Length];
44+
stream.Read(streamBytes);
45+
Assert.Equal(expectedBytes, streamBytes);
46+
}
47+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<ItemGroup>
3+
<Compile Include="ResourceResolve.cs" />
4+
</ItemGroup>
5+
<ItemGroup>
6+
<ProjectReference Include="$(TestLibraryProjectPath)" />
7+
<ProjectReference Include="ManifestResourceAssemblyRef.ilproj" />
8+
<ProjectReference Include="ResourceAssembly.csproj" />
9+
</ItemGroup>
10+
</Project>

0 commit comments

Comments
 (0)