]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: fix funcdata encode for functions with large frame size
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Fri, 13 Oct 2023 03:32:57 +0000 (10:32 +0700)
committerGopher Robot <gobot@golang.org>
Wed, 18 Oct 2023 16:32:07 +0000 (16:32 +0000)
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>

src/cmd/compile/internal/ssagen/ssa.go
src/cmd/compile/internal/types2/stdlib_test.go
src/go/types/stdlib_test.go
test/fixedbugs/issue52697.go [new file with mode: 0644]

index e8f0f561d0908ed8264f9d5078a679f27c076d9b..d3671a97738527f84ed768c2a166079ea9792ad6 100644 (file)
@@ -7,6 +7,7 @@ package ssagen
 import (
        "bufio"
        "bytes"
+       "encoding/binary"
        "fmt"
        "go/constant"
        "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.
 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))
        }
-       if v < 1<<7 {
-               return objw.Uint8(x, off, uint8(v))
+       var buf [binary.MaxVarintLen64]byte
+       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))
-       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))
+       return off
 }
 
 // emitOpenDeferInfo emits FUNCDATA information about the defers in a function
index fc93d4449778da1dd7f9068f7bce24ced17ca350..ae0f800d1e5744932a6e88a71fb564f059a1cbd2 100644 (file)
@@ -328,6 +328,7 @@ func TestStdFixed(t *testing.T) {
                "issue49767.go",  // go/types does not have constraints on channel element 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
+               "issue52697.go",  // types2 does not have constraints on stack size
 
                // These tests requires runtime/cgo.Incomplete, which is only available on some platforms.
                // However, types2 does not know about build constraints.
index 46fa475577a4da6b9c05fbb81af96d0263f565d7..e490dea848b8ad21f325ce1b42b1dd24a3a38b9c 100644 (file)
@@ -330,6 +330,7 @@ func TestStdFixed(t *testing.T) {
                "issue49767.go",  // go/types does not have constraints on channel element 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
+               "issue52697.go",  // go/types does not have constraints on stack size
 
                // These tests requires runtime/cgo.Incomplete, which is only available on some platforms.
                // However, go/types does not know about build constraints.
diff --git a/test/fixedbugs/issue52697.go b/test/fixedbugs/issue52697.go
new file mode 100644 (file)
index 0000000..da08a4f
--- /dev/null
@@ -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() {}