Skip to content

Commit 9153795

Browse files
Update patcher to use concrete type instead of an interface for collections, disposal of any assembly reading
1 parent 7a6b98b commit 9153795

9 files changed

Lines changed: 164 additions & 160 deletions

File tree

src/AssemblyResolver.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extern alias References;
2-
using System.IO;
32
using Oxide.Core;
3+
using Oxide.CSharp.Common;
44
using References::Mono.Cecil;
55

66
namespace Oxide.CSharp;
@@ -14,35 +14,35 @@ public AssemblyResolver()
1414
{
1515
_resolver = new DefaultAssemblyResolver();
1616
_resolver.AddSearchDirectory(Interface.Oxide.ExtensionDirectory);
17-
_mscorlib = AssemblyDefinition.ReadAssembly(Path.Combine(Interface.Oxide.ExtensionDirectory, "mscorlib.dll"));
17+
_mscorlib = AssemblyDefinition.ReadAssembly(Constants.MscorlibPath);
1818
}
1919

2020
public AssemblyDefinition Resolve(AssemblyNameReference assemblyNameReference)
2121
{
22-
if (assemblyNameReference.Name == "System.Private.CoreLib")
22+
if (assemblyNameReference.Name != "System.Private.CoreLib")
2323
{
24-
Interface.Oxide.RootLogger.WriteDebug(Core.Logging.LogType.Warning,
25-
new Logging.LogEvent(50, "Resolve"), "Resolver",
26-
"Redirecting reference to System.Private.CoreLib to mscorlib");
27-
28-
return _mscorlib;
24+
return _resolver.Resolve(assemblyNameReference);
2925
}
3026

31-
return _resolver.Resolve(assemblyNameReference);
27+
Interface.Oxide.RootLogger.WriteDebug(Core.Logging.LogType.Warning,
28+
new Logging.LogEvent(50, "Resolve"), "Resolver",
29+
"Redirecting reference to System.Private.CoreLib to mscorlib");
30+
31+
return _mscorlib;
3232
}
3333

3434
public AssemblyDefinition Resolve(AssemblyNameReference assemblyNameReference, ReaderParameters readerParameters)
3535
{
36-
if (assemblyNameReference.Name == "System.Private.CoreLib")
36+
if (assemblyNameReference.Name != "System.Private.CoreLib")
3737
{
38-
Interface.Oxide.RootLogger.WriteDebug(Core.Logging.LogType.Warning,
39-
new Logging.LogEvent(50, "Resolve"), "Resolver",
40-
"Redirecting reference to System.Private.CoreLib to mscorlib");
41-
42-
return _mscorlib;
38+
return _resolver.Resolve(assemblyNameReference, readerParameters);
4339
}
4440

45-
return _resolver.Resolve(assemblyNameReference, readerParameters);
41+
Interface.Oxide.RootLogger.WriteDebug(Core.Logging.LogType.Warning,
42+
new Logging.LogEvent(50, "Resolve"), "Resolver",
43+
"Redirecting reference to System.Private.CoreLib to mscorlib");
44+
45+
return _mscorlib;
4646
}
4747

4848
public void Dispose()

src/CSharpPluginLoader.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ public class CSharpPluginLoader : PluginLoader
2626
public static CompilablePlugin GetCompilablePlugin(string directory, string name)
2727
{
2828
string className = Regex.Replace(name, "_", "");
29-
if (!plugins.TryGetValue(className, out CompilablePlugin plugin))
29+
if (!plugins.TryGetValue(className, out CompilablePlugin? plugin))
3030
{
3131
plugin = new CompilablePlugin(extension, Instance, directory, name);
3232
plugins[className] = plugin;
3333
}
34+
3435
return plugin;
3536
}
3637

@@ -285,10 +286,12 @@ private void PluginLoadingCompleted(CompilablePlugin plugin)
285286
foreach (string loadingName in LoadingPlugins.ToArray())
286287
{
287288
CompilablePlugin loadingPlugin = GetCompilablePlugin(plugin.Directory, loadingName);
288-
if (loadingPlugin.IsLoading && loadingPlugin.Requires.Contains(plugin.Name))
289+
if (!loadingPlugin.IsLoading || !loadingPlugin.Requires.Contains(plugin.Name))
289290
{
290-
Load(loadingPlugin);
291+
continue;
291292
}
293+
294+
Load(loadingPlugin);
292295
}
293296
}
294297

