wliao008 / buffalo

an aspect oriented programming framework using mono cecil for the .NET platform
1 stars 0 forks source link

Running an assembly through BuffaloAOP multiple times would cause InvalidProgramException #24

Open wliao008 opened 11 years ago

wliao008 commented 11 years ago

Although it did still decompile valid c#. For example, the MSIL is out of whack. A simple method being injected twice looks something like this:

[Trace]
public void Say(string msg)
{
    int num = 1;
    object[] array = new object[num];
    array[0] = msg;
    MethodArgs methodArgs = new MethodArgs();
    methodArgs.SetProperties("Say", "System.Void Shared.Utility::Say(System.String)", "System.Void", "msg:System.String|", array, this);
    Trace trace = new Trace();
    try
    {
        trace.OnBefore(methodArgs);
        int num2 = 1;
        object[] array2 = new object[num2];
        array2[0] = msg;
        MethodArgs methodArgs2 = new MethodArgs();
        methodArgs2.SetProperties("Say", "System.Void Shared.Utility::Say(System.String)", "System.Void", "msg:System.String|", array2, this);
        Trace trace2 = new Trace();
        try
        {
            trace2.OnBefore(methodArgs2);
            int num3 = 0;
            int num4 = 1 / num3;
            trace2.OnSuccess(methodArgs2);
        }
        catch (Exception exception)
        {
            methodArgs2.SetException(exception);
            trace2.OnException(methodArgs2);
        }
        finally
        {
            trace2.OnAfter(methodArgs2);
        }
    }
    catch (Exception exception2)
    {
        methodArgs.SetException(exception2);
        trace.OnException(methodArgs);
    }
    finally
    {
        trace.OnAfter(methodArgs);
    }
}

with the following MSIL:

.method public hidebysig 
    instance void Say (
        string msg
    ) cil managed 
{
    .custom instance void Shared.Trace::.ctor() = (
        01 00 00 00
    )
    // Method begins at RVA 0x20b4
    // Code size 344 (0x158)
    .maxstack 7
    .locals init (
        [0] int32,
        [1] int32,
        [2] int32,
        [3] object[],
        [4] class [Buffalo]Buffalo.MethodArgs,
        [5] class Shared.Trace,
        [6] class [mscorlib]System.Exception,
        [7] int32,
        [8] object[],
        [9] class [Buffalo]Buffalo.MethodArgs,
        [10] class Shared.Trace,
        [11] class [mscorlib]System.Exception
    )

    IL_0000: ldc.i4 1
    IL_0005: stloc 7
    IL_0009: ldloc 7
    IL_000d: newarr [mscorlib]System.Object
    IL_0012: stloc 8
    IL_0016: ldloc 8
    IL_001a: ldc.i4 0
    IL_001f: ldarg msg
    IL_0023: stelem.ref
    IL_0024: newobj instance void [Buffalo]Buffalo.MethodArgs::.ctor()
    IL_0029: stloc 9
    IL_002d: ldloc 9
    IL_0031: ldstr "Say"
    IL_0036: ldstr "System.Void Shared.Utility::Say(System.String)"
    IL_003b: ldstr "System.Void"
    IL_0040: ldstr "msg:System.String|"
    IL_0045: ldloc 8
    IL_0049: ldarg.0
    IL_004a: callvirt instance void [Buffalo]Buffalo.MethodArgs::SetProperties(string, string, string, string, object[], object)
    IL_004f: newobj instance void Shared.Trace::.ctor()
    IL_0054: stloc 10
    IL_0058: ldloc 10
    IL_005c: ldloc 9
    IL_0060: callvirt instance void Shared.Trace::OnBefore(class [Buffalo]Buffalo.MethodArgs)
    IL_0065: ldc.i4 1
    IL_006a: stloc 2
    IL_006e: ldloc 2
    IL_0072: newarr [mscorlib]System.Object
    IL_0077: stloc 3
    IL_007b: ldloc 3
    IL_007f: ldc.i4 0
    IL_0084: ldarg msg
    IL_0088: stelem.ref
    IL_0089: newobj instance void [Buffalo]Buffalo.MethodArgs::.ctor()
    IL_008e: stloc 4
    IL_0092: ldloc 4
    IL_0096: ldstr "Say"
    IL_009b: ldstr "System.Void Shared.Utility::Say(System.String)"
    IL_00a0: ldstr "System.Void"
    IL_00a5: ldstr "msg:System.String|"
    IL_00aa: ldloc 3
    IL_00ae: ldarg.0
    IL_00af: callvirt instance void [Buffalo]Buffalo.MethodArgs::SetProperties(string, string, string, string, object[], object)
    IL_00b4: newobj instance void Shared.Trace::.ctor()
    IL_00b9: stloc 5
    .try
    {
        .try
        {
            IL_00bd: ldloc 5
            IL_00c1: ldloc 4
            IL_00c5: callvirt instance void Shared.Trace::OnBefore(class [Buffalo]Buffalo.MethodArgs)
            IL_00ca: nop
            IL_00cb: ldc.i4.0
            IL_00cc: stloc.0
            IL_00cd: ldc.i4.1
            IL_00ce: ldloc.0
            IL_00cf: div
            IL_00d0: stloc.1
            IL_00d1: ldloc 5
            IL_00d5: ldloc 4
            IL_00d9: callvirt instance void Shared.Trace::OnSuccess(class [Buffalo]Buffalo.MethodArgs)
            IL_00de: leave IL_0157
        } // end .try
        catch [mscorlib]System.Exception
        {
            IL_00e3: stloc 6
            IL_00e7: ldloc 4
            IL_00eb: ldloc 6
            IL_00ef: callvirt instance void [Buffalo]Buffalo.MethodArgs::SetException(class [mscorlib]System.Exception)
            IL_00f4: ldloc 5
            IL_00f8: ldloc 4
            IL_00fc: callvirt instance void Shared.Trace::OnException(class [Buffalo]Buffalo.MethodArgs)
            IL_0101: leave IL_0157
        } // end handler
    } // end .try
    finally
    {
        IL_0106: ldloc 5
        IL_010a: ldloc 4
        IL_010e: callvirt instance void Shared.Trace::OnAfter(class [Buffalo]Buffalo.MethodArgs)
        IL_0113: endfinally

        IL_0114: ldloc 10
        IL_0118: ldloc 9
        IL_011c: callvirt instance void Shared.Trace::OnSuccess(class [Buffalo]Buffalo.MethodArgs)
        IL_0121: leave IL_0157
        catch [mscorlib]System.Exception
        {
            IL_0126: stloc 11
            IL_012a: ldloc 9
            IL_012e: ldloc 11
            IL_0132: callvirt instance void [Buffalo]Buffalo.MethodArgs::SetException(class [mscorlib]System.Exception)
            IL_0137: ldloc 10
            IL_013b: ldloc 9
            IL_013f: callvirt instance void Shared.Trace::OnException(class [Buffalo]Buffalo.MethodArgs)
            IL_0144: leave IL_0157
        } // end handler
        finally
        {
            IL_0149: ldloc 10
            IL_014d: ldloc 9
            IL_0151: callvirt instance void Shared.Trace::OnAfter(class [Buffalo]Buffalo.MethodArgs)
            IL_0156: endfinally
        } // end handler
    } // end handler

    IL_0157: ret
} // end of method Utility::Say

The finally block is clearing wrong. This has to do with the positioning of the catch and finally handlers. And another question, an injected assembly maybe shouldn't be injected again? Maybe flag it in the assembly?

Need to think about how to handle this.