Skip to content

Commit

Permalink
Fixed bug in patch argument passing when first argument isn't instanc…
Browse files Browse the repository at this point in the history
…e but return buffer pointer
  • Loading branch information
pardeike committed Feb 9, 2020
1 parent 25fede0 commit cfbd9f3
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 12 deletions.
13 changes: 9 additions & 4 deletions Harmony/Internal/MethodPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class MethodPatcher
public const string PARAM_INDEX_PREFIX = "__";
public const string INSTANCE_FIELD_PREFIX = "___";

readonly bool debug;
readonly MethodBase original;
readonly MethodBase source;
readonly List<MethodInfo> prefixes;
Expand All @@ -28,6 +29,7 @@ internal class MethodPatcher
readonly List<MethodInfo> finalizers;
readonly int idx;
readonly bool firstArgIsReturnBuffer;
readonly OpCode Ldarg_instance;
readonly Type returnType;
readonly DynamicMethodDefinition patch;
readonly ILGenerator il;
Expand All @@ -38,6 +40,7 @@ internal MethodPatcher(MethodBase original, MethodBase source, List<MethodInfo>
if (original == null)
throw new ArgumentNullException(nameof(original));

this.debug = debug;
this.original = original;
this.source = source;
this.prefixes = prefixes;
Expand All @@ -55,6 +58,8 @@ internal MethodPatcher(MethodBase original, MethodBase source, List<MethodInfo>

idx = prefixes.Count() + postfixes.Count() + finalizers.Count();
firstArgIsReturnBuffer = NativeThisPointer.NeedsNativeThisPointerFix(original);
Ldarg_instance = firstArgIsReturnBuffer ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0;
if (debug && firstArgIsReturnBuffer) FileLog.Log($"### Special case: Ldarg.0 is return buffer, not instance!");
returnType = AccessTools.GetReturnedType(original);
patch = CreateDynamicMethod(original, $"_Patch{idx}");
if (patch == null)
Expand All @@ -64,7 +69,7 @@ internal MethodPatcher(MethodBase original, MethodBase source, List<MethodInfo>
emitter = new Emitter(il, debug);
}

internal MethodInfo CreateReplacement(bool debug, out Dictionary<int, CodeInstruction> finalInstructions)
internal MethodInfo CreateReplacement(out Dictionary<int, CodeInstruction> finalInstructions)
{
var originalVariables = DeclareLocalVariables(source ?? original);
var privateVars = new Dictionary<string, LocalBuilder>();
Expand Down Expand Up @@ -354,11 +359,11 @@ void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variab
var parameterIsRef = patchParam.ParameterType.IsByRef;
if (instanceIsRef == parameterIsRef)
{
emitter.Emit(OpCodes.Ldarg_0);
emitter.Emit(Ldarg_instance);
}
if (instanceIsRef && parameterIsRef == false)
{
emitter.Emit(OpCodes.Ldarg_0);
emitter.Emit(Ldarg_instance);
emitter.Emit(OpCodes.Ldobj, original.DeclaringType);
}
if (instanceIsRef == false && parameterIsRef)
Expand Down Expand Up @@ -391,7 +396,7 @@ void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variab
emitter.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldsflda : OpCodes.Ldsfld, fieldInfo);
else
{
emitter.Emit(OpCodes.Ldarg_0);
emitter.Emit(Ldarg_instance);
emitter.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, fieldInfo);
}
continue;
Expand Down
16 changes: 10 additions & 6 deletions Harmony/Internal/NativeThisPointerCheck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,19 +116,23 @@ private static IEnumerable<CodeInstruction> ArgumentShiftTranspiler(IEnumerable<
continue;
}

if (instruction.opcode == OpCodes.Ldarg_0)
{
instruction.opcode = OpCodes.Ldarg_1;
yield return instruction;
continue;
}

if (instruction.opcode == OpCodes.Ldarg
|| instruction.opcode == OpCodes.Ldarga
|| instruction.opcode == OpCodes.Ldarga_S
|| instruction.opcode == OpCodes.Starg
|| instruction.opcode == OpCodes.Starg_S)
{
var n = (int)instruction.operand;
if (n > 0)
{
instruction.operand = n + 1;
yield return instruction;
continue;
}
instruction.operand = n + 1;
yield return instruction;
continue;
}

yield return instruction;
Expand Down
4 changes: 2 additions & 2 deletions Harmony/Internal/PatchFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ internal static MethodInfo UpdateWrapper(MethodBase original, PatchInfo patchInf
var sortedFinalizers = GetSortedPatchMethods(original, patchInfo.finalizers, debug);

var patcher = new MethodPatcher(original, null, sortedPrefixes, sortedPostfixes, sortedTranspilers, sortedFinalizers, debug);
var replacement = patcher.CreateReplacement(debug, out var finalInstructions);
var replacement = patcher.CreateReplacement(out var finalInstructions);
if (replacement == null) throw new MissingMethodException($"Cannot create replacement for {original.FullDescription()}");

try
Expand Down Expand Up @@ -191,7 +191,7 @@ internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase origin

var empty = new List<MethodInfo>();
var patcher = new MethodPatcher(standin.method, original, empty, empty, transpilers, empty, debug);
var replacement = patcher.CreateReplacement(debug, out var finalInstructions);
var replacement = patcher.CreateReplacement(out var finalInstructions);
if (replacement == null) throw new MissingMethodException($"Cannot create replacement for {standin.method.FullDescription()}");

try
Expand Down

0 comments on commit cfbd9f3

Please sign in to comment.