mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Locate references to bad compiler generated methods in sandbox
Should help pinpoint issues from params arrays and similar.
This commit is contained in:
@@ -39,7 +39,7 @@ END TEMPLATE-->
|
||||
|
||||
### New features
|
||||
|
||||
*None yet*
|
||||
* If a sandbox error is caused by a compiler-generated method, the engine will now attempt to point out which using code is responsible.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
||||
@@ -14,12 +14,9 @@ namespace Robust.Shared.ContentPack;
|
||||
internal sealed partial class AssemblyTypeChecker
|
||||
{
|
||||
// This part of the code tries to find the originator of bad sandbox references.
|
||||
|
||||
private void ReportBadReferences(PEReader peReader, MetadataReader reader, IEnumerable<EntityHandle> reference)
|
||||
private IEnumerable<(EntityHandle Referenced, MethodDefinitionHandle SourceMethod, int InstructionOffset)> FindReference(PEReader peReader, MetadataReader reader, params IEnumerable<EntityHandle> handles)
|
||||
{
|
||||
_sawmill.Info("Started search for originator of bad references...");
|
||||
|
||||
var refs = reference.ToHashSet();
|
||||
var refs = handles.ToHashSet();
|
||||
ExpandReferences(reader, refs);
|
||||
|
||||
foreach (var methodDefHandle in reader.MethodDefinitions)
|
||||
@@ -28,8 +25,6 @@ internal sealed partial class AssemblyTypeChecker
|
||||
if (methodDef.RelativeVirtualAddress == 0)
|
||||
continue;
|
||||
|
||||
var methodName = reader.GetString(methodDef.Name);
|
||||
|
||||
var body = peReader.GetMethodBody(methodDef.RelativeVirtualAddress);
|
||||
var bytes = body.GetILBytes()!;
|
||||
|
||||
@@ -41,9 +36,7 @@ internal sealed partial class AssemblyTypeChecker
|
||||
{
|
||||
if (refs.Overlaps(ExpandHandle(reader, handle)))
|
||||
{
|
||||
var type = GetTypeFromDefinition(reader, methodDef.GetDeclaringType());
|
||||
_sawmill.Error(
|
||||
$"Found reference to {DisplayHandle(reader, handle)} in method {type}.{methodName} at IL 0x{prefPosition:X4}");
|
||||
yield return (handle, methodDefHandle, prefPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +45,19 @@ internal sealed partial class AssemblyTypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
private void ReportBadReferences(PEReader peReader, MetadataReader reader, IEnumerable<EntityHandle> reference)
|
||||
{
|
||||
foreach (var (referenced, method, ilOffset) in FindReference(peReader, reader, reference))
|
||||
{
|
||||
var methodDef = reader.GetMethodDefinition(method);
|
||||
var methodName = reader.GetString(methodDef.Name);
|
||||
|
||||
var type = GetTypeFromDefinition(reader, methodDef.GetDeclaringType());
|
||||
_sawmill.Error(
|
||||
$"Found reference to {DisplayHandle(reader, referenced)} in method {type}.{methodName} at IL 0x{ilOffset:X4}");
|
||||
}
|
||||
}
|
||||
|
||||
private static string DisplayHandle(MetadataReader reader, EntityHandle handle)
|
||||
{
|
||||
switch (handle.Kind)
|
||||
|
||||
@@ -227,6 +227,8 @@ namespace Robust.Shared.ContentPack
|
||||
#if TOOLS
|
||||
if (!badRefs.IsEmpty)
|
||||
{
|
||||
_sawmill.Info("Started search for originator of bad references...");
|
||||
|
||||
ReportBadReferences(peReader, reader, badRefs);
|
||||
}
|
||||
#endif
|
||||
@@ -298,6 +300,9 @@ namespace Robust.Shared.ContentPack
|
||||
|
||||
verifyErrors = true;
|
||||
_sawmill.Error(msg);
|
||||
|
||||
if (!res.Method.IsNil)
|
||||
PrintCompilerGeneratedMethodUsage(peReader, reader, res.Method);
|
||||
}
|
||||
|
||||
_sawmill.Debug($"{name}: Verified IL in {sw.Elapsed.TotalMilliseconds}ms");
|
||||
@@ -310,6 +315,22 @@ namespace Robust.Shared.ContentPack
|
||||
return true;
|
||||
}
|
||||
|
||||
private void PrintCompilerGeneratedMethodUsage(
|
||||
PEReader peReader,
|
||||
MetadataReader reader,
|
||||
MethodDefinitionHandle method)
|
||||
{
|
||||
var methodDef = reader.GetMethodDefinition(method);
|
||||
var type = GetTypeFromDefinition(reader, methodDef.GetDeclaringType());
|
||||
|
||||
if (!type.Name.Contains('<'))
|
||||
return;
|
||||
|
||||
_sawmill.Error("Hint: method is compiler-generated. Check for params collections and/or collection expressions:");
|
||||
|
||||
ReportBadReferences(peReader, reader, [method]);
|
||||
}
|
||||
|
||||
private static string FormatMethodName(MetadataReader reader, MethodDefinition method)
|
||||
{
|
||||
var methodSig = method.DecodeSignature(new TypeProvider(), 0);
|
||||
|
||||
Reference in New Issue
Block a user