Skip to content

JITted code throws NullRefException in release #56980

Closed

Description

@jakobbotsch

Run on x64 Windows:

// Generated by Fuzzlyn v1.2 on 2021-07-06 09:46:44
// Seed: 16635934940619066544
// Reduced from 447.5 KiB to 0.6 KiB in 00:02:24
// Debug: Runs successfully
// Release: Throws 'System.NullReferenceException'
struct S0
{
    public uint F1;
    public byte F3;
    public long F4;
    public uint F5;
    public S0(long f4): this()
    {
        F4 = f4;
    }
}

class C0
{
    public S0 F4;
}

struct S1
{
    public C0 F2;
    public S0 F8;
    public S1(C0 f2, S0 f8): this()
    {
        F2 = f2;
        F8 = f8;
    }
}

struct S2
{
    public S1 F0;
    public S2(S1 f0): this()
    {
        F0 = f0;
    }
}

public class Program
{
    public static void Main()
    {
        S2 vr0 = new S2(new S1(new C0(), new S0(0)));
        M17(ref vr0.F0.F2.F4.F1);
    }

    static void M17(ref uint arg2)
    {
    }
}

Disassembly looks quite strange:

; Assembly listing for method Program:Main()
; Emitting BLENDED_CODE for X64 CPU with AVX - Windows
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 5 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
;  V00 OutArgs      [V00    ] (  1,  1   )  lclBlk (32) [rsp+00H]   "OutgoingArgSpace"
;  V01 tmp1         [V01,T02] (  2,  4   )     ref  ->  rcx         class-hnd exact single-def "NewObj constructor temp"
;* V02 tmp2         [V02    ] (  0,  0   )  struct (24) zero-ref    "NewObj constructor temp"
;* V03 tmp3         [V03,T01] (  0,  0   )  struct (32) zero-ref    do-not-enreg[SFB] single-def "NewObj constructor temp"
;* V04 tmp4         [V04,T03] (  0,  0   )  struct (32) zero-ref    do-not-enreg[SFB] "NewObj constructor temp"
;* V05 tmp5         [V05,T00] (  0,  0   )  struct (24) zero-ref    do-not-enreg[SFB] "Inlining Arg"
;* V06 tmp6         [V06    ] (  0,  0   )  struct (32) zero-ref    do-not-enreg[S] single-def "Inlining Arg"
;* V07 tmp7         [V07,T08] (  0,  0   )     int  ->  zero-ref    V02.F1(offs=0x00) P-INDEP "field V02.F1 (fldOffset=0x0)"
;* V08 tmp8         [V08,T05] (  0,  0   )   ubyte  ->  zero-ref    V02.F3(offs=0x04) P-INDEP "field V02.F3 (fldOffset=0x4)"
;* V09 tmp9         [V09,T06] (  0,  0   )    long  ->  zero-ref    V02.F4(offs=0x08) P-INDEP "field V02.F4 (fldOffset=0x8)"
;* V10 tmp10        [V10,T04] (  0,  0   )     int  ->  zero-ref    V02.F5(offs=0x10) P-INDEP "field V02.F5 (fldOffset=0x10)"
;* V11 tmp11        [V11,T07] (  0,  0   )     ref  ->  zero-ref    single-def "Big Offset Morphing"
;
; Lcl frame size = 40

G_M27646_IG01:              ;; offset=0000H
       4883EC28             sub      rsp, 40
                                                ;; bbWeight=1    PerfScore 0.25
G_M27646_IG02:              ;; offset=0004H
       48B9D0C3EE8CFB7F0000 mov      rcx, 0x7FFB8CEEC3D0
       E89D95E35E           call     CORINFO_HELP_NEWSFAST
       488BC8               mov      rcx, rax
       E8BD15FEFF           call     System.Object:.ctor():this
       8B042500000000       mov      eax, dword ptr [0000H]
                                                ;; bbWeight=1    PerfScore 4.50
G_M27646_IG03:              ;; offset=0022H
       4883C428             add      rsp, 40
       C3                   ret
                                                ;; bbWeight=1    PerfScore 1.25

; Total bytes of code 39, prolog size 4, PerfScore 9.90, instruction count 8, allocated bytes for code 39 (MethodHash=cb019401) for method Program:Main()
; ============================================================

cc @dotnet/jit-contrib

