Skip to content

RyuJIT: By-ref assignment with null leads to runtime crash #10890

@jakobbotsch

Description

@jakobbotsch

The following example crashes the runtime when compiled and run in either debug or release:

class C0
{
}

struct S0
{
    public C0 F0;
    public ulong F4;
}

class C1
{
    public S0 F3;
}

struct S1
{
    public S0 F3;
}

public class Program
{
    static S1 s_38;
    static C1 s_43;

    public static void Main()
    {
        s_38.F3 = s_43.F3;
    }
}

In debug (and probably checked) builds, this assertion triggers:

Assert failure(PID 20848 [0x00005170], Thread: 17420 [0x440c]): Consistency check failed: AV in clr at this callstack:
------
CORECLR! JIT_ByRefWriteBarrier + 0x0 (0x00007ffc`5e207d70)
<no module>! <no symbol> + 0x0 (0x00007ffb`fef22611)
<no module>! <no symbol> + 0x0 (0x00007ffb`fee045e0)
<no module>! <no symbol> + 0x0 (0x000000fa`00000005)
<no module>! <no symbol> + 0x0 (0x000000fa`2077d580)
-----
.AV on tid=0x440c (17420), cxr=000000FA2077CE00, exr=000000FA2077D2F0
FAILED: false

CORECLR! CHECK::Trigger + 0x275 (0x00007ffc`5db0cea5)
CORECLR! CLRVectoredExceptionHandlerPhase3 + 0x332 (0x00007ffc`5dc1bd62)
CORECLR! CLRVectoredExceptionHandlerPhase2 + 0x8C (0x00007ffc`5dc1b70c)
CORECLR! CLRVectoredExceptionHandler + 0x275 (0x00007ffc`5dc1b665)
CORECLR! CLRVectoredExceptionHandlerShim + 0x18D (0x00007ffc`5dc1c04d)
NTDLL! RtlInitializeCriticalSection + 0x1D8 (0x00007ffc`c5bd5678)
NTDLL! RtlWalkFrameChain + 0x109A (0x00007ffc`c5b7692a)
NTDLL! KiUserExceptionDispatcher + 0x2E (0x00007ffc`c5c0dc1e)
CORECLR! JIT_ByRefWriteBarrier + 0x0 (0x00007ffc`5e207d70)
<no module>! <no symbol> + 0x0 (0x00007ffb`fef22611)
    File: z:\programming\dotnet\coreclr\src\vm\excep.cpp Line: 7831
    Image: Z:\Programming\dotnet\coreclr\bin\Product\Windows_NT.x64.Debug\CoreRun.exe

The code generated is:

; Assembly listing for method Program:Main()
; Emitting BLENDED_CODE for X64 CPU with AVX
; optimized code
; rsp based frame
; partially interruptible
; Final local variable assignments
;
;  V00 OutArgs      [V00    ] (  1,  1   )  lclBlk (32) [rsp+0x00]
;  V01 cse0         [V01,T00] (  5,  5   )    long  ->  [rsp+0x20]
;
; Lcl frame size = 40

G_M5092_IG01:
       57                   push     rdi
       56                   push     rsi
       4883EC28             sub      rsp, 40

G_M5092_IG02:
       48B9E045E3FEFB7F0000 mov      rcx, 0x7FFBFEE345E0
       BA05000000           mov      edx, 5
       E8461E455F           call     CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
       48B87829001091010000 mov      rax, 0x19110002978
       488B00               mov      rax, gword ptr [rax]
       488D7008             lea      rsi, bword ptr [rax+8]
       48B87029001091010000 mov      rax, 0x19110002970
       488B00               mov      rax, gword ptr [rax]
       488D7808             lea      rdi, bword ptr [rax+8]
       E85F572B5F           call     CORINFO_HELP_ASSIGN_BYREF
       48A5                 movsq

G_M5092_IG03:
       4883C428             add      rsp, 40
       5E                   pop      rsi
       5F                   pop      rdi
       C3                   ret

; Total bytes of code 74, prolog size 6 for method Program:Main()
;

Question: How will this normally be handled by CoreCLR? Should the runtime turn the AV in CORINFO_HELP_ASSIGN_BYREF into a managed NRE, or is the caller supposed to null-check/deref the reference before calling CORINFO_HELP_ASSIGN_BYREF?

Metadata

Metadata

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