Skip to content

Commit 5aa9856

Browse files
authored
Merge pull request #228 from Pryaxis/improvearchchecks
Test failed plugins for incompatible architectures
2 parents 27cd3e3 + 6bed191 commit 5aa9856

1 file changed

Lines changed: 37 additions & 1 deletion

File tree

TerrariaServerAPI/TerrariaApi.Server/ServerApi.cs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using System.Linq;
99
using Terraria;
1010
using TerrariaApi.Reporting;
11+
using System.Reflection.PortableExecutable;
12+
using System.Runtime.InteropServices;
1113

1214
namespace TerrariaApi.Server
1315
{
@@ -265,6 +267,33 @@ internal static void HandleCommandLine(string[] parms)
265267
}
266268
}
267269

270+
/// <summary>
271+
/// Tests to see if a plugin is using an incompatible architecture
272+
/// </summary>
273+
/// <param name="file">File info of the plugin</param>
274+
/// <param name="data">File contents</param>
275+
static void TryCheckArchitecture(FileInfo file, byte[] data)
276+
{
277+
using var ms = new MemoryStream(data);
278+
using var pe = new PEReader(ms);
279+
if (pe.HasMetadata)
280+
{
281+
var currentArch = RuntimeInformation.ProcessArchitecture;
282+
var laa = (pe.PEHeaders.CoffHeader.Characteristics & Characteristics.LargeAddressAware) != 0;
283+
Architecture? asmArch = pe.PEHeaders.CoffHeader.Machine switch
284+
{
285+
Machine.IA64 => Architecture.X64,
286+
Machine.Arm64 => Architecture.Arm64,
287+
Machine.Amd64 => Architecture.X64,
288+
Machine.I386 => laa ? Architecture.X64 : Architecture.X86,
289+
Machine.Arm => Architecture.Arm,
290+
_ => null,
291+
};
292+
if (asmArch is not null && currentArch != asmArch)
293+
LogWriter.ServerWriteLine($"{file.Name} was built for {asmArch} but expected it to be compatible with {currentArch}.", TraceLevel.Error);
294+
}
295+
}
296+
268297
internal static void LoadPlugins()
269298
{
270299
string ignoredPluginsFilePath = Path.Combine(ServerPluginsDirectoryPath, "ignoredplugins.txt");
@@ -297,16 +326,23 @@ internal static void LoadPlugins()
297326
// load it again, but we do still have to verify it and create plugin instances.
298327
if (!loadedAssemblies.TryGetValue(fileNameWithoutExtension, out assembly))
299328
{
329+
byte[] pe = null;
300330
try
301331
{
302332
var pdb = Path.ChangeExtension(fileInfo.FullName, ".pdb");
303333
var symbols = File.Exists(pdb) ? File.ReadAllBytes(pdb) : null;
304-
assembly = Assembly.Load(File.ReadAllBytes(fileInfo.FullName), symbols);
334+
assembly = Assembly.Load(pe = File.ReadAllBytes(fileInfo.FullName), symbols);
305335
}
306336
catch (BadImageFormatException)
307337
{
308338
continue;
309339
}
340+
catch(FileLoadException)
341+
{
342+
if (pe is not null)
343+
TryCheckArchitecture(fileInfo, pe);
344+
throw; // don't consume the exception, only care about testing arch here
345+
}
310346
loadedAssemblies.Add(fileNameWithoutExtension, assembly);
311347
}
312348

0 commit comments

Comments
 (0)