Skip to content

Commit 6a30014

Browse files
authored
Fix getting resource when ResourceResolve returns assembly with resource that is an assembly ref (#112893)
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 a327ddd commit 6a30014

File tree

6 files changed

+104
-12
lines changed

6 files changed

+104
-12
lines changed

src/coreclr/vm/peassembly.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,6 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource,
518518
}
519519
CONTRACTL_END;
520520

521-
522521
mdToken mdLinkRef;
523522
DWORD dwResourceFlags;
524523
DWORD dwOffset;
@@ -567,30 +566,31 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource,
567566
}
568567

569568

570-
switch(TypeFromToken(mdLinkRef)) {
569+
switch(TypeFromToken(mdLinkRef))
570+
{
571571
case mdtAssemblyRef:
572572
{
573573
if (pAssembly == NULL)
574574
return FALSE;
575575

576576
AssemblySpec spec;
577-
spec.InitializeSpec(mdLinkRef, GetMDImport(), pAssembly);
578-
DomainAssembly* pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED);
577+
spec.InitializeSpec(mdLinkRef, pAssembly->GetMDImport(), pAssembly);
578+
Assembly* pLoadedAssembly = spec.LoadAssembly(FILE_LOADED);
579579

580580
if (dwLocation) {
581581
if (pAssemblyRef)
582-
*pAssemblyRef = pDomainAssembly->GetAssembly();
582+
*pAssemblyRef = pLoadedAssembly;
583583

584584
*dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
585585
}
586586

587-
return GetResource(szName,
588-
cbResource,
589-
pbInMemoryResource,
590-
pAssemblyRef,
591-
szFileName,
592-
dwLocation,
593-
pDomainAssembly->GetAssembly());
587+
return pLoadedAssembly->GetResource(
588+
szName,
589+
cbResource,
590+
pbInMemoryResource,
591+
pAssemblyRef,
592+
szFileName,
593+
dwLocation);
594594
}
595595

596596
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)