aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunyang Shao <shaojunyang@google.com>2026-03-06 00:03:45 +0000
committerGopher Robot <gobot@golang.org>2026-04-07 12:14:08 -0700
commitc4b4bd7b3aefeb67a541912df0733bde68333bfc (patch)
tree2bcac1145af89f757b0eda0ef33b5d032ef4aaa7
parent3a4577a2687ad46d2a00305ddb68733283ea0720 (diff)
downloadgo-c4b4bd7b3aefeb67a541912df0733bde68333bfc.tar.xz
[release-branch.go1.26] cmd/compile: fix loopbce overflow check logic
addWillOverflow and subWillOverflow has an implicit assumption that y is positive, using it outside of addU and subU is really incorrect. This CL fixes those incorrect usage to use the correct logic in place. Thanks to Jakub Ciolek for reporting this issue. Fixes #78333 Fixes CVE-2026-27143 Change-Id: I263e8e7ac227e2a68109eb7bbd45f66569ed22ec Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3700 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Neal Patel <nealpatel@google.com> Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3986 Commit-Queue: Damien Neil <dneil@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/763546 Reviewed-by: David Chase <drchase@google.com> Auto-Submit: Gopher Robot <gobot@golang.org> Reviewed-by: Junyang Shao <shaojunyang@google.com> TryBot-Bypass: Gopher Robot <gobot@golang.org>
-rw-r--r--src/cmd/compile/internal/ssa/loopbce.go36
-rw-r--r--test/loopbce.go28
2 files changed, 53 insertions, 11 deletions
diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go
index aa6cc48cac..a63a314043 100644
--- a/src/cmd/compile/internal/ssa/loopbce.go
+++ b/src/cmd/compile/internal/ssa/loopbce.go
@@ -219,9 +219,11 @@ func findIndVar(f *Func) []indVar {
if init.AuxInt > v {
return false
}
+ // TODO(1.27): investigate passing a smaller-magnitude overflow limit to addU
+ // for addWillOverflow.
v = addU(init.AuxInt, diff(v, init.AuxInt)/uint64(step)*uint64(step))
}
- if addWillOverflow(v, step) {
+ if addWillOverflow(v, step, maxSignedValue(ind.Type)) {
return false
}
if inclusive && v != limit.AuxInt || !inclusive && v+1 != limit.AuxInt {
@@ -250,7 +252,7 @@ func findIndVar(f *Func) []indVar {
// ind < knn - k cannot overflow if step is at most k+1
return step <= k+1 && k != maxSignedValue(limit.Type)
} else { // step < 0
- if limit.Op == OpConst64 {
+ if limit.isGenericIntConst() {
// Figure out the actual smallest value.
v := limit.AuxInt
if !inclusive {
@@ -264,9 +266,11 @@ func findIndVar(f *Func) []indVar {
if init.AuxInt < v {
return false
}
+ // TODO(1.27): investigate passing a smaller-magnitude underflow limit to subU
+ // for subWillUnderflow.
v = subU(init.AuxInt, diff(init.AuxInt, v)/uint64(-step)*uint64(-step))
}
- if subWillUnderflow(v, -step) {
+ if subWillUnderflow(v, -step, minSignedValue(ind.Type)) {
return false
}
if inclusive && v != limit.AuxInt || !inclusive && v-1 != limit.AuxInt {
@@ -328,14 +332,22 @@ func findIndVar(f *Func) []indVar {
return iv
}
-// addWillOverflow reports whether x+y would result in a value more than maxint.
-func addWillOverflow(x, y int64) bool {
- return x+y < x
+// subWillUnderflow checks if x - y underflows the min value.
+// y must be positive.
+func subWillUnderflow(x, y int64, min int64) bool {
+ if y < 0 {
+ base.Fatalf("expecting positive value")
+ }
+ return x < min+y
}
-// subWillUnderflow reports whether x-y would result in a value less than minint.
-func subWillUnderflow(x, y int64) bool {
- return x-y > x
+// addWillOverflow checks if x + y overflows the max value.
+// y must be positive.
+func addWillOverflow(x, y int64, max int64) bool {
+ if y < 0 {
+ base.Fatalf("expecting positive value")
+ }
+ return x > max-y
}
// diff returns x-y as a uint64. Requires x>=y.
@@ -356,7 +368,8 @@ func addU(x int64, y uint64) int64 {
x += 1
y -= 1 << 63
}
- if addWillOverflow(x, int64(y)) {
+ // TODO(1.27): investigate passing a smaller-magnitude overflow limit in here.
+ if addWillOverflow(x, int64(y), maxSignedValue(types.Types[types.TINT64])) {
base.Fatalf("addU overflowed %d + %d", x, y)
}
return x + int64(y)
@@ -372,7 +385,8 @@ func subU(x int64, y uint64) int64 {
x -= 1
y -= 1 << 63
}
- if subWillUnderflow(x, int64(y)) {
+ // TODO(1.27): investigate passing a smaller-magnitude underflow limit in here.
+ if subWillUnderflow(x, int64(y), minSignedValue(types.Types[types.TINT64])) {
base.Fatalf("subU underflowed %d - %d", x, y)
}
return x - int64(y)
diff --git a/test/loopbce.go b/test/loopbce.go
index aabd56c682..9b1b1cc4c8 100644
--- a/test/loopbce.go
+++ b/test/loopbce.go
@@ -469,6 +469,34 @@ func stride2(x *[7]int) int {
return s
}
+// This loop should not be proved anything.
+func smallIntUp(arr *[128]int) {
+ for i := int8(0); i <= int8(120); i += int8(10) {
+ arr[i] = int(i)
+ }
+}
+
+// This loop should not be proved anything.
+func smallIntDown(arr *[128]int) {
+ for i := int8(0); i >= int8(-120); i -= int8(10) {
+ arr[127+i] = int(i)
+ }
+}
+
+// This loop should not be proved anything.
+func smallUintUp(arr *[128]int) {
+ for i := uint8(0); i <= uint8(250); i += uint8(10) {
+ arr[i] = int(i)
+ }
+}
+
+// This loop should not be proved anything.
+func smallUintDown(arr *[128]int) {
+ for i := uint8(255); i >= uint8(0); i -= uint8(10) {
+ arr[127+i] = int(i)
+ }
+}
+
//go:noinline
func useString(a string) {
}