cmd/compile: fix corner case boundedness for oversized shifts

For unsigned x >> k where k exceeds the width of x, the result is zero,
which means that using it as an index doesn't require a bounds
check...but not if the length is zero.

Walk mishandled this. Fix it.

It's a corner case, but the fix is trivial.

Change-Id: Ieb7f2d33563f09e98bb31eefb2d2c01f03064311
Reviewed-on: https://go-review.googlesource.com/c/go/+/778200
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Josh Bleecher Snyder 2026-05-15 07:31:04 -07:00 committed by Gopher Robot
parent 8f7f951965
commit 0c3b9f837d
2 changed files with 29 additions and 2 deletions

View file

@ -1015,7 +1015,7 @@ func walkStringHeader(n *ir.StringHeaderExpr, init *ir.Nodes) ir.Node {
return n
}
// return 1 if integer n must be in range [0, max), 0 otherwise.
// bounded reports whether integer n must be in range [0, max).
func bounded(n ir.Node, max int64) bool {
if n.Type() == nil || !n.Type().IsInteger() {
return false
@ -1073,7 +1073,7 @@ func bounded(n ir.Node, max int64) bool {
if !sign && ir.IsSmallIntConst(n.Y) {
v := ir.Int64Val(n.Y)
if v > int64(bits) {
return true
return max > 0
}
bits -= int32(v)
}

View file

@ -0,0 +1,27 @@
// run
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "strings"
//go:noinline
func f(i uint8) byte {
return ""[i>>9]
}
func main() {
defer func() {
r := recover()
if r == nil {
panic("missing bounds panic")
}
if got := r.(error).Error(); !strings.Contains(got, "index out of range") {
panic(got)
}
}()
_ = f(7)
}