Skip to content

Commit 3b1d1aa

Browse files
committed
review: harden IsInstalled() with assembly version checks
Address PR review: file-existence alone treats a stale v4 of System.Runtime.CompilerServices.Unsafe (or any other downgraded plugin) as "installed" and silently masks the bootstrap failure this PR is meant to fix. Read each on-disk DLL's manifest via AssemblyName.GetAssemblyName(...).Version and compare to the NuGet entry's declared version; if the file is older than declared or its manifest can't be read, return false so Install() rewrites it. Applied uniformly to all entries (defense-in-depth, per the optional suggestion in the review). Notes: - System.Version comparison handles "6.0.0" (Revision=-1) vs "6.0.0.0" (Revision=0) correctly: the higher-revision actual passes; a stale v4 fails. - AssemblyName.GetAssemblyName only reads the manifest, no assembly load into the AppDomain, so this is cheap and side-effect-free. - Validated locally: with the v6 DLL in Plugins/Roslyn/, IsInstalled returns true; manually swapping in a v4 placeholder causes it to return false and Install() proceeds.
1 parent f116493 commit 3b1d1aa

1 file changed

Lines changed: 23 additions & 1 deletion

File tree

MCPForUnity/Editor/Setup/RoslynInstaller.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.IO;
33
using System.IO.Compression;
4+
using System.Reflection;
45
using UnityEditor;
56
using UnityEngine;
67
using UnityEngine.Networking;
@@ -28,8 +29,29 @@ public static bool IsInstalled()
2829
string folder = Path.Combine(Application.dataPath, PluginsRelPath);
2930
foreach (var entry in NuGetEntries)
3031
{
31-
if (!File.Exists(Path.Combine(folder, entry.dllName)))
32+
string path = Path.Combine(folder, entry.dllName);
33+
if (!File.Exists(path))
3234
return false;
35+
36+
// Defense-in-depth: a stale DLL whose assembly version is older than what
37+
// Roslyn references (e.g. a v4.x System.Runtime.CompilerServices.Unsafe
38+
// shadowing the v6 we actually need) would still satisfy file-existence but
39+
// leave Roslyn unable to load. Compare the on-disk assembly version against
40+
// each entry's declared NuGet version, treating "older or unreadable" as not
41+
// installed so Install() can rewrite it.
42+
if (Version.TryParse(entry.version, out var requiredVersion))
43+
{
44+
try
45+
{
46+
var actual = AssemblyName.GetAssemblyName(path).Version;
47+
if (actual == null || actual < requiredVersion)
48+
return false;
49+
}
50+
catch
51+
{
52+
return false;
53+
}
54+
}
3355
}
3456
return true;
3557
}

0 commit comments

Comments
 (0)