From a5ba803989de5a82b234422c402eee304960512e Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 1 May 2026 15:13:34 +0200 Subject: [PATCH 1/2] Fix INT_MIN overflow in RangeCheck::BetweenBounds When the lower-limit constant 'lcns' equals INT_MIN, the expression '-lcns' triggers signed integer overflow (undefined behavior; on two's-complement targets it yields INT_MIN itself). The check '-lcns > arrSize' then evaluates to false and the function may incorrectly conclude that an out-of-bounds index is in range. Use 'lcns < -arrSize' instead. arrSize is guaranteed to be > 0 at these sites, so '-arrSize' cannot overflow. Fixes #127639 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/jit/rangecheck.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 85953433c066aa..5e758588c52387 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -208,7 +208,11 @@ bool RangeCheck::BetweenBounds(Range& range, GenTree* upper, int arrSize) if (range.LowerLimit().IsBinOpArray()) { int lcns = range.LowerLimit().GetConstant(); - if (lcns >= 0 || -lcns > arrSize) + // Use "lcns < -arrSize" rather than "-lcns > arrSize" to avoid signed + // overflow when lcns == INT_MIN (negating INT_MIN is undefined and on + // two's-complement targets yields INT_MIN itself, which would then + // incorrectly compare as not greater than arrSize). + if (lcns >= 0 || lcns < -arrSize) { return false; } @@ -236,8 +240,10 @@ bool RangeCheck::BetweenBounds(Range& range, GenTree* upper, int arrSize) if (range.LowerLimit().IsBinOpArray()) { int lcns = range.LowerLimit().GetConstant(); - // len + lcns, make sure we don't subtract too much from len. - if (lcns >= 0 || -lcns > arrSize) + // len + lcns, make sure we don't subtract too much from len. Use + // "lcns < -arrSize" rather than "-lcns > arrSize" to avoid signed + // overflow when lcns == INT_MIN. + if (lcns >= 0 || lcns < -arrSize) { return false; } From fdad5312c514b98000c7a207f0f10095975baab6 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 1 May 2026 15:18:30 +0200 Subject: [PATCH 2/2] Update rangecheck.cpp --- src/coreclr/jit/rangecheck.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 5e758588c52387..55a2c5ab7e3545 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -209,9 +209,8 @@ bool RangeCheck::BetweenBounds(Range& range, GenTree* upper, int arrSize) { int lcns = range.LowerLimit().GetConstant(); // Use "lcns < -arrSize" rather than "-lcns > arrSize" to avoid signed - // overflow when lcns == INT_MIN (negating INT_MIN is undefined and on - // two's-complement targets yields INT_MIN itself, which would then - // incorrectly compare as not greater than arrSize). + // overflow when lcns == INT_MIN. + assert(arrSize > 0); if (lcns >= 0 || lcns < -arrSize) { return false; @@ -243,6 +242,7 @@ bool RangeCheck::BetweenBounds(Range& range, GenTree* upper, int arrSize) // len + lcns, make sure we don't subtract too much from len. Use // "lcns < -arrSize" rather than "-lcns > arrSize" to avoid signed // overflow when lcns == INT_MIN. + assert(arrSize > 0); if (lcns >= 0 || lcns < -arrSize) { return false;