From fa41a711bc0ec9ae5725f0a393e8b8c8309f7b3c Mon Sep 17 00:00:00 2001 From: Bip901 <74911767+Bip901@users.noreply.github.com> Date: Wed, 24 Sep 2025 13:59:46 +0300 Subject: [PATCH 1/2] Check the full inheritence chain rather than just the immediate parent --- .../CriticalBaseTypesCriticalAnalyzer.cs | 64 +++++++++++++++++-- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/src/BitMono.Core/Analyzing/CriticalBaseTypesCriticalAnalyzer.cs b/src/BitMono.Core/Analyzing/CriticalBaseTypesCriticalAnalyzer.cs index a0f977f7..87fa276b 100644 --- a/src/BitMono.Core/Analyzing/CriticalBaseTypesCriticalAnalyzer.cs +++ b/src/BitMono.Core/Analyzing/CriticalBaseTypesCriticalAnalyzer.cs @@ -1,6 +1,7 @@ -namespace BitMono.Core.Analyzing; +using System.Text.RegularExpressions; + +namespace BitMono.Core.Analyzing; -[SuppressMessage("ReSharper", "InvertIf")] public class CriticalBaseTypesCriticalAnalyzer : ICriticalAnalyzer { private readonly CriticalsSettings _criticalsSettings; @@ -12,19 +13,68 @@ public CriticalBaseTypesCriticalAnalyzer(IOptions criticals) public bool NotCriticalToMakeChanges(TypeDefinition type) { - if (_criticalsSettings.UseCriticalBaseTypes == false) + if (!_criticalsSettings.UseCriticalBaseTypes) { return true; } - if (type.HasBaseType()) + foreach (string ancestorFullName in YieldAncestors(type)) { - var criticalBaseTypes = _criticalsSettings.CriticalBaseTypes!; - var typeBaseTypeName = type.BaseType?.Name?.Value.Split('`')[0] ?? string.Empty; - if (criticalBaseTypes.FirstOrDefault(c => c.StartsWith(typeBaseTypeName)) != null) + if (IsCriticalBaseType(ancestorFullName)) { return false; } } return true; } + + private bool IsCriticalBaseType(string ancestorFullName) + { + ancestorFullName = StripGenerics(ancestorFullName); + foreach (string criticalBaseType in _criticalsSettings.CriticalBaseTypes) + { + bool matches; + if (criticalBaseType.Contains('*')) + { + string regex = "^" + Regex.Escape(criticalBaseType).Replace(@"\*", ".*") + "$"; + matches = Regex.IsMatch(ancestorFullName, regex); + } + else + { + matches = criticalBaseType == ancestorFullName; + } + if (matches) + { + return true; + } + } + return false; + } + + private static string StripGenerics(string fullName) + { + int genericDelimeterIndex = fullName.IndexOf('`'); + if (genericDelimeterIndex == -1) + { + return fullName; + } + return fullName[..genericDelimeterIndex]; + } + + /// + /// Yields the full class names of all ancestors across the inheritence chain of , including itself. + /// + private static IEnumerable YieldAncestors(TypeDefinition? current) + { + while (current != null) + { + yield return current.FullName; + ITypeDefOrRef? baseType = current.BaseType; + current = baseType?.Resolve(); + if (current == null && baseType != null) + { + //Type is in an unresolved dependency assembly, stop the search but yield the type name + yield return baseType.FullName; + } + } + } } \ No newline at end of file From 6675fae768eb7c6a0e0349aa07567b3cf476cf8b Mon Sep 17 00:00:00 2001 From: Bip901 <74911767+Bip901@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:47:33 +0300 Subject: [PATCH 2/2] Update default CriticalBaseTypes to use globs --- src/BitMono.Host/criticals.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/BitMono.Host/criticals.json b/src/BitMono.Host/criticals.json index a079a76c..f76e8494 100644 --- a/src/BitMono.Host/criticals.json +++ b/src/BitMono.Host/criticals.json @@ -70,16 +70,15 @@ "UseCriticalBaseTypes": true, "CriticalBaseTypes": [ // RocketMod - "RocketPlugin", + "RocketPlugin*", // OpenMod - "OpenModUnturnedPlugin", - "OpenModUniversalPlugin", - "Command", + "OpenModUnturnedPlugin*", + "OpenModUniversalPlugin*", + "Command*", // rust-oxide-umod - "RustPlugin" - + "RustPlugin*" ], // Exclude from obfuscation if the member starts with string