Skip to content

Commit e63e183

Browse files
committed
fixes a regression with methods ending in throw + ret
1 parent 1350ab8 commit e63e183

File tree

5 files changed

+63
-8
lines changed

5 files changed

+63
-8
lines changed

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<PropertyGroup>
44
<HarmonyVersion>2.3.0.0</HarmonyVersion>
5-
<HarmonyPrerelease>-prerelease.4</HarmonyPrerelease>
6-
<MonoModCoreVersion>1.1.0-prerelease.1</MonoModCoreVersion>
5+
<HarmonyPrerelease>-prerelease.5</HarmonyPrerelease>
6+
<MonoModCoreVersion>1.1.0-prerelease.2</MonoModCoreVersion>
77
</PropertyGroup>
88

99
</Project>

Harmony/Internal/MethodCopier.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ internal void AddTranspiler(MethodInfo transpiler)
3434
transpilers.Add(transpiler);
3535
}
3636

37-
internal List<CodeInstruction> Finalize(Emitter emitter, List<Label> endLabels, out bool hasReturnCode)
37+
internal List<CodeInstruction> Finalize(Emitter emitter, List<Label> endLabels, out bool hasReturnCode, out bool endsInThrow)
3838
{
39-
return reader.FinalizeILCodes(emitter, transpilers, endLabels, out hasReturnCode);
39+
return reader.FinalizeILCodes(emitter, transpilers, endLabels, out hasReturnCode, out endsInThrow);
4040
}
4141

4242
internal static List<CodeInstruction> GetInstructions(ILGenerator generator, MethodBase method, int maxTranspilers)
@@ -57,7 +57,7 @@ internal static List<CodeInstruction> GetInstructions(ILGenerator generator, Met
5757
copier.AddTranspiler(sortedTranspilers[i]);
5858
}
5959

60-
return copier.Finalize(null, null, out var _);
60+
return copier.Finalize(null, null, out var _, out var _);
6161
}
6262
}
6363

@@ -315,9 +315,10 @@ void ParseExceptions()
315315
{ OpCodes.Blt_Un_S, OpCodes.Blt_Un }
316316
};
317317

318-
internal List<CodeInstruction> FinalizeILCodes(Emitter emitter, List<MethodInfo> transpilers, List<Label> endLabels, out bool hasReturnCode)
318+
internal List<CodeInstruction> FinalizeILCodes(Emitter emitter, List<MethodInfo> transpilers, List<Label> endLabels, out bool hasReturnCode, out bool endsInThrow)
319319
{
320320
hasReturnCode = false;
321+
endsInThrow = false;
321322
if (generator is null) return null;
322323

323324
// pass1 - define labels and add them to instructions that are target of a jump
@@ -381,6 +382,7 @@ internal List<CodeInstruction> FinalizeILCodes(Emitter emitter, List<MethodInfo>
381382
// pass4 - check for any RET
382383
//
383384
hasReturnCode = codeInstructions.Any(code => code.opcode == OpCodes.Ret);
385+
endsInThrow = codeInstructions.LastOrDefault()?.opcode == OpCodes.Throw;
384386

385387
// pass5 - remove RET if it appears at the end
386388
//

Harmony/Internal/MethodPatcher.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ internal MethodInfo CreateReplacement(out Dictionary<int, CodeInstruction> final
139139
copier.AddTranspiler(PatchTools.m_GetExecutingAssemblyReplacementTranspiler);
140140

141141
var endLabels = new List<Label>();
142-
var lastCode = copier.Finalize(emitter, endLabels, out var hasReturnCode).LastOrDefault();
143-
var endsInThrow = lastCode != null && lastCode.opcode == OpCodes.Throw;
142+
_ = copier.Finalize(emitter, endLabels, out var hasReturnCode, out var endsInThrow);
144143

145144
foreach (var label in endLabels)
146145
emitter.MarkLabel(label);

HarmonyTests/Patching/Assets/Specials.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using HarmonyLib;
22
using System;
33
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.IO;
46
using System.Linq;
57
using System.Reflection;
68
using System.Reflection.Emit;
@@ -113,6 +115,33 @@ static Exception Cleanup()
113115
}
114116
}
115117

118+
public class LateThrowClass
119+
{
120+
StringBuilder builder;
121+
122+
public void Method()
123+
{
124+
if (builder == null)
125+
{
126+
builder = new StringBuilder();
127+
var num = builder.Length == 123;
128+
129+
// this throw is the last IL code before 'ret' in this method
130+
if (num == false)
131+
throw new Exception("Test");
132+
}
133+
}
134+
}
135+
136+
[HarmonyPatch(typeof(LateThrowClass), nameof(LateThrowClass.Method))]
137+
public class LateThrowClass_Patch
138+
{
139+
static bool Prefix()
140+
{
141+
return false;
142+
}
143+
}
144+
116145
public struct SomeStruct
117146
{
118147
public bool accepted;

HarmonyTests/Patching/Specials.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,31 @@ public void Test_PatchException()
156156
Assert.NotNull(exception, "expecting runtime exception");
157157
}
158158

159+
[Test]
160+
public void Test_PatchingLateThrow()
161+
{
162+
var patchClass = typeof(LateThrowClass_Patch);
163+
Assert.NotNull(patchClass);
164+
165+
try
166+
{
167+
new LateThrowClass().Method();
168+
Assert.Fail("expecting exception");
169+
}
170+
catch (Exception ex)
171+
{
172+
Assert.AreEqual(ex.Message, "Test");
173+
}
174+
175+
var instance = new Harmony("test");
176+
Assert.NotNull(instance);
177+
var patcher = instance.CreateClassProcessor(patchClass);
178+
Assert.NotNull(patcher);
179+
Assert.NotNull(patcher.Patch());
180+
181+
new LateThrowClass().Method();
182+
}
183+
159184
[Test]
160185
public void Test_PatchExceptionWithCleanup2()
161186
{

0 commit comments

Comments
 (0)