mirror of
https://github.com/golang/go
synced 2024-11-02 09:28:34 +00:00
cmd/compile: ignore out-of-bounds reads from readonly constants
Out-of-bounds reads of globals can happen in dead code. For code like this: s := "a" if len(s) == 3 { load s[0], s[1], and s[2] } The out-of-bounds loads are dead code, but aren't removed yet when lowering. We need to not panic when compile-time evaluating those loads. This can only happen for dead code, so the result doesn't matter. Fixes #29215 Change-Id: I7fb765766328b9524c6f2a1e6ab8d8edd9875097 Reviewed-on: https://go-review.googlesource.com/c/154057 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alberto Donizetti <alb.donizetti@gmail.com>
This commit is contained in:
parent
4422319fbf
commit
443990742e
2 changed files with 34 additions and 0 deletions
|
@ -1137,12 +1137,22 @@ func symIsRO(sym interface{}) bool {
|
||||||
// read8 reads one byte from the read-only global sym at offset off.
|
// read8 reads one byte from the read-only global sym at offset off.
|
||||||
func read8(sym interface{}, off int64) uint8 {
|
func read8(sym interface{}, off int64) uint8 {
|
||||||
lsym := sym.(*obj.LSym)
|
lsym := sym.(*obj.LSym)
|
||||||
|
if off >= int64(len(lsym.P)) {
|
||||||
|
// Invalid index into the global sym.
|
||||||
|
// This can happen in dead code, so we don't want to panic.
|
||||||
|
// Just return any value, it will eventually get ignored.
|
||||||
|
// See issue 29215.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return lsym.P[off]
|
return lsym.P[off]
|
||||||
}
|
}
|
||||||
|
|
||||||
// read16 reads two bytes from the read-only global sym at offset off.
|
// read16 reads two bytes from the read-only global sym at offset off.
|
||||||
func read16(sym interface{}, off int64, bigEndian bool) uint16 {
|
func read16(sym interface{}, off int64, bigEndian bool) uint16 {
|
||||||
lsym := sym.(*obj.LSym)
|
lsym := sym.(*obj.LSym)
|
||||||
|
if off >= int64(len(lsym.P))-1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
if bigEndian {
|
if bigEndian {
|
||||||
return binary.BigEndian.Uint16(lsym.P[off:])
|
return binary.BigEndian.Uint16(lsym.P[off:])
|
||||||
} else {
|
} else {
|
||||||
|
@ -1153,6 +1163,9 @@ func read16(sym interface{}, off int64, bigEndian bool) uint16 {
|
||||||
// read32 reads four bytes from the read-only global sym at offset off.
|
// read32 reads four bytes from the read-only global sym at offset off.
|
||||||
func read32(sym interface{}, off int64, bigEndian bool) uint32 {
|
func read32(sym interface{}, off int64, bigEndian bool) uint32 {
|
||||||
lsym := sym.(*obj.LSym)
|
lsym := sym.(*obj.LSym)
|
||||||
|
if off >= int64(len(lsym.P))-3 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
if bigEndian {
|
if bigEndian {
|
||||||
return binary.BigEndian.Uint32(lsym.P[off:])
|
return binary.BigEndian.Uint32(lsym.P[off:])
|
||||||
} else {
|
} else {
|
||||||
|
@ -1163,6 +1176,9 @@ func read32(sym interface{}, off int64, bigEndian bool) uint32 {
|
||||||
// read64 reads eight bytes from the read-only global sym at offset off.
|
// read64 reads eight bytes from the read-only global sym at offset off.
|
||||||
func read64(sym interface{}, off int64, bigEndian bool) uint64 {
|
func read64(sym interface{}, off int64, bigEndian bool) uint64 {
|
||||||
lsym := sym.(*obj.LSym)
|
lsym := sym.(*obj.LSym)
|
||||||
|
if off >= int64(len(lsym.P))-7 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
if bigEndian {
|
if bigEndian {
|
||||||
return binary.BigEndian.Uint64(lsym.P[off:])
|
return binary.BigEndian.Uint64(lsym.P[off:])
|
||||||
} else {
|
} else {
|
||||||
|
|
18
test/fixedbugs/issue29215.go
Normal file
18
test/fixedbugs/issue29215.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// compile
|
||||||
|
|
||||||
|
// Copyright 2018 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 f() {
|
||||||
|
var s string
|
||||||
|
var p, q bool
|
||||||
|
s = "a"
|
||||||
|
for p {
|
||||||
|
p = false == (true != q)
|
||||||
|
s = ""
|
||||||
|
}
|
||||||
|
_ = s == "bbb"
|
||||||
|
}
|
Loading…
Reference in a new issue