CIL: “Operation could destabilize the runtime” exc

2019-08-03 02:48发布

I've been playing with PostSharp a bit and I ran into a nasty problem.

Following IL in Silverlight assembly:

.method public hidebysig specialname newslot virtual final instance void 
set_AccountProfileModifiedAt(valuetype [mscorlib]System.DateTime 'value') cil managed
{
    .maxstack 2
    .locals (
        [0] bool ~propertyHasChanged,
        [1] bool CS$4$0000)
    L_0000: nop 
    L_0001: nop 
    L_0002: ldarg.0 
    L_0003: call instance valuetype [mscorlib]System.DateTime 

Accounts.AccountOwner::get_AccountProfileModifiedAt()
    L_0008: ldarg.1 
    L_0009: call bool [mscorlib]System.DateTime::op_Inequality(valuetype 

[mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
    L_000e: stloc.0 
    L_000f: ldarg.0 
    L_0010: ldarg.1 
    L_0011: stfld valuetype [mscorlib]System.DateTime 

Accounts.AccountOwner::accountProfileModifiedAt
    L_0016: br.s L_0018
    L_0018: ldloc.0 
    L_0019: ldc.i4.0 
    L_001a: ceq 
    L_001c: stloc.1 
    L_001d: ldloc.1 
    L_001e: brtrue.s L_002b
    L_0020: ldarg.0 
    L_0021: ldstr "AccountProfileModifiedAt"
    L_0026: call instance void 

Accounts.AccountOwner::NotifyPropertyChanged(string)
    L_002b: nop 
    L_002c: leave.s L_002e
    L_002e: ret 
}

triggers System.Security.VerificationException: Operation could destabilize the runtime. exception. Reflector parses it OK. What could be wrong with it?

Update 1 Code is intended to work as follows:

public void set_AccountProfileModifiedAt(DateTime value)
{
    bool propertyHasChanged = this.AccountProfileModifiedAt != value;
    this.accountProfileModifiedAt = value;
    if (propertyHasChanged)
    {
        this.NotifyPropertyChanged("AccountProfileModifiedAt");
    }
}

Update 2 I get specified exception inside the setter itself

Update 3 Making non-static calls as callvirt (NotifyPropertyChanged) does not help

Update 4 Commenting out (for test purposes) code:

L_0018: ldloc.0 
L_0019: ldc.i4.0 
L_001a: ceq 
L_001c: stloc.1 
L_001d: ldloc.1 

and replacing L_001e: brtrue.s L_002b with L_001e: br.s L_002b does the trick but it's an unconditional return - not what I want.

Update 5 If I use C# compiler to mimic required behavior (I still need to do that with Postsharp) I get following IL:

.method public hidebysig specialname newslot virtual final instance void 

set_AccountProfileModifiedAt(valuetype [mscorlib]System.DateTime 'value') cil managed
{
    .maxstack 2
    .locals init (
        [0] bool val,
        [1] bool CS$4$0000)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call instance valuetype [mscorlib]System.DateTime 

Accounts.AccountOwner::get_AccountProfileModifiedAt()
    L_0007: ldarg.1 
    L_0008: call bool [mscorlib]System.DateTime::op_Inequality(valuetype 

[mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
    L_000d: stloc.0 
    L_000e: ldarg.0 
    L_000f: ldarg.1 
    L_0010: stfld valuetype [mscorlib]System.DateTime 

Accounts.AccountOwner::accountProfileModifiedAt
    L_0015: ldloc.0 
    L_0016: ldc.i4.0 
    L_0017: ceq 
    L_0019: stloc.1 
    L_001a: ldloc.1 
    L_001b: brtrue.s L_0029
    L_001d: ldarg.0 
    L_001e: ldstr "AccountProfileModifiedAt"
    L_0023: call instance void 

Accounts.AccountOwner::NotifyPropertyChanged(string)
    L_0028: nop 
    L_0029: ret 
}

Note there are minor differences - extra br.s jump at L_0016 and some strange jump L_001e: brtrue.s L_002b. In compiler version I get direct jump to ret.

3条回答
对你真心纯属浪费
2楼-- · 2019-08-03 03:01

Here's a post that deals with that error. I don't know if your particular case is caused by the same problem, but in general it looks like this has to do with code access security and verification. If that's the case, Reflector will be able to read the IL just fine but the CAS system will kick it out for reasons unknown.

It looks like you have a property setter calling into a bunch of other objects. You should go through those other method calls looking for big switch statements, in case it is the specific issue mentioned in the post.

查看更多
Animai°情兽
3楼-- · 2019-08-03 03:02

Did you use peverify? You should always run this utility when playing directly with MSIL (you can use the msbuild flag /p:PostSharpVerify=true).

Looking at your code:

  1. Your local variables are not initialized (missing "init" keyword). This is a property of MethodBodyDeclaration.

  2. You are using a 'leave' instead of a 'jmp' out of a protected block; this is useless but should not matter.

Good luck,

-gael

查看更多
Deceive 欺骗
4楼-- · 2019-08-03 03:13

It is difficult to say - do you have a stack trace? This exception is usually thrown when the CLR is unable to verify the type-safety of your code. As this could have come from this code or from any of the methods or types you are using it will be difficult to say what the issue is without a stack trace.

查看更多
登录 后发表回答