Files
RobustToolbox/Robust.Shared/ContentPack/AssemblyTypeChecker.Config.cs
PJB3005 8cda9b86e3 Validate that content assemblies have a limited list of names.
Also, only read assemblies once from disk

(cherry picked from commit 443a8dfca65be7d60c4bd46181b4c749b4756114)
2025-09-26 13:40:42 +02:00

123 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ILVerify;
using Pidgin;
using Robust.Shared.Log;
using Robust.Shared.Utility;
using YamlDotNet.Serialization;
namespace Robust.Shared.ContentPack
{
internal sealed partial class AssemblyTypeChecker
{
private static SandboxConfig LoadConfig(ISawmill sawmill)
{
using var stream = typeof(AssemblyTypeChecker).Assembly
.GetManifestResourceStream("Robust.Shared.ContentPack.Sandbox.yml")!;
DebugTools.AssertNotNull(stream);
var cfg = new Deserializer().Deserialize<SandboxConfig>(new StreamReader(stream, Encoding.UTF8));
foreach (var typeCfg in cfg.Types.Values.SelectMany(p => p.Values))
{
ParseTypeConfig(typeCfg, sawmill);
}
return cfg;
}
private static void ParseTypeConfig(TypeConfig cfg, ISawmill sawmill)
{
if (cfg.Methods != null)
{
var list = new List<WhitelistMethodDefine>();
foreach (var m in cfg.Methods)
{
try
{
list.Add(MethodParser.ParseOrThrow(m));
}
catch (ParseException e)
{
sawmill.Error($"Parse exception for '{m}': {e}");
}
}
cfg.MethodsParsed = list.ToArray();
}
else
{
cfg.MethodsParsed = Array.Empty<WhitelistMethodDefine>();
}
if (cfg.Fields != null)
{
var list = new List<WhitelistFieldDefine>();
foreach (var f in cfg.Fields)
{
try
{
list.Add(FieldParser.ParseOrThrow(f));
}
catch (ParseException e)
{
sawmill.Error($"Parse exception for '{f}': {e}");
}
}
cfg.FieldsParsed = list.ToArray();
}
else
{
cfg.FieldsParsed = Array.Empty<WhitelistFieldDefine>();
}
if (cfg.NestedTypes != null)
{
foreach (var nested in cfg.NestedTypes.Values)
{
ParseTypeConfig(nested, sawmill);
}
}
}
private sealed class SandboxConfig
{
public string SystemAssemblyName = default!;
public HashSet<VerifierError> AllowedVerifierErrors = default!;
public List<string> WhitelistedNamespaces = default!;
public List<string> AllowedAssemblyPrefixes = default!;
public Dictionary<string, Dictionary<string, TypeConfig>> Types = default!;
}
#pragma warning disable 649
private sealed class TypeConfig
{
// Used for type configs where the type config doesn't exist due to a bigger-scoped All whitelisting.
// e.g. nested types or namespace whitelist.
public static readonly TypeConfig DefaultAll = new TypeConfig {All = true};
public bool All;
public InheritMode Inherit = InheritMode.Default;
public string[]? Methods;
[NonSerialized] public WhitelistMethodDefine[] MethodsParsed = default!;
public string[]? Fields;
[NonSerialized] public WhitelistFieldDefine[] FieldsParsed = default!;
public Dictionary<string, TypeConfig>? NestedTypes;
}
#pragma warning restore 649
private enum InheritMode : byte
{
// Allow if All is set, block otherwise
Default,
Allow,
// Block even is All is set
Block
}
}
}