src/Common/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,6 @@ internal static class Constants
4141

4242
internal static readonly string IncludePath = Path.Combine(Interface.Oxide.PluginDirectory, "include");
4343
internal static readonly string CSharpPath = Path.Combine(Interface.Oxide.ExtensionDirectory, "Oxide.CSharp.dll");
44+
internal static readonly string MscorlibPath = Path.Combine(Interface.Oxide.ExtensionDirectory, "mscorlib.dll");
4445
}
4546
}

src/CompiledAssembly.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ private void ValidateAssembly(Action<byte[], byte[]> callback)
111111
SymbolReaderProvider = new PortablePdbReaderProvider()
112112
};
113113

114-
AssemblyDefinition baseAssembly = AssemblyDefinition.ReadAssembly(Constants.CSharpPath,
114+
using AssemblyDefinition baseAssembly = AssemblyDefinition.ReadAssembly(Constants.CSharpPath,
115115
new ReaderParameters
116116
{
117117
AssemblyResolver = assemblyResolver,
@@ -122,7 +122,8 @@ private void ValidateAssembly(Action<byte[], byte[]> callback)
122122
using MemoryStream symbolStream = new(Symbols);
123123
readerParameters.SymbolStream = symbolStream;
124124

125-
AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyStream, readerParameters);
125+
using AssemblyDefinition assemblyDefinition =
126+
AssemblyDefinition.ReadAssembly(assemblyStream, readerParameters);
126127

127128
int foundPlugins = 0;
128129
int totalPlugins = CompilablePlugins.Count(p => p.CompilerErrors.Count == 0);

src/CompilerStream/CompilerFile.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class CompilerFile
2121
internal static readonly Dictionary<string, CompilerFile> FileCache =
2222
new Dictionary<string, CompilerFile>(StringComparer.InvariantCultureIgnoreCase);
2323

24-
public static CompilerFile CachedReadFile(string directory, string fileName, byte[] data = null)
24+
public static CompilerFile? CachedReadFile(string directory, string fileName, byte[]? data = null)
2525
{
2626
string fullPath = Path.Combine(directory, fileName);
2727

@@ -34,6 +34,7 @@ public static CompilerFile CachedReadFile(string directory, string fileName, byt
3434
{
3535
file.Data = data;
3636
}
37+
3738
file.LastRead = DateTime.Now;
3839
return file;
3940
}

src/Patching/Patcher.cs

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,21 @@ private static void GetPatches(Assembly module, ref Dictionary<Type, List<PatchV
2424
try
2525
{
2626
Type[] types = module.GetTypes();
27-
28-
for (int i = 0; i < types.Length; i++)
27+
int typeCount = types.Length;
28+
for (int i = 0; i < typeCount; i++)
2929
{
3030
Type type = types[i];
3131

32-
if (!type.IsAbstract && PatchType.IsAssignableFrom(type))
32+
if (type.IsAbstract || !PatchType.IsAssignableFrom(type))
3333
{
34-
List<PatchValidationAttribute> validators = GetValidationRules(type.GetCustomAttributes(PatchValidationType, true)
35-
.Concat(type.Assembly.GetCustomAttributes(PatchValidationType, true)).ToArray());
36-
37-
patchTypes.Add(type, validators);
38-
Interface.Oxide.RootLogger.WriteDebug(LogType.Info, Logging.LogEvent.Patch, "Patcher", $"Found {validators.Count} total validators for patch {type.Name}");
34+
continue;
3935
}
36+
37+
List<PatchValidationAttribute> validators = GetValidationRules(type.GetCustomAttributes(PatchValidationType, true)
38+
.Concat(type.Assembly.GetCustomAttributes(PatchValidationType, true)).ToArray());
39+
40+
patchTypes.Add(type, validators);
41+
Interface.Oxide.RootLogger.WriteDebug(LogType.Info, Logging.LogEvent.Patch, "Patcher", $"Found {validators.Count} total validators for patch {type.Name}");
4042
}
4143
}
4244
catch (Exception e)
@@ -47,7 +49,8 @@ private static void GetPatches(Assembly module, ref Dictionary<Type, List<PatchV
4749

4850
private static void GetPatches(Assembly[] modules, ref Dictionary<Type, List<PatchValidationAttribute>> patchTypes)
4951
{
50-
for (int i = 0; i < modules.Length; i++)
52+
int moduleCount = modules.Length;
53+
for (int i = 0; i < moduleCount; i++)
5154
{
5255
GetPatches(modules[i], ref patchTypes);
5356
}
@@ -63,23 +66,27 @@ public static bool Run(AssemblyDefinition module)
6366
}
6467

6568
PatchContext context = new PatchContext(module);
66-
foreach (var kv in Patches)
69+
foreach (KeyValuePair<Type, List<PatchValidationAttribute>> kv in Patches)
6770
{
6871

6972
Type patchType = kv.Key;
7073
List<PatchValidationAttribute> validators = kv.Value;
7174
context.PatchValidators = validators;
7275
bool failed = false;
73-
for (int n = 0; n < validators.Count; n++)
76+
77+
int validatorCount = validators.Count;
78+
for (int i = 0; i < validatorCount; i++)
7479
{
75-
PatchValidationAttribute valid = validators[n];
76-
bool pass = valid.Validate(module);
80+
PatchValidationAttribute patchValidationAttribute = validators[i];
81+
bool pass = patchValidationAttribute.Validate(module);
7782
// Interface.Oxide.RootLogger.WriteDebug(LogType.Info, Logging.LogEvent.Patch, "Patcher", $"Validation {valid.GetType().Name}: {(pass ? "passed" : "failed")}");
78-
if (!pass)
83+
if (pass)
7984
{
80-
failed = true;
81-
break;
85+
continue;
8286
}
87+
88+
failed = true;
89+
break;
8390
}
8491

8592
if (failed)
@@ -96,10 +103,10 @@ public static bool Run(AssemblyDefinition module)
96103
Interface.Oxide.RootLogger.WriteDebug(LogType.Info, Logging.LogEvent.Patch, "Patcher",
97104
$"{patchType.Name} has applied {context.ContextPatches} patches to {module.Name?.Name ?? module.FullName}");
98105
}
99-
catch (Exception e)
106+
catch (Exception exception)
100107
{
101108
Interface.Oxide.RootLogger.WriteDebug(LogType.Error, Logging.LogEvent.Patch, "Patcher",
102-
$"{patchType.Name} has applied {context.ContextPatches} patches to {module.Name?.Name ?? module.FullName} but threw a error", e);
109+
$"{patchType.Name} has applied {context.ContextPatches} patches to {module.Name?.Name ?? module.FullName} but threw a error", exception);
103110
}
104111
}
105112

@@ -110,25 +117,20 @@ public static byte[] Run(byte[] data, out bool patched)
110117
{
111118
try
112119
{
113-
using (MemoryStream inStream = new MemoryStream(data))
114-
{
115-
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(inStream);
120+
using MemoryStream inStream = new(data);
121+
using AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(inStream);
116122

117-
if (Run(assembly))
118-
{
119-
using (MemoryStream outStream = new MemoryStream())
120-
{
121-
assembly.Write(outStream);
122-
patched = true;
123-
return outStream.ToArray();
124-
}
125-
}
123+
if (Run(assembly))
124+
{
125+
using MemoryStream outStream = new();
126+
assembly.Write(outStream);
127+
patched = true;
128+
return outStream.ToArray();
126129
}
127-
128130
}
129-
catch (Exception e)
131+
catch (Exception exception)
130132
{
131-
Interface.Oxide.RootLogger.WriteDebug(LogType.Error, Logging.LogEvent.Patch, "Patcher", $"Failed to patch", e);
133+
Interface.Oxide.RootLogger.WriteDebug(LogType.Error, Logging.LogEvent.Patch, "Patcher", $"Failed to patch", exception);
132134
}
133135

134136
patched = false;
@@ -137,15 +139,17 @@ public static byte[] Run(byte[] data, out bool patched)
137139

138140
public static List<PatchValidationAttribute> GetValidationRules(object[] attributes)
139141
{
140-
List<PatchValidationAttribute> validators = new List<PatchValidationAttribute>();
142+
List<PatchValidationAttribute> validators = new();
141143

142-
for (int i = 0; i < attributes.Length; i++)
144+
int attributeCount = attributes.Length;
145+
for (int i = 0; i < attributeCount; i++)
143146
{
144-
Attribute a = attributes[i] as Attribute;
145-
if (a is PatchValidationAttribute valid)
147+
if (attributes[i] is not PatchValidationAttribute patchValidationAttribute)
146148
{
147-
validators.Add(valid);
149+
continue;
148150
}
151+
152+
validators.Add(patchValidationAttribute);
149153
}
150154

151155
return validators;

src/Patching/Publicizer.cs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ protected override bool OnMemberDefinition(IMemberDefinition member)
3030

3131
protected override bool OnTypeDefinition(TypeDefinition type)
3232
{
33-
if (type.IsNested && !type.IsNestedPublic)
33+
if (type is { IsNested: true, IsNestedPublic: false })
3434
{
3535
type.IsNestedPublic = true;
3636
return true;
3737
}
3838

39-
if (!type.IsPublic)
39+
if (type.IsPublic)
4040
{
41-
type.IsPublic = true;
42-
return true;
41+
return false;
4342
}
4443

45-
return false;
44+
type.IsPublic = true;
45+
return true;
4646
}
4747

4848
protected override bool OnFieldDefinition(FieldDefinition field)
@@ -58,9 +58,8 @@ protected override bool OnFieldDefinition(FieldDefinition field)
5858

5959
protected override bool OnPropertyDefinition(PropertyDefinition property)
6060
{
61-
bool get = property.GetMethod != null ? OnMethodDefinition(property.GetMethod) : false;
62-
bool set = property.SetMethod != null ? OnMethodDefinition(property.SetMethod) : false;
63-
61+
bool get = property.GetMethod != null && OnMethodDefinition(property.GetMethod);
62+
bool set = property.SetMethod != null && OnMethodDefinition(property.SetMethod);
6463
return get || set;
6564
}
6665

@@ -78,26 +77,27 @@ protected override bool OnMethodDefinition(MethodDefinition method)
7877
protected override void OnPatchFinished(PatchContext context)
7978
{
8079
string writePath = EnvironmentHelper.GetVariable("PublicizerOutput");
80+
if (string.IsNullOrEmpty(writePath))
81+
{
82+
return;
83+
}
8184

82-
if (!string.IsNullOrEmpty(writePath))
85+
string name = context.Assembly.Name.Name;
86+
if (!Directory.Exists(writePath))
8387
{
84-
string name = context.Assembly.Name.Name;
85-
if (!Directory.Exists(writePath))
86-
{
87-
Log($"Failed to write {name} because PublicizeOutput {writePath} doesn't exist", Core.Logging.LogType.Error);
88-
return;
89-
}
88+
Log($"Failed to write {name} because PublicizeOutput {writePath} doesn't exist", Core.Logging.LogType.Error);
89+
return;
90+
}
9091

91-
try
92-
{
93-
name = Path.Combine(writePath, name + ".dll");
94-
context.Assembly.Write(name);
95-
Log($"Wrote publicized assembly to {writePath}");
96-
}
97-
catch (Exception e)
98-
{
99-
Log($"Failed to write publicized assembly to {writePath}", Core.Logging.LogType.Error, e);
100-
}
92+
try
93+
{
94+
name = Path.Combine(writePath, $"{name}.dll");
95+
context.Assembly.Write(name);
96+
Log($"Wrote publicized assembly to {writePath}");
97+
}
98+
catch (Exception exception)
99+
{
100+
Log($"Failed to write publicized assembly to {writePath}", Core.Logging.LogType.Error, exception);
101101
}
102102
}
103103
}

0 commit comments

Comments
 (0)