cmd/compile: set the limit of string constants to 1 GiB

CL 761300's decsription said setting a limit of 10 GiB for string
constants, but the code actually set the limit to 10 MiB. 10 MiB
is rather small, and it is reasonable to have string constants of
that size. 10 GiB is unnecessarily too large, as it overflows int
and the address space on 32-bit platforms. Set the limit to 1 GiB,
so can be handled on 32-bit platforms and not arbitrarily small.

Change-Id: I9af08c23ed8ba383e330a3f0fca18eb4943b7579
Reviewed-on: https://go-review.googlesource.com/c/go/+/769180
TryBot-Bypass: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Cherry Mui 2026-04-20 16:46:15 -04:00
parent 33cf6926ec
commit 543703d352
5 changed files with 83 additions and 10 deletions

View file

@ -34,6 +34,8 @@ import (
"cmd/compile/internal/syntax"
"flag"
"fmt"
"go/build"
"go/build/constraint"
"internal/buildcfg"
"internal/testenv"
"os"
@ -41,6 +43,7 @@ import (
"reflect"
"regexp"
"runtime"
"slices"
"strconv"
"strings"
"testing"
@ -435,13 +438,42 @@ func testDir(t *testing.T, dir string, colDelta uint, manual bool) {
}
func testPkg(t *testing.T, filenames []string, colDelta uint, manual bool) {
srcs := make([][]byte, len(filenames))
for i, filename := range filenames {
fs := filenames[:0]
srcs := make([][]byte, 0, len(filenames))
for _, filename := range filenames {
src, err := os.ReadFile(filename)
if err != nil {
t.Fatalf("could not read %s: %v", filename, err)
}
srcs[i] = src
if !shouldTest(src) {
continue
}
fs = append(fs, filename)
srcs = append(srcs, src)
}
testFiles(t, filenames, srcs, colDelta, manual)
if len(fs) == 0 {
t.Skip("all files skipped by build tags")
}
testFiles(t, fs, srcs, colDelta, manual)
}
// shouldTest checks build tags in src and returns whether the file
// should be tested according to the tags.
func shouldTest(src []byte) bool {
match := func(tag string) bool {
// We only care GOOS, GOARCH, and go version tags.
if slices.Contains(build.Default.ReleaseTags, tag) {
return true
}
return tag == runtime.GOOS || tag == runtime.GOARCH
}
for line := range strings.SplitSeq(string(src), "\n") {
if strings.HasPrefix(line, "package ") {
break
}
if expr, err := constraint.Parse(line); err == nil {
return expr.Eval(match)
}
}
return true
}

View file

@ -49,7 +49,7 @@ func (check *Checker) overflow(x *operand, opPos syntax.Pos) {
return
}
const maxLen = 10 * 1024 * 1024
const maxLen = 1 * 1024 * 1024 * 1024
if x.val.Kind() == constant.String && len(constant.StringVal(x.val)) > maxLen {
check.error(atPos(opPos), InvalidConstVal, "constant string too long")
x.val = constant.MakeUnknown()

View file

@ -34,6 +34,8 @@ import (
"flag"
"fmt"
"go/ast"
"go/build"
"go/build/constraint"
"go/parser"
"go/scanner"
"go/token"
@ -45,6 +47,7 @@ import (
"reflect"
"regexp"
"runtime"
"slices"
"strconv"
"strings"
"testing"
@ -461,13 +464,42 @@ func testDir(t *testing.T, dir string, manual bool) {
}
func testPkg(t *testing.T, filenames []string, manual bool) {
srcs := make([][]byte, len(filenames))
for i, filename := range filenames {
fs := filenames[:0]
srcs := make([][]byte, 0, len(filenames))
for _, filename := range filenames {
src, err := os.ReadFile(filename)
if err != nil {
t.Fatalf("could not read %s: %v", filename, err)
}
srcs[i] = src
if !shouldTest(src) {
continue
}
fs = append(fs, filename)
srcs = append(srcs, src)
}
if len(fs) == 0 {
t.Skip("all files skipped by build tags")
}
testFiles(t, filenames, srcs, manual)
}
// shouldTest checks build tags in src and returns whether the file
// should be tested according to the tags.
func shouldTest(src []byte) bool {
match := func(tag string) bool {
// We only care GOOS, GOARCH, and go version tags.
if slices.Contains(build.Default.ReleaseTags, tag) {
return true
}
return tag == runtime.GOOS || tag == runtime.GOARCH
}
for line := range strings.SplitSeq(string(src), "\n") {
if strings.HasPrefix(line, "package ") {
break
}
if expr, err := constraint.Parse(line); err == nil {
return expr.Eval(match)
}
}
return true
}

View file

@ -51,7 +51,7 @@ func (check *Checker) overflow(x *operand, opPos token.Pos) {
return
}
const maxLen = 10 * 1024 * 1024
const maxLen = 1 * 1024 * 1024 * 1024
if x.val.Kind() == constant.String && len(constant.StringVal(x.val)) > maxLen {
check.error(atPos(opPos), InvalidConstVal, "constant string too long")
x.val = constant.MakeUnknown()

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !386 && !arm && !mips && !mipsle && !wasm
package p
const (
@ -29,6 +31,13 @@ const (
v = u + u
w = v + v
x = w + w
y = x + /* ERROR "constant string too long" */ x
y = x + x
z = y + y
A = z + z
B = A + A
C = B + B
D = C + C
E = D + D
F = E + /* ERROR "constant string too long" */ E
G = F + F
)