IConstructorInterceptor causes assembly to fail verification (and won't run)
0x15e opened this issue · comments
Using package versions:
- Fody: 3.2.4
- Cauldron.Interception.Fody: 3.0.34 (and latest beta)
- Cauldron.BasicInterceptors: 3.0.33 (and latest beta)
Attempting to build a .NET Framework console app for framework 4.7.2. There's nothing in the project but the necessary nuget packages for the interceptors, an attribute class, a class where it's applied, and Program.cs.
peverify /verbose
produces the error:
Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.0
Copyright (c) Microsoft Corporation. All rights reserved.
[IL]: Error: [C:\Users\0x15e\source\repos\CauldronExeFailReproduction\CauldronExeFailReproduction\bin\Debug\CauldronExeFailReproduction.exe : CauldronExeFailReproduction.TestSubject::.ctor][mdToken=0x6000008][offset 0x0000006C][found ref 'Cauldron.Interception.IConstructorInterceptor'][expected ref 'System.Exception'] Unexpected type on the stack.
[IL]: Error: [C:\Users\0x15e\source\repos\CauldronExeFailReproduction\CauldronExeFailReproduction\bin\Debug\CauldronExeFailReproduction.exe : CauldronExeFailReproduction.TestSubject::.ctor][mdToken=0x6000008][offset 0x0000006C] Stack underflow.
2 Error(s) Verifying CauldronExeFailReproduction.exe
Attempting to run it anyway results in a System.InvalidProgramException: "Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program."
Here's the IL of the class where the interceptor is applied:
.class public auto ansi beforefieldinit CauldronExeFailReproduction.TestSubject
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
string someParam
) cil managed
{
// Method begins at RVA 0x20d4
// Code size 115 (0x73)
.maxstack 5
.locals init (
[0] object[],
[1] class [Cauldron.Interception]Cauldron.Interception.IConstructorInterceptor,
[2] class [mscorlib]System.Exception
)
// (no C# code)
IL_0000: ldc.i4.1
IL_0001: newarr [mscorlib]System.Object
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.0
// object[] values = new object[1]
// {
// someParam
// };
IL_0009: ldarg.1
// (no C# code)
IL_000a: stelem.ref
// IConstructorInterceptor constructorInterceptor = new TestConstructorFailureAttribute();
IL_000b: newobj instance void CauldronExeFailReproduction.TestConstructorFailureAttribute::.ctor()
IL_0010: stloc.1
// constructorInterceptor.OnBeforeInitialization(typeof(TestSubject), MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(TestSubject).TypeHandle), values);
IL_0011: ldloc.1
IL_0012: ldtoken CauldronExeFailReproduction.TestSubject
IL_0017: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001c: ldtoken method instance void CauldronExeFailReproduction.TestSubject::.ctor(string)
IL_0021: ldtoken CauldronExeFailReproduction.TestSubject
IL_0026: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle, valuetype [mscorlib]System.RuntimeTypeHandle)
IL_002b: ldloc.0
IL_002c: callvirt instance void [Cauldron.Interception]Cauldron.Interception.IConstructorInterceptor::OnBeforeInitialization(class [mscorlib]System.Type, class [mscorlib]System.Reflection.MethodBase, object[])
// base..ctor();
IL_0031: ldarg.0
IL_0032: call instance void [mscorlib]System.Object::.ctor()
.try
{
.try
{
// constructorInterceptor.OnEnter(typeof(TestSubject), this, MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/, typeof(TestSubject).TypeHandle), values);
IL_0037: ldloc.1
IL_0038: ldtoken CauldronExeFailReproduction.TestSubject
IL_003d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0042: ldarg.0
IL_0043: ldtoken method instance void CauldronExeFailReproduction.TestSubject::.ctor(string)
IL_0048: ldtoken CauldronExeFailReproduction.TestSubject
IL_004d: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle, valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0052: ldloc.0
IL_0053: callvirt instance void [Cauldron.Interception]Cauldron.Interception.IConstructorInterceptor::OnEnter(class [mscorlib]System.Type, object, class [mscorlib]System.Reflection.MethodBase, object[])
// (no C# code)
IL_0058: leave.s IL_0072
} // end .try
catch [mscorlib]System.Exception
{
IL_005a: stloc.2
// if (constructorInterceptor.OnException(e))
IL_005b: ldloc.1
IL_005c: ldloc.2
IL_005d: callvirt instance bool [Cauldron.Interception]Cauldron.Interception.IConstructorInterceptor::OnException(class [mscorlib]System.Exception)
// (no C# code)
IL_0062: ldc.i4.1
IL_0063: ceq
IL_0065: brfalse.s IL_0069
IL_0067: rethrow
IL_0069: leave.s IL_0072
} // end handler
} // end .try
finally
{
// ((IConstructorInterceptor)/*Error near IL_006c: Stack underflow*/).OnException((Exception)constructorInterceptor);
IL_006b: ldloc.1
IL_006c: callvirt instance bool [Cauldron.Interception]Cauldron.Interception.IConstructorInterceptor::OnException(class [mscorlib]System.Exception)
// (no C# code)
IL_0071: endfinally
} // end handler
IL_0072: ret
} // end of method TestSubject::.ctor
} // end of class CauldronExeFailReproduction.TestSubject
Does it have the same error in Release mode with optimization turned on?
I just checked and confirmed the same thing happens in Release with optimizations on (also regardless of platform target and bitness preference).
In case it helps anything, here are my msbuild and csc versions:
- msbuild: 15.8.169+g1ccb72aefa
- csc: 2.9.0.63208 (958f2354)
OK thanks… I'll look into this as soon as possible.
Fixed … Next version will have the fix...
Fantastic. I just built from source and confirmed everything's working on my end as well. Thanks!
Nuget packages are coming. I am unlisting older and merged packages.