jbevain / cecil

Cecil is a library to inspect, modify and create .NET programs and libraries.
MIT License
2.76k stars 627 forks source link

Bug: PInvoke information is not saved to assembly properly #926

Closed mhmd-azeez closed 1 year ago

mhmd-azeez commented 1 year ago

I am trying to add PInvokeInfo to a method and then save it, but it doesn't seem to get saved properly. Am I missing something?

Repro:

[Fact]
public void PInvoke()
{
    // Create a new assembly
    var assemblyName = new AssemblyNameDefinition("MyAssembly", new Version(1, 0, 0, 0));
    var assembly = AssemblyDefinition.CreateAssembly(assemblyName, "MyAssembly", ModuleKind.Dll);

    // Create a new type
    var type = new TypeDefinition(
        "MyNamespace",
        "MyType",
        TypeAttributes.Class | TypeAttributes.Public,
        assembly.MainModule.ImportReference(typeof(object))
    );

    // Add the type to the assembly
    assembly.MainModule.Types.Add(type);

    // Create a method in the type
    var method = new MethodDefinition(
        "MyMethod",
        MethodAttributes.Static | MethodAttributes.Public,
        assembly.MainModule.ImportReference(typeof(void))
    )
    {
        IsPInvokeImpl = true
    };

    var pinvokeInfo = new PInvokeInfo(PInvokeAttributes.CallConvCdecl, "my_method", new ModuleReference("lib"));
    method.PInvokeInfo = pinvokeInfo;
    method.Attributes |= MethodAttributes.PInvokeImpl;
    method.ImplAttributes |= MethodImplAttributes.PreserveSig | (MethodImplAttributes)pinvokeInfo.Attributes;

    type.Methods.Add(method);

    // Save the assembly to disk
    assembly.Write("MyAssembly.dll");

    var readAssembly = AssemblyDefinition.ReadAssembly("MyAssembly.dll");
    var readMethod = readAssembly.MainModule.GetType(type.FullName).GetMethods().First(m => m.Name == method.Name);
    Assert.True(readMethod.HasPInvokeInfo); // this passes
    var x = readMethod.PInvokeInfo; // this throws
}

Expected

x should contain the method's PInvokeInfo

Actual

Message: 
System.IndexOutOfRangeException : Index was outside the bounds of the array.

Stack Trace: 
Collection`1.get_Item(Int32 index)
MetadataReader.ReadPInvokeInfo(MethodDefinition method)
<>c.<get_PInvokeInfo>b__49_0(MethodDefinition method, MetadataReader reader)
ModuleDefinition.Read[TItem,TRet](TRet& variable, TItem item, Func`3 read)
MethodDefinition.get_PInvokeInfo()
ExtismFFIGeneratorTests.PInvoke() line 213
RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

dotPeek can't decompile the assembly either: image

Version:

0.11.5