cmd/compile: handle constant-folding of an out-of-range jump table index

The input index to a jump table can be out of range for unreachable code.

Dynamically the compiler ensures that an out-of-range index can never
reach a jump table, but that guarantee doesn't extend to the static
realm.

Fixes #64826

Change-Id: I5829f3933ae5124ffad8337dfd7dd75e67a8ec33
Reviewed-on: https://go-review.googlesource.com/c/go/+/552055
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Keith Randall 2023-12-20 15:38:50 -08:00
parent adec22b9f7
commit f6509cf5cd
2 changed files with 45 additions and 0 deletions

View File

@ -535,6 +535,13 @@ func rewireSuccessor(block *Block, constVal *Value) bool {
case BlockJumpTable:
// Remove everything but the known taken branch.
idx := int(constVal.AuxInt)
if idx < 0 || idx >= len(block.Succs) {
// This can only happen in unreachable code,
// as an invariant of jump tables is that their
// input index is in range.
// See issue 64826.
return false
}
block.swapSuccessorsByIdx(0, idx)
for len(block.Succs) > 1 {
block.removeEdge(1)

View File

@ -0,0 +1,38 @@
// build
// Copyright 2023 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
func main() {
f(g(false))
}
func g(b bool) string {
if b {
return "z"
}
return "q"
}
func f(x string) int {
switch len(x) {
case 4:
return 4
case 5:
return 5
case 6:
return 6
case 7:
return 7
case 8:
return 8
case 9:
return 9
case 10:
return 10
case 11:
return 11
}
return 0
}