From cf9eb1bc3e230f9cd2f8318f5870722940064184 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 21:20:53 +0000 Subject: [PATCH 1/3] Initial plan From 9f8979eac10cf3dc0a0313f41e21e98e03d6e4bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 21:48:35 +0000 Subject: [PATCH 2/3] Preserve checked unsigned overflow Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com> --- src/coreclr/jit/rangecheck.h | 4 ++- .../JitBlue/Runtime_130431/Runtime_130431.cs | 28 +++++++++++++++++++ .../JIT/Regression/Regression_ro_2.csproj | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs diff --git a/src/coreclr/jit/rangecheck.h b/src/coreclr/jit/rangecheck.h index a722fa4bf06c09..2c09ae8d771035 100644 --- a/src/coreclr/jit/rangecheck.h +++ b/src/coreclr/jit/rangecheck.h @@ -340,7 +340,9 @@ struct RangeOps } static_assert(CheckedOps::Unsigned == true); - if (!CheckedOps::AddOverflows(a.GetConstant(), b.GetConstant(), unsignedAdd)) + if (!CheckedOps::AddOverflows(a.GetConstant(), b.GetConstant(), unsignedAdd) && + (!unsignedAdd || + !CheckedOps::AddOverflows(a.GetConstant(), b.GetConstant(), CheckedOps::Signed))) { if (a.IsConstant() && b.IsConstant()) { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs new file mode 100644 index 00000000000000..b7c4e89c32cc84 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_130431 +{ + [Fact] + public static void TestEntryPoint() + { + Assert.Throws(() => Add(1, uint.MaxValue)); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static uint Add(uint x, uint y) + { + uint result = checked(y + unchecked((byte)x)); + + if (x == 0) + { + return result + 1; + } + + return result; + } +} diff --git a/src/tests/JIT/Regression/Regression_ro_2.csproj b/src/tests/JIT/Regression/Regression_ro_2.csproj index f768233f63c9b8..4a0ed731181667 100644 --- a/src/tests/JIT/Regression/Regression_ro_2.csproj +++ b/src/tests/JIT/Regression/Regression_ro_2.csproj @@ -113,6 +113,7 @@ + From 9505ea55324b078405a67a51fa67ae7b20034c03 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 21:57:12 +0000 Subject: [PATCH 3/3] Handle sign-straddling unsigned ranges Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com> --- src/coreclr/jit/rangecheck.h | 10 ++++++++++ .../JitBlue/Runtime_130431/Runtime_130431.cs | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/coreclr/jit/rangecheck.h b/src/coreclr/jit/rangecheck.h index 2c09ae8d771035..70943ae69439a2 100644 --- a/src/coreclr/jit/rangecheck.h +++ b/src/coreclr/jit/rangecheck.h @@ -326,6 +326,16 @@ struct RangeOps static Range Add(const Range& r1, const Range& r2, bool unsignedAdd = false) { + if (unsignedAdd && + ((r1.IsConstantRange() && (r1.LowerLimit().GetConstant() < 0) && + (r1.UpperLimit().GetConstant() >= 0)) || + (r2.IsConstantRange() && (r2.LowerLimit().GetConstant() < 0) && + (r2.UpperLimit().GetConstant() >= 0)))) + { + // Signed intervals that straddle zero are not monotonic when interpreted as unsigned. + return Limit(Limit::keUnknown); + } + return ApplyRangeOp(r1, r2, [unsignedAdd](const Limit& a, const Limit& b) { // For Add we support: // keConstant + keConstant => keConstant diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs b/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs index b7c4e89c32cc84..10e0d368629bc6 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_130431/Runtime_130431.cs @@ -11,6 +11,7 @@ public class Runtime_130431 public static void TestEntryPoint() { Assert.Throws(() => Add(1, uint.MaxValue)); + Assert.Throws(() => AddWithSignStraddlingRange(uint.MaxValue, 1)); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] @@ -25,4 +26,15 @@ private static uint Add(uint x, uint y) return result; } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static uint AddWithSignStraddlingRange(uint x, uint y) + { + if (((int)x > 0) || (y > 1)) + { + return 0; + } + + return checked(x + y); + } }