Skip to content

Patching functions with ref parameters in IL2CPP #129

@qwerty01

Description

@qwerty01

Version Info

BepInEx version: 6.0.0-be.735 (commit: 5fef3570f212b2fb5fbe9c1d20487c13c2fa90cb)

Bug

When a function with ref parameters is hooked in an IL2CPP game, it appears that the HarmonyX portion of the hook does something that modifies the parameters even if the parameters aren't present in the hook callback, or even if there is a prefix at all.

Example

Decompiled IL2CPP interop layer:

public class DataLayer: BaseLayer
{
    public unsafe override void ProcessData(ref Il2CppStructArray<byte> data, ref int length)
    {
        // ...
    }
}

Original code (dumped from il2cpp metadata):

public class DataLayer: BaseLayer
{
    public override void ProcessData(ref byte[] data, ref int length)
    {
        // ...
    }
}

Plugin Hook:

[HarmonyPatch(typeof(DataLayer))]
internal static class DataValues
{
    [HarmonyPrefix]
    [HarmonyPatch("ProcessData")]
    private static void Data(Il2CppStructArray<byte> data, int length)
    {
        LogData(data, false, length);
    }
    [HarmonyPostfix]
    [HarmonyPatch("ProcessData")]
    private static void DataPost(Il2CppStructArray<byte> data, int length)
    {
        LogData(data, true, length);
    }
    private static void LogData(byte[] data, bool post, int length)
    {
        var d = string.Join(", ", data.Take(length).Select(x => x.ToString("X")));
        var dd = post ? " Post" : "";
        Plugin.Log.LogInfo($"Data{dd}: [{d}]");
    }
}

When the hook is active, the original function is called and there's an exception saying data's length is too small. This occurs even in the following circumstances:

  • The hook parameters are ref parameters instead of normal parameters
  • The function bodies of both the prefix and postfix are empty
  • The prefix and postfix functions are defined with no parameters
  • The prefix function is fully commented out, so only a postfix hook exists, with no parameters and an empty body

The only way to make the bug not show up is to completely remove all hooking on the target function.
There are also no errors in the log during hooking or when the prefix/postfix are run, the only exception is raised by the original function.

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions