dotnet / dotnet/runtime

JIT: (bug) Loop cloning drops bounds checks when an arr.Length + K loop limit overflows to a negative value

Open
#133,823 1 comment 0 reactions 1 assignee Claimed by @AndyAyersMS View on GitHub
area-CodeGen-coreclr
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

`optDeriveLoopCloningConditions` only emits the `arr.Length + offset >= 0` guard when the peeled limit offset is negative, but the 32-bit add also wraps negative for large positive offsets, so the check-free fast clone runs out of bounds.

### Minimal Repro

```csharp
using System;
using System.Runtime.CompilerServices;

public class Program
{
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
public static int Test(int[] a, int[] b)
{
int sum = 0;
for (int i = a.Length - 1; i > b.Length + int.MaxValue; i--)
{
sum += a[i];
}
return sum;
}

public static void Main()
{
int[] a = new int[4];
int[] b = new int[4];
try
{
Console.WriteLine("result " + Test(a, b));
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("IndexOutOfRangeException");
}
}
}
```

`b.Length + int.MaxValue` wraps to `-2147483645`, so the decreasing loop must walk `i` below `0` and throw.

### Expected

```
IndexOutOfRangeException
```

`DOTNET_JitCloneLoops=0` produces this correct result.

### Actual

```
Fatal error.
```

Exit code `0xC0000005`. Silent out-of-bounds read from safe C#.

### Notes

- `MatchLimit` / `NaturalLoopIterInfo::LimitOffset` (`src/coreclr/jit/flowgraph.cpp`) peel the constant out of `b.Length + K`; `loopcloning.cpp` guards `arr.Length + offset >= 0` only under `if (iterInfo->LimitOffset < 0)`.
- The derived conditions are only about the initial IV (`(V03 GE 0) && (V03 LT V00.Length)`), both true here, so the check-free clone is entered and `i` walks down through negative values.
- Fix direction: emit the `arr.Length + offset >= 0` condition for positive offsets too, or reject offsets where the add can overflow.
- .NET 11 regression (10.0.12 is correct, 11.0.0-rc.1 Release is bad); introduced by "JIT: extend loop cloning for span+stride>1 and ±const limits" (#129309).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.