Skip to content

Invalid IL produced by unreachable code blocks optimization #86304

Description

@MichalStrehovsky

IL Linker tries to remove unreachable basic blocks from exception filter blocks, but may strip the endfilter instruction in the process, making the IL invalid.

Ran into this in the CoreCLR Pri0 test suite because Native AOT also imported this bug. The CoreCLR test is in IL but it can be reached with C# - this is the simplest way to reach it (pardon the nonsensical code, didn't want to think about this much):

try
{
    throw new Exception();
}
catch when (IntPtr.Size == 8 ? throw new Exception() : true)
{
    Console.WriteLine("Hey");
}

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on May 16, 2023
  2. vitek-karas commented on May 16, 2023

    @vitek-karas
    Member

    I think I found a compiler bug... I played with the above sample and created this:

            try
            {
                throw new Exception();
            }
            catch when (IntPtr.Size == 8 ? throw new Exception() : throw new Exception())
            {
                Console.WriteLine("");
            }

    When compiled it produces IL like this:

    	.try
    	{
    		IL_0000: newobj instance void [System.Runtime]System.Exception::.ctor()
    		IL_0005: throw
    	} // end .try
    	IL_0006: pop
    	IL_0007: call int32 [System.Runtime]System.IntPtr::get_Size()
    	IL_000c: ldc.i4.8
    	IL_000d: pop
    	IL_000e: pop
    	IL_000f: newobj instance void [System.Runtime]System.Exception::.ctor()
    	IL_0014: throw
    

    It's a try block with no handlers.

    Trying to run this on CoreCLR produces:
    System.InvalidProgramException: Common Language Runtime detected an invalid program.

    Trying to trim this crashes Cecil:

      Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
         at Mono.Cecil.Cil.CodeReader.ReadExceptionHandlers(Int32 count, Func`1 read_entry, Func`1 read_length)
         at Mono.Cecil.Cil.CodeReader.ReadSmallSection()
         at Mono.Cecil.Cil.CodeReader.ReadSection()
         at Mono.Cecil.Cil.CodeReader.ReadFatMethod()
    

    NativeAOT actually handles this the best and prints out:
    ILC: Method '[FilterBlockRemoval]Repro.Test()' will always throw because: Invalid IL or CLR metadata
    (and then fails with InvalidProgramException at runtime).

  3. MichalStrehovsky commented on May 16, 2023

    @MichalStrehovsky
    MemberAuthor

    Heh, cursed pattern.

    There is a handler, but it's bogus (need to go to and uncheck View -> Expand try/catch in ILDasm UI):

    .method private hidebysig static void  '<Main>$'(string[] args) cil managed
    {
      .entrypoint
      // Code size       28 (0x1c)
      .maxstack  2
      .locals init (bool V_0)
      IL_0000:  nop
      IL_0001:  newobj     instance void [System.Runtime]System.Exception::.ctor()
      IL_0006:  throw
      IL_0007:  pop
      IL_0008:  call       int32 [System.Runtime]System.IntPtr::get_Size()
      IL_000d:  ldc.i4.8
      IL_000e:  beq.s      IL_0016
      IL_0010:  newobj     instance void [System.Runtime]System.Exception::.ctor()
      IL_0015:  throw
      IL_0016:  newobj     instance void [System.Runtime]System.Exception::.ctor()
      IL_001b:  throw
      IL_001c:  
      // Exception count 1
      .try IL_0000 to IL_0007 filter IL_0007 handler IL_0002 to IL_001c
    } // end of method Program::'<Main>$'
    

    Will you do the honors in the Roslyn repo?

  4. vitek-karas commented on May 16, 2023

    @vitek-karas
    Member

    Hmm - somebody already did: dotnet/roslyn#67494

  5. MichalStrehovsky commented on May 30, 2023

    @MichalStrehovsky
    MemberAuthor

    @vitek-karas can we close this?

  6. vitek-karas commented on May 30, 2023

    @vitek-karas
    Member

    Yes.

  7. ghost removed
    untriagedNew issue has not been triaged by the area owner
    on May 30, 2023
  8. ghost locked as resolved and limited conversation to collaborators on Jun 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-Tools-ILLink.NET linker development as well as trimming analyzers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions