Skip to content

JIT: a method whose first instruction is inside a finally or fault handler compiles and overflows the stack when called #135593

Closed

Description

@pcshrosbree

Description

The .NET 10.0.12 JIT accepts the three methods below even though their first instruction lies inside a handler. The finally and fault examples compile in a release build and crash the process with a stack overflow when called. A checked JIT asserts instead:

Assertion failed 'block->bbRefs == blockRefs' in 'Repro:EntryInFinally()' during 'Post-import' (fgdiagnostic.cpp:3066)

The tested catch and filter variants that begin with pop are rejected with stack underflow in the checked JIT's importer. A catch variant whose handler starts with leave instead is compiled and crashes with a stack overflow when called. ECMA-335 I.12.4.2.8.1 allows a filter or handler to be entered only through the exception mechanism and explicitly forbids them at the beginning of a method.

Reproduction Steps

EntryInHandler.il (assemble with ilasm -dll):

.assembly extern System.Runtime {}
.assembly EntryInHandler {}
.class public Repro extends [System.Runtime]System.Object {
    .method public static void EntryInFinally() cil managed
    {
    HandlerStart:
        endfinally
    TryStart:
        leave MethodEnd
    MethodEnd:
        ret
        .try TryStart to MethodEnd finally handler HandlerStart to TryStart
    }

    .method public static void EntryInFault() cil managed
    {
    HandlerStart:
        endfault
    TryStart:
        leave MethodEnd
    MethodEnd:
        ret
        .try TryStart to MethodEnd fault handler HandlerStart to TryStart
    }

    .method public static void EntryInCatchNoPop() cil managed
    {
        .maxstack 1
    HandlerStart:
        leave MethodEnd
    TryStart:
        leave MethodEnd
    MethodEnd:
        ret
        .try TryStart to MethodEnd catch [System.Runtime]System.Exception handler HandlerStart to TryStart
    }
}

Call any of the three methods, or RuntimeHelpers.PrepareMethod them.

Expected behavior

InvalidProgramException at JIT time for all three.

Actual behavior

Release 10.0.12: PrepareMethod succeeds for all three, and calling any of them terminates the process with Stack overflow. (SIGABRT). Checked 10.0.12: the assert above for all three.

Regression?

Not that I know of.

Known Workarounds

Found while testing the EH-layout validation in #134749. ILVerify at 72a6735 rejects all three methods above with FallthroughIntoHandler; it reports FallthroughIntoFilter for the separately tested method-entry-in-filter case.

Configuration

.NET 10.0.12, linux-x64 (Ubuntu, glibc 2.43); checked JIT built from the v10.0.12 tag; main at 01a32f3 has no such check in fgFindBasicBlocks either.

Other information

A possible fix to investigate is a check in fgFindBasicBlocks, after handler indices are assigned, that reports BADCODE if the original IL entry block has a handler index. I can send a PR with that and a regression test if that is welcome.

Note

This issue was prepared with AI assistance (Anthropic Claude and OpenAI Codex), under my direction. I reviewed it before posting.

Activity

  1. dotnet-policy-service commented on Oct 11, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @agocke
    See info in area-owners.md if you want to be subscribed.

  2. added a commit that references this issue on Oct 15, 2026
    281925e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status
      No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions