From d90d730a1afb80a8285f67ce380cc60fa4a0c9d8 Mon Sep 17 00:00:00 2001 From: kohanis Date: Thu, 29 Feb 2024 00:03:43 +0300 Subject: [PATCH] Fix prefix skipping for dead-end code --- Harmony/Internal/MethodPatcher.cs | 4 ++-- HarmonyTests/Patching/Assets/Specials.cs | 2 ++ HarmonyTests/Patching/Specials.cs | 22 +++++++++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Harmony/Internal/MethodPatcher.cs b/Harmony/Internal/MethodPatcher.cs index c22a64ef..3c19924d 100644 --- a/Harmony/Internal/MethodPatcher.cs +++ b/Harmony/Internal/MethodPatcher.cs @@ -164,7 +164,7 @@ internal MethodInfo CreateReplacement(out Dictionary final _ = AddPostfixes(privateVars, runOriginalVariable, false); - if (resultVariable is not null && hasReturnCode) + if (resultVariable is not null && (hasReturnCode || (methodEndsInDeadCode && skipOriginalLabel is not null))) emitter.Emit(OpCodes.Ldloc, resultVariable); var needsToStorePassthroughResult = AddPostfixes(privateVars, runOriginalVariable, true); @@ -219,7 +219,7 @@ internal MethodInfo CreateReplacement(out Dictionary final emitter.Emit(OpCodes.Ldloc, resultVariable); } - if (methodEndsInDeadCode == false || hasFinalizers || postfixes.Count > 0) + if (methodEndsInDeadCode == false || skipOriginalLabel is not null || hasFinalizers || postfixes.Count > 0) emitter.Emit(OpCodes.Ret); finalInstructions = emitter.GetInstructions(); diff --git a/HarmonyTests/Patching/Assets/Specials.cs b/HarmonyTests/Patching/Assets/Specials.cs index 067ea2f6..d5cdfa29 100644 --- a/HarmonyTests/Patching/Assets/Specials.cs +++ b/HarmonyTests/Patching/Assets/Specials.cs @@ -104,6 +104,8 @@ public class DeadEndCode_Patch1 public static void Prefix() => prefixCalled = true; public static void Postfix() => postfixCalled = true; + + public static bool PrefixWithControl() => false; } [HarmonyPatch(typeof(DeadEndCode), nameof(DeadEndCode.Method))] diff --git a/HarmonyTests/Patching/Specials.cs b/HarmonyTests/Patching/Specials.cs index 5daa2214..55215905 100644 --- a/HarmonyTests/Patching/Specials.cs +++ b/HarmonyTests/Patching/Specials.cs @@ -179,6 +179,9 @@ public void Test_PatchException() Assert.NotNull(prefix); var postfix = AccessTools.Method(typeof(DeadEndCode_Patch1), nameof(DeadEndCode_Patch1.Postfix)); Assert.NotNull(postfix); + var prefixWithControl = + AccessTools.Method(typeof(DeadEndCode_Patch1), nameof(DeadEndCode_Patch1.PrefixWithControl)); + Assert.NotNull(postfix); // run original try @@ -208,13 +211,16 @@ public void Test_PatchException() } Assert.True(DeadEndCode_Patch1.prefixCalled); + + var isMonoRuntime = AccessTools.IsMonoRuntime; + var harmonyMethodPostfix = new HarmonyMethod(postfix); // patch: +postfix - if (AccessTools.IsMonoRuntime) + if (isMonoRuntime) { // mono should fail try { - _ = instance.Patch(original, postfix: new HarmonyMethod(postfix)); + _ = instance.Patch(original, postfix: harmonyMethodPostfix); Assert.Fail("expecting patch exception"); } catch (Exception ex) @@ -226,7 +232,7 @@ public void Test_PatchException() { // non-mono can add postfix to methods ending in dead code - _ = instance.Patch(original, postfix: new HarmonyMethod(prefix)); + _ = instance.Patch(original, postfix: harmonyMethodPostfix); DeadEndCode_Patch1.prefixCalled = false; DeadEndCode_Patch1.postfixCalled = false; // run original @@ -242,6 +248,16 @@ public void Test_PatchException() Assert.False(DeadEndCode_Patch1.postfixCalled); } } + + _ = instance.Patch(original, + prefix: new HarmonyMethod(prefixWithControl), + postfix: isMonoRuntime ? harmonyMethodPostfix : null + ); + DeadEndCode_Patch1.prefixCalled = false; + DeadEndCode_Patch1.postfixCalled = false; + test.Method(); + Assert.True(DeadEndCode_Patch1.prefixCalled); + Assert.True(DeadEndCode_Patch1.postfixCalled); } [Test]