Activity

  1. ghost added
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    on Aug 6, 2021
  2. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Aug 6, 2021
  3. added
    needs-further-triageIssue has been initially triaged, but needs deeper consideration or reconsideration
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 6, 2021
  4. added this to the 6.0.0 milestone on Aug 6, 2021
  5. AndyAyersMS commented on Aug 6, 2021

    @AndyAyersMS
    Member

    Took a quick look; proximate cause is that VN thinks the base of an indir is null, and that feeds a nullcheck, so the codegen above is the nullcheck of a null.

      VNApplySelectors:
        VNForHandle(F0) is $147, fieldType is struct, size = 32
          AX2: $147 != $146 ==> select([$4c1]store($440, $146, $205), $147) ==> select($440, $147) remaining budget is 99.
          AX2: $147 != $145 ==> select([$440]store($1, $145, $180), $147) ==> select($1, $147) remaining budget is 98.
        VNForMapSelect($4c1, $147):struct returns $VN.ZeroMap
      VNApplySelectors:
        VNForHandle(F2) is $145, fieldType is ref
        VNForMapSelect($1, $145):ref returns $VN.Null
      VNApplySelectors:
        VNForHandle(F0) is $147, fieldType is struct, size = 32
          AX2: $147 != $146 ==> select([$4c0]store($440, $146, $204), $147) ==> select($440, $147) remaining budget is 99.
          AX2: $147 != $145 ==> select([$440]store($1, $145, $180), $147) ==> select($1, $147) remaining budget is 98.
        VNForMapSelect($4c0, $147):struct returns $VN.ZeroMap
      VNApplySelectors:
        VNForHandle(F2) is $145, fieldType is ref
        VNForMapSelect($1, $145):ref returns $VN.Null
    N001 [000031]   LCL_FLD   V04 tmp4         u:1[+0] Fseq[F0, F2] (last use) => $VN.Null
    
    ***** BB01, STMT00018(after)
    N008 ( 11, 10) [000086] -A-XG-------              *  COMMA     void   $500
    N006 ( 11, 10) [000148] -A-X--------              +--*  COMMA     void   $183
    N003 (  7,  7) [000137] -A------R---              |  +--*  ASG       ref    $VN.Null
    N002 (  3,  2) [000136] D------N----              |  |  +--*  LCL_VAR   ref    V11 tmp11        d:1 $VN.Null
    N001 (  3,  4) [000031] ------------              |  |  \--*  LCL_FLD   ref    V04 tmp4         u:1[+0] Fseq[F0, F2] (last use) $VN.Null
    N005 (  4,  3) [000139] ---X---N----              |  \--*  NULLCHECK byte   $183
    N004 (  3,  2) [000138] ------------              |     \--*  LCL_VAR   ref    V11 tmp11        u:1 (last use) $VN.Null
    N007 (  0,  0) [000085] ------------              \--*  NOP       void   $1c5
    

    Now WHY VN thinks that is not immediately clear.... likely we are missing something when modelling the memory updates done earlier in the method, and so think that bit of the struct was not explicitly initialized.

  6. self-assigned this
    on Aug 9, 2021
  7. removed
    needs-further-triageIssue has been initially triaged, but needs deeper consideration or reconsideration
    on Aug 9, 2021
  8. AndyAyersMS commented on Aug 9, 2021

    @AndyAyersMS
    Member

    Think the issue may originate here:

    LocalAddressVisitor visiting statement:
    STMT00016 (IL 0x011...  ???)
                   [000080] -A----------              *  ASG       struct (copy)
                   [000079] ------------              +--*  OBJ       struct<S1, 32>
                   [000078] ------------              |  \--*  ADDR      byref 
                   [000077] -------N----              |     \--*  FIELD     struct F0
                   [000074] ------------              |        \--*  ADDR      byref 
                   [000075] -------N----              |           \--*  LCL_VAR   struct<S2, 32> V04 tmp4         
                   [000076] ------------              \--*  LCL_VAR   struct<S1, 32> V06 tmp6         
    LocalAddressVisitor modified statement:
    STMT00016 (IL 0x011...  ???)
                   [000080] -A----------              *  ASG       struct (copy)
                   [000079] D------N----              +--*  LCL_VAR   struct<S2, 32> V04 tmp4         
                   [000076] ------------              \--*  LCL_VAR   struct<S1, 32> V06 tmp6         
    

    We seem to lose the fact that we're storing to the S1 field of an S2, not to the S2 itself. Logically it's the same set of bits, but I think we need to preserve the bit of field seq here we've lost...?

  9. AndyAyersMS commented on Aug 9, 2021

    @AndyAyersMS
    Member

    @sandreenko if this is similar to issues you're already working on, do you want to take this over?

  10. self-assigned this
    on Aug 9, 2021
  11. sandreenko commented on Aug 9, 2021

    @sandreenko
    Contributor

    @sandreenko if this is similar to issues you're already working on, do you want to take this over?

    sure.

  12. ghost locked as resolved and limited conversation to collaborators on Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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