summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/gc/ssa.go33
-rw-r--r--test/loopbce.go6
-rw-r--r--test/prove.go4
3 files changed, 13 insertions, 30 deletions
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 84b9207481..d6b2bd3137 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -4029,6 +4029,7 @@ func (s *state) nilCheck(ptr *ssa.Value) {
}
// boundsCheck generates bounds checking code. Checks if 0 <= idx < len, branches to exit if not.
+// len must be known to be nonnegative.
// Starts a new block on return.
// idx is already converted to full int width.
func (s *state) boundsCheck(idx, len *ssa.Value) {
@@ -4041,34 +4042,14 @@ func (s *state) boundsCheck(idx, len *ssa.Value) {
s.check(cmp, panicindex)
}
-func couldBeNegative(v *ssa.Value) bool {
- switch v.Op {
- case ssa.OpSliceLen, ssa.OpSliceCap, ssa.OpStringLen:
- return false
- case ssa.OpConst64:
- return v.AuxInt < 0
- case ssa.OpConst32:
- return int32(v.AuxInt) < 0
- }
- return true
-}
-
// sliceBoundsCheck generates slice bounds checking code. Checks if 0 <= idx <= len, branches to exit if not.
+// len must be known to be nonnegative.
// Starts a new block on return.
// idx and len are already converted to full int width.
func (s *state) sliceBoundsCheck(idx, len *ssa.Value) {
if Debug['B'] != 0 {
return
}
- if couldBeNegative(len) {
- // OpIsSliceInBounds requires second arg not negative; if it's not obviously true, must check.
- cmpop := ssa.OpGeq64
- if len.Type.Size() == 4 {
- cmpop = ssa.OpGeq32
- }
- cmp := s.newValue2(cmpop, types.Types[TBOOL], len, s.zeroVal(len.Type))
- s.check(cmp, panicslice)
- }
// bounds check
cmp := s.newValue2(ssa.OpIsSliceInBounds, types.Types[TBOOL], idx, len)
@@ -4332,13 +4313,15 @@ func (s *state) slice(t *types.Type, v, i, j, k *ssa.Value, bounded bool) (p, l,
if !bounded {
// Panic if slice indices are not in bounds.
- s.sliceBoundsCheck(i, j)
- if j != k {
- s.sliceBoundsCheck(j, k)
- }
+ // Make sure we check these in reverse order so that we're always
+ // comparing against a value known to be nonnegative. See issue 28797.
if k != cap {
s.sliceBoundsCheck(k, cap)
}
+ if j != k {
+ s.sliceBoundsCheck(j, k)
+ }
+ s.sliceBoundsCheck(i, j)
}
// Generate the following code assuming that indexes are in bounds.
diff --git a/test/loopbce.go b/test/loopbce.go
index 81f2524e95..e0a6463c5e 100644
--- a/test/loopbce.go
+++ b/test/loopbce.go
@@ -63,7 +63,7 @@ func f5(a [10]int) int {
func f6(a []int) {
for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- b := a[0:i] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$" "(\([0-9]+\) )?Proved Geq64$"
+ b := a[0:i] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
f6(b)
}
}
@@ -186,10 +186,10 @@ func k0(a [100]int) [100]int {
func k1(a [100]int) [100]int {
for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
- useSlice(a[:i-11]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i-11])
useSlice(a[:i-10]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i-5]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
- useSlice(a[:i]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$" "(\([0-9]+\) )?Proved Geq64$"
+ useSlice(a[:i]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+5]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+10]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+11]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
diff --git a/test/prove.go b/test/prove.go
index eb0fb2a15e..2db0a841e2 100644
--- a/test/prove.go
+++ b/test/prove.go
@@ -269,7 +269,7 @@ func f11b(a []int, i int) {
func f11c(a []int, i int) {
useSlice(a[:i])
- useSlice(a[:i]) // ERROR "Proved Geq64$" "Proved IsSliceInBounds$"
+ useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
}
func f11d(a []int, i int) {
@@ -469,7 +469,7 @@ func f17(b []int) {
// using the derived relation between len and cap.
// This depends on finding the contradiction, since we
// don't query this condition directly.
- useSlice(b[:i]) // ERROR "Proved Geq64$" "Proved IsSliceInBounds$"
+ useSlice(b[:i]) // ERROR "Proved IsSliceInBounds$"
}
}