Skip to content

NullReferenceException when executing VB compiled code with goto+closure pattern on macOS #125702

@jaredpar

Description

@jaredpar

Description

VB-compiled code that combines goto statements with lambda closures throws a NullReferenceException at runtime on macOS, despite the generated IL being valid and executing correctly on Windows and Linux. The issue appears to be in the .NET runtime (JIT or interpreter) on macOS.

Reproduction Steps

The following VB.NET program compiles without errors and runs correctly on Windows (output: 1, 3, 1), but throws a NullReferenceException on macOS (OSX 15, x64):

Imports System

Module M1
    Class C1
        Public Sub Goo(x As Integer)
            If x < 0
                Dim d2 As Action = Sub()
                    Console.Write(x)
                End Sub
                GoTo label0
            End If

label0:
            If x > 0
                Dim dummy1 As Integer = 1
                Console.WriteLine(dummy1)
                GoTo label2
            End If

            While x > 0
                Dim dummy2 As Integer = 1
                Console.WriteLine(dummy2)
                GoTo label1
            End While

            While x > 0
label1:
                Dim y As Integer = 1

                If x > 0
                    Dim d1 As Action = Sub()
                        Console.Write(1)
                    End Sub
                    d1.Invoke()
                End If

                While x > 0
                    Dim dummy3 As Integer = 1
                    Console.WriteLine(dummy3)
                    Exit Sub
label2:
                    Console.WriteLine(x)
                End While
            End While
        End Sub
    End Class

    Public Sub Main()
        Dim x As C1 = New C1
        x.Goo(3)
    End Sub
End Module

Expected behavior

Program prints:

1
3
1

Actual behavior

System.NullReferenceException : Object reference not set to an instance of an object.
   at M1.Main() in a.vb:line 59
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Regression?

Analysis

The generated IL is valid

I decompiled the VB compiler output and verified:

  1. Closure is created at method entry — The _Closure$__1-0 instance (containing the captured parameter x) is allocated at IL_0000IL_0007, before any control flow branches.
  2. Parameter x is stored into the closure immediatelystfld $VB$Local_x at IL_000A, right after closure creation.
  3. Stack is balanced — The closure constructor takes 1 parameter (a copy-source closure for Edit-and-Continue, passed as null). The ldloc.0; newobj; stloc.0 pattern correctly pops the null argument and pushes the new instance.
  4. The goto label2 branch (br.s IL_00BA) is a forward jump into the inner While loop body. This is valid because the closure is already fully initialized at method entry.

Why this is a runtime issue, not a compiler issue

  • Same IL, different behavior: The exact same compiled assembly runs correctly on Windows and Linux but throws NRE on macOS.
  • Stack trace is suspicious: The trace shows M1.Main() with no C1.Goo() frame, suggesting the runtime isn't correctly unwinding through the call chain.
  • InterpretedInvoke_Method in the trace: On macOS, the runtime appears to be using the interpreter rather than JIT, which may handle the complex control flow differently.
  • The control flow pattern is unusual: A forward br.s jumping into the body of nested While loops (bypassing loop condition checks) is a rare IL pattern that may not be well-exercised in the interpreter.

Roslyn issue history

Environment

  • Failing on: macOS 15, x64 (Amd64), Debug configuration
  • Passing on: Windows (all configurations), Linux
  • Test leg: Test_macOS_Debug_OSX.15.Amd64.Open (Helix)
  • Roslyn pipeline: roslyn-CI

Related links

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIneeds-author-actionAn issue or pull request that requires more info or actions from the author.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions