Skip to content

Commit f80b126

Browse files
committed
go/types, types2: check integer constant literal overflow
Fixes #54280. Change-Id: I44a31daaace50bc90c96cd36387bd1a009d6a287 Reviewed-on: https://go-review.googlesource.com/c/go/+/424055 Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 7ec0ec3 commit f80b126

File tree

7 files changed

+52
-11
lines changed

7 files changed

+52
-11
lines changed

src/cmd/compile/internal/types2/expr.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,11 @@ func (check *Checker) overflow(x *operand) {
109109
// Untyped integer values must not grow arbitrarily.
110110
const prec = 512 // 512 is the constant precision
111111
if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
112-
check.errorf(opPos(x.expr), "constant %s overflow", opName(x.expr))
112+
op := opName(x.expr)
113+
if op != "" {
114+
op += " "
115+
}
116+
check.errorf(opPos(x.expr), "constant %soverflow", op)
113117
x.val = constant.MakeUnknown()
114118
}
115119
}
@@ -1344,6 +1348,9 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
13441348
check.errorf(e, "malformed constant: %s", e.Value)
13451349
goto Error
13461350
}
1351+
// Ensure that integer values don't overflow (issue #54280).
1352+
x.expr = e // make sure that check.overflow below has an error position
1353+
check.overflow(x)
13471354

13481355
case *syntax.FuncLit:
13491356
if sig, ok := check.typ(e.Type).(*Signature); ok {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
const C = 912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912 // ERROR constant overflow

src/go/types/check_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ func TestManual(t *testing.T) {
352352
}
353353

354354
func TestLongConstants(t *testing.T) {
355-
format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant"
355+
format := "package longconst\n\nconst _ = %s /* ERROR constant overflow */ \nconst _ = %s // ERROR excessively long constant"
356356
src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001))
357357
testFiles(t, nil, []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil)
358358
}

src/go/types/expr.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,11 @@ func (check *Checker) overflow(x *operand, opPos token.Pos) {
110110
// Untyped integer values must not grow arbitrarily.
111111
const prec = 512 // 512 is the constant precision
112112
if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
113-
check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", opName(x.expr))
113+
op := opName(x.expr)
114+
if op != "" {
115+
op += " "
116+
}
117+
check.errorf(atPos(opPos), _InvalidConstVal, "constant %soverflow", op)
114118
x.val = constant.MakeUnknown()
115119
}
116120
}
@@ -1300,6 +1304,8 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
13001304
check.errorf(e, _InvalidConstVal, "malformed constant: %s", e.Value)
13011305
goto Error
13021306
}
1307+
// Ensure that integer values don't overflow (issue #54280).
1308+
check.overflow(x, e.Pos())
13031309

13041310
case *ast.FuncLit:
13051311
if sig, ok := check.typ(e.Type).(*Signature); ok {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
const C = 912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912 // ERROR constant overflow

test/const7.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ import (
2424
// which declares an untyped constant of the given length.
2525
// testProg compiles this package and checks for the absence or
2626
// presence of a constant literal error.
27-
func testProg(dir, name string, length int, ok bool) {
27+
func testProg(dir, name string, length int, msg string) {
2828
var buf bytes.Buffer
2929

3030
fmt.Fprintf(&buf,
31-
"package %s; const _ = %s // %d digits",
32-
name, strings.Repeat("9", length), length,
31+
"package %s; const _ = 0b%s // %d bits",
32+
name, strings.Repeat("1", length), length,
3333
)
3434

3535
filename := filepath.Join(dir, fmt.Sprintf("%s.go", name))
@@ -41,7 +41,7 @@ func testProg(dir, name string, length int, ok bool) {
4141
cmd.Dir = dir
4242
output, err := cmd.CombinedOutput()
4343

44-
if ok {
44+
if msg == "" {
4545
// no error expected
4646
if err != nil {
4747
log.Fatalf("%s: compile failed unexpectedly: %v", name, err)
@@ -53,7 +53,7 @@ func testProg(dir, name string, length int, ok bool) {
5353
if err == nil {
5454
log.Fatalf("%s: compile succeeded unexpectedly", name)
5555
}
56-
if !bytes.Contains(output, []byte("excessively long constant")) {
56+
if !bytes.Contains(output, []byte(msg)) {
5757
log.Fatalf("%s: wrong compiler error message:\n%s\n", name, output)
5858
}
5959
}
@@ -69,7 +69,10 @@ func main() {
6969
}
7070
defer os.RemoveAll(dir)
7171

72-
const limit = 10000 // compiler-internal constant length limit
73-
testProg(dir, "x1", limit, true)
74-
testProg(dir, "x2", limit+1, false)
72+
const bitLimit = 512
73+
const charLimit = 10000 // compiler-internal constant length limit
74+
testProg(dir, "x1", bitLimit, "")
75+
testProg(dir, "x2", bitLimit+1, "constant overflow")
76+
testProg(dir, "x3", charLimit-2, "constant overflow") // -2 because literal contains 0b prefix
77+
testProg(dir, "x4", charLimit-1, "excessively long constant")
7578
}

test/fixedbugs/issue54280.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// errorcheck
2+
3+
// Copyright 2022 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Don't crash in export of oversized integer constant.
8+
9+
package p
10+
11+
const C = 912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912_345_678_901_234_567_890_123_456_789_012_345_678_901_234_567_890_912 // ERROR "constant overflow"

0 commit comments

Comments
 (0)