Skip to content

JIT: (bug) Struct copy through the GC bulk-copy helper faults on the destination before the source expression is evaluated #133587

Description

@EgorBo

Repro

using System;
using System.Runtime.CompilerServices;

struct Big { public object A, B, C, D, E; }

public class Program
{
    static Big s_src;
    static string s_log = "";

    [MethodImpl(MethodImplOptions.NoInlining)]
    static ref Big GetSrc() { s_log += "GetSrc;"; return ref s_src; }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static int Index() { s_log += "Index;"; return 0; }

    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
    static void Test(ref Big dst) { Unsafe.Add(ref dst, Index()) = GetSrc(); }

    public static int Main()
    {
        try { Test(ref Unsafe.NullRef<Big>()); }
        catch (Exception e) { Console.WriteLine(e.GetType().Name); }
        Console.WriteLine("log=[" + s_log + "]");
        return 100;
    }
}

Expected

NullReferenceException
log=[Index;GetSrc;]

Actual

NullReferenceException
log=[Index;]

Both sides of the assignment must be evaluated before the copy can fault, but the destination null
check runs as soon as the destination address is computed, so the call on the right-hand side is
skipped entirely. Reducing Big to three object fields (which no longer uses the bulk-copy helper)
prints the expected log=[Index;GetSrc;].

Platform

Windows x64, .NET 11 (dotnet/runtime main @ a0b86b1, Checked build), DOTNET_TieredCompilation=0.
No special CPU features. Also reproduces identically on the Release build.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions