Skip to content

Arm64: If Conversion can bypass overflow checks #78554

Closed
@a74nh

Description

@a74nh

This issue was spotted as part of PR #77728

    [MethodImplAttribute(MethodImplOptions.NoInlining)]
    static void lenfail(uint[] a, uint i)
    {
        if (i < a.Length)
	 {
           i = a[i];
	 }
	Consume(i,i+2);
    }

    static void Main(string[] args)
    {
	 var arr = new uint[] { 1, 42, 3000 };
	 lenfail(arr,0xffffffff);
    }

With the following set:

export DOTNET_TieredCompilation=0
export DOTNET_JitStressModeNames=STRESS_IF_CONVERSION_COST
export DOTNET_JITMinOpts=0

Get error:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at CSharpTutorials.Program.lenfail(UInt32[], UInt32)
   at CSharpTutorials.Program.Main(System.String[])
[1]    2099041 abort (core dumped)   ./bin/release/net7.0/linux-arm64/conditional.dll

Why? The load from a[i] should only happen if the if condition holds. With If Conversion, the load is effectively hoisted outside if and is always executed.

This is the Assignment block the If Conversion sees. There are no flags here to indicate moving the ASG before the compare is unsafe. Even more worrying, the IND is marked as GTF_IND_NONFAULTING.

STMT00003 ( 0x008[E-] ... 0x00B )
N012 ( 10, 12) [000018] -A--G---R--                         *  ASG       int    $145
N011 (  1,  1) [000017] D------N---                         +--*  LCL_VAR   int    V01 arg1         d:3 $VN.Void
N010 ( 10, 12) [000031] n---G--N---                         \--*  IND       int    <l:$183, c:$c2>
N009 (  7, 10) [000029] -----------                            \--*  ARR_ADDR  byref int[] $2c0
N008 (  7, 10) [000028] -------N---                               \--*  ADD       byref  $201
N003 (  3,  4) [000027] -----------                                  +--*  ADD       byref  $200
N001 (  1,  1) [000019] -----------                                  |  +--*  LCL_VAR   ref    V00 arg0         u:1 (last use) $80
N002 (  1,  2) [000026] -----------                                  |  \--*  CNS_INT   long   16 $1c0
N007 (  4,  6) [000025] -----------                                  \--*  LSH       long   $241
N005 (  2,  3) [000023] ---------U-                                     +--*  CAST      long <- uint $240
N004 (  1,  1) [000020] -----------                                     |  \--*  LCL_VAR   int    V01 arg1         u:1 (last use) $c0
N006 (  1,  2) [000024] -------N---                                     \--*  CNS_INT   long   2 $1c1

Not quite sure yet on what needs to be fixed earlier on

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