Skip to content

Commit 78d611e

Browse files
committed
fix: improve assembly name search and comparison
1 parent 0e9de15 commit 78d611e

3 files changed

Lines changed: 88 additions & 13 deletions

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.Reflection;
2+
3+
namespace HatModLoader.Source.AssemblyResolving
4+
{
5+
internal static class AssemblyResolveCompability
6+
{
7+
public static bool MatchesRequest(this AssemblyName assemblyName, ResolveEventArgs args, bool allowRollForward)
8+
{
9+
var requestedName = new AssemblyName(args.Name);
10+
11+
return assemblyName.Name == requestedName.Name &&
12+
assemblyName.CultureName == requestedName.CultureName &&
13+
ComparePublicKeyTokens(assemblyName.GetPublicKeyToken(), requestedName.GetPublicKeyToken()) &&
14+
CompareVersions(assemblyName.Version, requestedName.Version, allowRollForward);
15+
}
16+
17+
private static bool ComparePublicKeyTokens(byte[] tokenA, byte[] tokenB)
18+
{
19+
// Avoiding usage of stuff like SequenceEqual to prevent accidental dependency request at this stage.
20+
21+
if (tokenA == null && tokenB == null)
22+
{
23+
return true;
24+
}
25+
26+
if (tokenA == null || tokenB == null || tokenA.Length != tokenB.Length)
27+
{
28+
return false;
29+
}
30+
31+
for (int i = 0; i < tokenA.Length; i++)
32+
{
33+
if (tokenA[i] != tokenB[i])
34+
{
35+
return false;
36+
}
37+
}
38+
39+
return true;
40+
}
41+
42+
private static bool CompareVersions(Version checkedVersion, Version requiredVersion, bool allowRollForward)
43+
{
44+
if (allowRollForward)
45+
{
46+
return checkedVersion >= requiredVersion;
47+
}
48+
49+
return checkedVersion.Major == requiredVersion.Major &&
50+
checkedVersion.Minor == requiredVersion.Minor &&
51+
checkedVersion.Build == requiredVersion.Build &&
52+
checkedVersion.Revision >= requiredVersion.Revision;
53+
}
54+
}
55+
}
56+

Source/AssemblyResolving/HatSubdirectoryAssemblyResolver.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
using System.Reflection;
32

43
namespace HatModLoader.Source.AssemblyResolving
@@ -19,8 +18,12 @@ public Assembly ProvideAssembly(object sender, ResolveEventArgs args)
1918
{
2019
foreach (var file in EnumerateAssemblyFilesInSubdirectory())
2120
{
22-
var assemblyName = AssemblyName.GetAssemblyName(file);
23-
if (assemblyName.FullName == args.Name)
21+
if (!TryGetAssemblyName(file, out var assemblyName))
22+
{
23+
continue;
24+
}
25+
26+
if (assemblyName.MatchesRequest(args, true))
2427
{
2528
return Assembly.LoadFrom(file);
2629
}
@@ -48,5 +51,19 @@ private IEnumerable<string> EnumerateAssemblyFilesInSubdirectory()
4851
yield return file;
4952
}
5053
}
54+
55+
private bool TryGetAssemblyName(string filePath, out AssemblyName assemblyName)
56+
{
57+
assemblyName = null;
58+
try
59+
{
60+
assemblyName = AssemblyName.GetAssemblyName(filePath);
61+
return true;
62+
}
63+
catch
64+
{
65+
return false;
66+
}
67+
}
5168
}
52-
}
69+
}

Source/AssemblyResolving/ModInternalAssemblyResolver.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal class ModInternalAssemblyResolver : IAssemblyResolver
88
{
99
private readonly Mod _mod;
1010

11-
private readonly Dictionary<string, string> _cachedAssemblyPaths = new();
11+
private readonly Dictionary<AssemblyName, string> _cachedAssemblyPaths = new();
1212

1313
public ModInternalAssemblyResolver(Mod mod)
1414
{
@@ -18,19 +18,21 @@ public ModInternalAssemblyResolver(Mod mod)
1818

1919
public Assembly ProvideAssembly(object sender, ResolveEventArgs args)
2020
{
21-
if (_mod.Assembly?.FullName == args.Name)
21+
if (_mod.Assembly != null && _mod.Assembly.GetName().MatchesRequest(args, false))
2222
{
2323
return _mod.Assembly;
2424
}
2525

26-
if (_cachedAssemblyPaths.TryGetValue(args.Name, out var assemblyPath))
26+
foreach(var assemblyName in _cachedAssemblyPaths.Keys)
2727
{
28-
using var assemblyData = _mod.FileProxy.OpenFile(assemblyPath);
29-
var assemblyBytes = new byte[assemblyData.Length];
30-
assemblyData.Read(assemblyBytes, 0, assemblyBytes.Length);
31-
return Assembly.Load(assemblyBytes);
28+
if (assemblyName.MatchesRequest(args, false))
29+
{
30+
using var assemblyData = _mod.FileProxy.OpenFile(_cachedAssemblyPaths[assemblyName]);
31+
var assemblyBytes = new byte[assemblyData.Length];
32+
assemblyData.Read(assemblyBytes, 0, assemblyBytes.Length);
33+
return Assembly.Load(assemblyBytes);
34+
}
3235
}
33-
3436
return null;
3537
}
3638

@@ -40,7 +42,7 @@ private void CacheAssemblyPaths()
4042
{
4143
using var assemblyFile = _mod.FileProxy.OpenFile(filePath);
4244
using var assemblyDef = AssemblyDefinition.ReadAssembly(assemblyFile, new ReaderParameters { ReadSymbols = false });
43-
var fullName = assemblyDef.Name.ToString();
45+
var fullName = new AssemblyName(assemblyDef.Name.ToString());
4446

4547
if (!_cachedAssemblyPaths.ContainsKey(fullName))
4648
{

0 commit comments

Comments
 (0)