Repository navigation
Description
Note
This issue was authored by GitHub Copilot CLI on @AndyAyersMS's machine,
based on a bug surfaced by an experimental in-development fuzzer.
The C# repro is verified.
Repro
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
public static class Program
{
private static uint Sink;
[MethodImpl(MethodImplOptions.NoInlining)]
public static uint Fn()
{
uint v2 = BitOperations.RotateRight(0xFFFFFFFFu, 1);
Sink = v2;
return v2;
}
public static int Main()
{
Console.WriteLine($"{Fn():X8}");
return 0;
}
}Observed
| Configuration | Result |
|---|---|
Local dotnet/runtime HEAD Checked, DOTNET_TieredCompilation=0 (FullOpts) |
JIT assertion 'FitsIn<int32_t>(value)' in src/coreclr/jit/compiler.hpp:2100 during 'Morph - Global' |
Local HEAD DOTNET_JITMinOpts=1 |
FFFFFFFF ✅ |
Shipping dotnet 11.0.0-preview.3.26207.106 (any config, Release) |
FFFFFFFF ✅ |
Same regression window as #129076 (between preview-3 and HEAD); haven't bisected this one yet.
Asserts on osx-arm64 Checked at HEAD a8b2c92ce21. Whether Release builds produce wrong code is unverified — I don't have a Release runtime build handy. The assertion is at GenTreeIntCon::SetIconValue-style code path, which is normally a "load-bearing" invariant rather than a debug-only sanity check.
Required ingredients
All necessary, all sufficient when combined:
BitOperations.RotateRight(0xFFFFFFFFu, k)for anyk >= 1(rotation count > 0)- Result stored into a local
- Two uses of that local — one into a side-effecting target (here a static field), one as the return value
Removing any of these stops the crash. So:
- Direct
return BitOperations.RotateRight(0xFFFFFFFFu, 1);(single use, no local) — no crash, returnsFFFFFFFF - Different constant input, e.g.
BitOperations.RotateRight(0xFFFFFFFEu, 1)— no crash, returns7FFFFFFF - ulong overload,
BitOperations.RotateRight(0xFFFFFFFFFFFFFFFFul, 1)— no crash, returnsFFFFFFFFFFFFFFFF
Hypothesis
The JIT recognizes BitOperations.RotateRight(uint, int) as an intrinsic and constant-folds it when both inputs are constants. The folded value is 0xFFFFFFFF. With two uses, CSE produces a shared constant node typed uint with value 0xFFFFFFFF. Something during Morph - Global then tries to write that constant value through a GenTreeIntCon::SetIconValue-style path with type == TYP_INT, which asserts FitsIn<int32_t>(value) and trips because 0xFFFFFFFF = 4294967295 > int.MaxValue = 2147483647.
The ulong-not-affected datapoint is consistent: that code path is gated on genTypeSize(type) <= genTypeSize(TYP_INT).
How it was found
ReifyCs (semantic-reification fuzzer, same one that found #129076) with a new --profile intrinsic populator that emits BitOperations.RotateLeft/Right and Math.Abs/Max/Min calls. Surfaced on the first 50-trial smoke campaign of that profile. Hand-reduced from a ~60-line generated function to the 6-line repro above.
Activity
dotnet-policy-service commentedon Jun 7, 2026
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.
AndyAyersMS commentedon Jul 30, 2026
Need to check if this leads to a bug in release mode.
AndyAyersMS commentedon Jul 30, 2026
It doesn't seem to, so moving this out of .NET 11.
Fix JIT assertion for TYP_UINT constants exceeding int32_t range (dot…
JIT: sign-extend folded 32-bit RotateLeft/RotateRight constants (dotn…