No running AssemblyTypeChecker unless necessary, use less dumb byte copies.

This commit is contained in:
Pieter-Jan Briers
2020-01-25 16:27:30 +01:00
parent 4eb29a9e80
commit 3d11cf2f87
4 changed files with 59 additions and 38 deletions

View File

@@ -196,45 +196,63 @@ namespace Robust.Shared.ContentPack
/// </summary>
/// <param name="assembly">Assembly to load.</param>
/// <returns></returns>
public static bool CheckAssembly(byte[] assembly)
public static bool CheckAssembly(Stream assembly)
{
using (var asmDefStream = new MemoryStream(assembly))
if (WouldNoOp)
{
var asmDef = AssemblyDefinition.ReadAssembly(asmDefStream);
// This method is a no-op in this case so don't bother
return true;
}
if (DumpTypes)
AnalyzeTypes(asmDef.MainModule.GetTypeReferences());
var asmDef = AssemblyDefinition.ReadAssembly(assembly);
if (DisableTypeCheck)
return true;
if (DumpTypes)
AnalyzeTypes(asmDef.MainModule.GetTypeReferences());
foreach (var typeRef in asmDef.MainModule.GetTypeReferences())
if (DisableTypeCheck)
return true;
foreach (var typeRef in asmDef.MainModule.GetTypeReferences())
{
// Assemblies are guilty until proven innocent in a court of law.
var safe = false;
foreach (var typeName in _typeWhiteList)
{
// Assemblies are guilty until proven innocent in a court of law.
var safe = false;
foreach (var typeName in _typeWhiteList)
{
if (typeRef.FullName.StartsWith(typeName))
safe = true;
}
foreach (var typeName in _typeBlackList)
{
if (typeRef.FullName.StartsWith(typeName))
safe = false;
}
if (safe)
continue;
Logger.ErrorS("res.typecheck", $"Cannot load {asmDef.MainModule.Name}, {typeRef.FullName} is not whitelisted.");
return false;
if (typeRef.FullName.StartsWith(typeName))
safe = true;
}
foreach (var typeName in _typeBlackList)
{
if (typeRef.FullName.StartsWith(typeName))
safe = false;
}
if (safe)
continue;
Logger.ErrorS("res.typecheck", $"Cannot load {asmDef.MainModule.Name}, {typeRef.FullName} is not whitelisted.");
return false;
}
return true;
}
private static bool WouldNoOp => !DumpTypes && DisableTypeCheck;
public static bool CheckAssembly(string diskPath)
{
if (WouldNoOp)
{
// This method is a no-op in this case so don't bother
return true;
}
using var file = File.OpenRead(diskPath);
return CheckAssembly(file);
}
/// <summary>
/// Runs an enumeration of types through the white/black lists and prints results to log.
/// </summary>

View File

@@ -1,3 +1,4 @@
using System.IO;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.Timing;
@@ -11,7 +12,7 @@ namespace Robust.Shared.ContentPack
/// <typeparam name="T">The type of the entry point to search for.</typeparam>
/// <param name="assembly">Byte array of the assembly.</param>
/// <param name="symbols">Optional byte array of the debug symbols.</param>
void LoadGameAssembly<T>(byte[] assembly, byte[] symbols = null)
void LoadGameAssembly<T>(Stream assembly, Stream symbols = null)
where T : GameShared;
/// <summary>

View File

@@ -73,20 +73,20 @@ namespace Robust.Shared.ContentPack
private readonly List<Assembly> _sideModules = new List<Assembly>();
public virtual void LoadGameAssembly<T>(byte[] assembly, byte[] symbols = null)
public virtual void LoadGameAssembly<T>(Stream assembly, Stream symbols = null)
where T : GameShared
{
// TODO: Re-enable type check when it's not just a giant pain in the butt.
// It slows down development too much and we need other things like System.Type fixed
// before it can reasonably be re-enabled.
AssemblyTypeChecker.DisableTypeCheck = true;
AssemblyTypeChecker.DumpTypes = true;
AssemblyTypeChecker.DumpTypes = false;
if (!AssemblyTypeChecker.CheckAssembly(assembly))
return;
var gameAssembly = symbols != null
? AppDomain.CurrentDomain.Load(assembly, symbols)
: AppDomain.CurrentDomain.Load(assembly);
assembly.Position = 0;
var gameAssembly = AssemblyLoadContext.Default.LoadFromStream(assembly, symbols);
InitMod<T>(gameAssembly);
}
@@ -98,8 +98,9 @@ namespace Robust.Shared.ContentPack
// It slows down development too much and we need other things like System.Type fixed
// before it can reasonably be re-enabled.
AssemblyTypeChecker.DisableTypeCheck = true;
AssemblyTypeChecker.DumpTypes = true;
if (!AssemblyTypeChecker.CheckAssembly(File.ReadAllBytes(diskPath)))
AssemblyTypeChecker.DumpTypes = false;
if (!AssemblyTypeChecker.CheckAssembly(diskPath))
return;
InitMod<T>(Assembly.LoadFrom(diskPath));
@@ -202,7 +203,7 @@ namespace Robust.Shared.ContentPack
try
{
// load the assembly into the process, and bootstrap the GameServer entry point.
LoadGameAssembly<T>(gameDll.CopyToArray(), gamePdb.CopyToArray());
LoadGameAssembly<T>(gameDll, gamePdb);
return true;
}
catch (Exception e)
@@ -216,7 +217,7 @@ namespace Robust.Shared.ContentPack
try
{
// load the assembly into the process, and bootstrap the GameServer entry point.
LoadGameAssembly<T>(gameDll.CopyToArray());
LoadGameAssembly<T>(gameDll);
return true;
}
catch (Exception e)

View File

@@ -1,3 +1,4 @@
using System.IO;
using System.Reflection;
using Robust.Shared.ContentPack;
using Robust.Shared.Interfaces.Resources;
@@ -12,7 +13,7 @@ namespace Robust.UnitTesting
public Assembly ServerContentAssembly { get; set; }
public Assembly SharedContentAssembly { get; set; }
public override void LoadGameAssembly<T>(byte[] assembly, byte[] symbols = null)
public override void LoadGameAssembly<T>(Stream assembly, Stream symbols = null)
{
if (TryLoadPreset<T>())
{