From 2ea021afcf1811c9f4a4a05b02ba4c7fa188ad9d Mon Sep 17 00:00:00 2001 From: kohanis Date: Fri, 19 Jan 2024 17:17:24 +0300 Subject: [PATCH] Fix for unintentional removal of some `leave` instructions (#96) This will keep 2 leave instructions, but it's jump anyway, no harm done. Upstream harmony makes it this way. These instructions are added after all transpilers have already been applied, and repatching takes original instructions anyway. And, if someone wants to, they can find a way to remove these duplicates without offset shifting later on. Fixes #65 and Closes #77 --- Harmony/Internal/Patching/ILManipulator.cs | 8 ++------ Harmony/Tools/Extensions.cs | 24 ---------------------- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/Harmony/Internal/Patching/ILManipulator.cs b/Harmony/Internal/Patching/ILManipulator.cs index 1af400be..d887ab16 100644 --- a/Harmony/Internal/Patching/ILManipulator.cs +++ b/Harmony/Internal/Patching/ILManipulator.cs @@ -340,17 +340,13 @@ public void WriteTo(MethodBody body, MethodBase original = null) var newInstructions = ApplyTranspilers(cil, original, vDef => il.GetLocal(vDef), il.DefineLabel); // Step 2: Emit code - foreach (var (cur, next) in newInstructions.Pairwise()) + foreach (var cur in newInstructions) { cur.labels.ForEach(l => il.MarkLabel(l)); cur.blocks.ForEach(b => il.MarkBlockBefore(b)); // We need to handle exception handler opcodes specially because ILProcessor emits them automatically - // Case 1: leave + start or end of exception block => ILProcessor generates leave automatically - if ((cur.opcode == SRE.OpCodes.Leave || cur.opcode == SRE.OpCodes.Leave_S) && - (cur.blocks.Count > 0 || next?.blocks.Count > 0)) - goto mark_block; - // Case 2: endfilter/endfinally and end of exception marker => ILProcessor will generate the correct end + // Case: endfilter/endfinally and end of exception marker => ILProcessor will generate the correct end if ((cur.opcode == SRE.OpCodes.Endfilter || cur.opcode == SRE.OpCodes.Endfinally) && cur.blocks.Count > 0) goto mark_block; // Other cases are either intentional leave or invalid IL => let them be processed and let JIT generate correct exception diff --git a/Harmony/Tools/Extensions.cs b/Harmony/Tools/Extensions.cs index 4052b2ea..e1b56c5b 100644 --- a/Harmony/Tools/Extensions.cs +++ b/Harmony/Tools/Extensions.cs @@ -595,30 +595,6 @@ internal static Dictionary TransformKeys(this Dictionary origD dict.Add(transform(pair.Key), pair.Value); return dict; } - - // Iterates the enumerable pairwise, i.e. by returning tuple (current, next) - internal static IEnumerable<(T, T)> Pairwise(this IEnumerable self) - { - var isFirst = true; - T prev = default; - - foreach (var e in self) - if (isFirst) - { - prev = e; - isFirst = false; - } - else - { - yield return (prev, e); - prev = e; - } - - if (isFirst) - yield break; - - yield return (prev, default); - } } /// General extensions for collections