Skip to content
This repository was archived by the owner on Jul 15, 2023. It is now read-only.
This repository was archived by the owner on Jul 15, 2023. It is now read-only.

CCRewriter produces invalid IL on async method or iterator blocks #38

@SergeyTeplyakov

Description

@SergeyTeplyakov

Code Contracts version: 1.7.11202.10 (reproduces on earlier versions as well).
Perform Runtime Contract Checking != Full
Debug/Release: both

Using CCRewrite with Perform Runtime Contract Checking not equals to Full with async method (or methods with iterator blocks) with complex Contract.Requires (that has II or && in it) provides invalid assembly. Using such an assembly leads to System.InvalidProgramExecution exception and peverify shows following error:

[IL]: Error: [PATHToExecutable\CcRewriterBug\bin\Release\CCRewriterBug.exe:
CcRewriterBug.Program+<FooEnumerable>d__3::MoveNext][offset 0x00000021] Stack underflow

Steps to reproduce:

static async Task FooAsync(string str)
{
   // Works fine with Contract.Requires(str != null);
    Contract.Requires(str != null && str.Length > 1);
    await Task.Delay(42);
}

or

static IEnumerable<string> FooEnumerable(string str)
{
    Contract.Requires(str != null && str.Length > 1);
    yield return str;
}

In latter case if Perform Runtime Contract Checking is not Full CCRewrite produces following IL in MoveMethod:

.method private final hidebysig newslot virtual 
    instance bool MoveNext () cil managed 
{
    .override method instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    // Method begins at RVA 0x21ac
    // Code size 64 (0x40)
    .maxstack 2
    .locals init (
        [0] int32 CS$0$0000
    )

    IL_0000: ldarg.0
    IL_0001: ldfld int32 CcRewriterBug.Program/'<FooEnumerable>d__0'::'<>1__state'
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: switch (IL_001a, IL_0037)

    IL_0015: br IL_003e

    IL_001a: ldarg.0
    IL_001b: ldc.i4.m1
    IL_001c: stfld int32 CcRewriterBug.Program/'<FooEnumerable>d__0'::'<>1__state'
    IL_0021: pop // this instruction is invalid!
    IL_0022: ldarg.0
    IL_0023: ldarg.0
    IL_0024: ldfld string CcRewriterBug.Program/'<FooEnumerable>d__0'::str
    IL_0029: stfld string CcRewriterBug.Program/'<FooEnumerable>d__0'::'<>2__current'
    IL_002e: ldarg.0
    IL_002f: ldc.i4.1
    IL_0030: stfld int32 CcRewriterBug.Program/'<FooEnumerable>d__0'::'<>1__state'
    IL_0035: ldc.i4.1
    IL_0036: ret

    IL_0037: ldarg.0
    IL_0038: ldc.i4.m1
    IL_0039: stfld int32 CcRewriterBug.Program/'<FooEnumerable>d__0'::'<>1__state'

    IL_003e: ldc.i4.0
    IL_003f: ret
} // end of method '<FooEnumerable>d__0'::MoveNext```

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions