mirror of
https://github.com/golang/go
synced 2024-11-26 04:58:00 -07:00
cmd/compile: fix funcdata encode for functions with large frame size
The funcdata is encoded as varint, with the upper limit set to 1e9. However, the stack offsets could be up to 1<<30. Thus emitOpenDeferInfo will trigger an ICE for function with large frame size. By using binary.PutUvarint, the frame offset could be encoded correctly for value larger than 1<<35, allow the compiler to report the error. Further, the runtime also do validation when reading in the funcdata value, so a bad offset won't likely cause mis-behavior. Fixes #52697 Change-Id: I084c243c5d24c5d31cc22d5b439f0889e42b107c Reviewed-on: https://go-review.googlesource.com/c/go/+/535077 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Than McIntosh <thanm@google.com> Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
80834af206
commit
da7ac77380
@ -7,6 +7,7 @@ package ssagen
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"html"
|
"html"
|
||||||
@ -258,26 +259,15 @@ func abiForFunc(fn *ir.Func, abi0, abi1 *abi.ABIConfig) *abi.ABIConfig {
|
|||||||
|
|
||||||
// dvarint writes a varint v to the funcdata in symbol x and returns the new offset.
|
// dvarint writes a varint v to the funcdata in symbol x and returns the new offset.
|
||||||
func dvarint(x *obj.LSym, off int, v int64) int {
|
func dvarint(x *obj.LSym, off int, v int64) int {
|
||||||
if v < 0 || v > 1e9 {
|
if v < 0 {
|
||||||
panic(fmt.Sprintf("dvarint: bad offset for funcdata - %v", v))
|
panic(fmt.Sprintf("dvarint: bad offset for funcdata - %v", v))
|
||||||
}
|
}
|
||||||
if v < 1<<7 {
|
var buf [binary.MaxVarintLen64]byte
|
||||||
return objw.Uint8(x, off, uint8(v))
|
n := binary.PutUvarint(buf[:], uint64(v))
|
||||||
|
for _, b := range buf[:n] {
|
||||||
|
off = objw.Uint8(x, off, b)
|
||||||
}
|
}
|
||||||
off = objw.Uint8(x, off, uint8((v&127)|128))
|
return off
|
||||||
if v < 1<<14 {
|
|
||||||
return objw.Uint8(x, off, uint8(v>>7))
|
|
||||||
}
|
|
||||||
off = objw.Uint8(x, off, uint8(((v>>7)&127)|128))
|
|
||||||
if v < 1<<21 {
|
|
||||||
return objw.Uint8(x, off, uint8(v>>14))
|
|
||||||
}
|
|
||||||
off = objw.Uint8(x, off, uint8(((v>>14)&127)|128))
|
|
||||||
if v < 1<<28 {
|
|
||||||
return objw.Uint8(x, off, uint8(v>>21))
|
|
||||||
}
|
|
||||||
off = objw.Uint8(x, off, uint8(((v>>21)&127)|128))
|
|
||||||
return objw.Uint8(x, off, uint8(v>>28))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitOpenDeferInfo emits FUNCDATA information about the defers in a function
|
// emitOpenDeferInfo emits FUNCDATA information about the defers in a function
|
||||||
|
@ -328,6 +328,7 @@ func TestStdFixed(t *testing.T) {
|
|||||||
"issue49767.go", // go/types does not have constraints on channel element size
|
"issue49767.go", // go/types does not have constraints on channel element size
|
||||||
"issue49814.go", // go/types does not have constraints on array size
|
"issue49814.go", // go/types does not have constraints on array size
|
||||||
"issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22
|
"issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22
|
||||||
|
"issue52697.go", // types2 does not have constraints on stack size
|
||||||
|
|
||||||
// These tests requires runtime/cgo.Incomplete, which is only available on some platforms.
|
// These tests requires runtime/cgo.Incomplete, which is only available on some platforms.
|
||||||
// However, types2 does not know about build constraints.
|
// However, types2 does not know about build constraints.
|
||||||
|
@ -330,6 +330,7 @@ func TestStdFixed(t *testing.T) {
|
|||||||
"issue49767.go", // go/types does not have constraints on channel element size
|
"issue49767.go", // go/types does not have constraints on channel element size
|
||||||
"issue49814.go", // go/types does not have constraints on array size
|
"issue49814.go", // go/types does not have constraints on array size
|
||||||
"issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22
|
"issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22
|
||||||
|
"issue52697.go", // go/types does not have constraints on stack size
|
||||||
|
|
||||||
// These tests requires runtime/cgo.Incomplete, which is only available on some platforms.
|
// These tests requires runtime/cgo.Incomplete, which is only available on some platforms.
|
||||||
// However, go/types does not know about build constraints.
|
// However, go/types does not know about build constraints.
|
||||||
|
25
test/fixedbugs/issue52697.go
Normal file
25
test/fixedbugs/issue52697.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// errorcheck
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build !386 && !amd64p32 && !arm && !mips && !mipsle
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func g() { // GC_ERROR "stack frame too large"
|
||||||
|
xs := [3000 * 2000][33]int{}
|
||||||
|
for _, x := range xs {
|
||||||
|
if len(x) > 50 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() { // GC_ERROR "stack frame too large"
|
||||||
|
defer f()
|
||||||
|
g()
|
||||||
|
}
|
||||||
|
|
||||||
|
func f() {}
|
Loading…
Reference in New Issue
Block a user