]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: check integer constant literal overflow
authorRobert Griesemer <gri@golang.org>
Mon, 15 Aug 2022 23:26:23 +0000 (16:26 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 16 Aug 2022 01:11:29 +0000 (01:11 +0000)
Fixes #54280.

Change-Id: I44a31daaace50bc90c96cd36387bd1a009d6a287
Reviewed-on: https://go-review.googlesource.com/c/go/+/424055
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue54280.go [new file with mode: 0644]
src/go/types/check_test.go
src/go/types/expr.go
src/go/types/testdata/fixedbugs/issue54280.go [new file with mode: 0644]
test/const7.go
test/fixedbugs/issue54280.go [new file with mode: 0644]

index ee0792e61c472c6a994f572e426eda7c77af62d7..6e1e47c08ff154dff5e37df8064d75544e726961 100644 (file)
@@ -109,7 +109,11 @@ func (check *Checker) overflow(x *operand) {
        // Untyped integer values must not grow arbitrarily.
        const prec = 512 // 512 is the constant precision
        if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
-               check.errorf(opPos(x.expr), "constant %s overflow", opName(x.expr))
+               op := opName(x.expr)
+               if op != "" {
+                       op += " "
+               }
+               check.errorf(opPos(x.expr), "constant %soverflow", op)
                x.val = constant.MakeUnknown()
        }
 }
@@ -1344,6 +1348,9 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
                        check.errorf(e, "malformed constant: %s", e.Value)
                        goto Error
                }
+               // Ensure that integer values don't overflow (issue #54280).
+               x.expr = e // make sure that check.overflow below has an error position
+               check.overflow(x)
 
        case *syntax.FuncLit:
                if sig, ok := check.typ(e.Type).(*Signature); ok {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue54280.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue54280.go
new file mode 100644 (file)
index 0000000..e83e1a1
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2022 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 p
+
+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
index 4684a6e2961759cffb7875314745d53f53d91298..cd149499b2de2fb616f385ef96a37e21ac901685 100644 (file)
@@ -352,7 +352,7 @@ func TestManual(t *testing.T) {
 }
 
 func TestLongConstants(t *testing.T) {
-       format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant"
+       format := "package longconst\n\nconst _ = %s /* ERROR constant overflow */ \nconst _ = %s // ERROR excessively long constant"
        src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001))
        testFiles(t, nil, []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil)
 }
index 4b60123499c89a8c3f7a126016e486066b6ef6b2..4d3dd9edaba208d5a780ece0adc1c3e3f182b109 100644 (file)
@@ -110,7 +110,11 @@ func (check *Checker) overflow(x *operand, opPos token.Pos) {
        // Untyped integer values must not grow arbitrarily.
        const prec = 512 // 512 is the constant precision
        if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
-               check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", opName(x.expr))
+               op := opName(x.expr)
+               if op != "" {
+                       op += " "
+               }
+               check.errorf(atPos(opPos), _InvalidConstVal, "constant %soverflow", op)
                x.val = constant.MakeUnknown()
        }
 }
@@ -1300,6 +1304,8 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        check.errorf(e, _InvalidConstVal, "malformed constant: %s", e.Value)
                        goto Error
                }
+               // Ensure that integer values don't overflow (issue #54280).
+               check.overflow(x, e.Pos())
 
        case *ast.FuncLit:
                if sig, ok := check.typ(e.Type).(*Signature); ok {
diff --git a/src/go/types/testdata/fixedbugs/issue54280.go b/src/go/types/testdata/fixedbugs/issue54280.go
new file mode 100644 (file)
index 0000000..e83e1a1
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2022 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 p
+
+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
index 6acd7fde3a0decc3ac912db3ce30e24e8c7c41a4..8b252a24cf81d4e3f31c80e1f945da7000e89ffe 100644 (file)
@@ -24,12 +24,12 @@ import (
 // which declares an untyped constant of the given length.
 // testProg compiles this package and checks for the absence or
 // presence of a constant literal error.
-func testProg(dir, name string, length int, ok bool) {
+func testProg(dir, name string, length int, msg string) {
        var buf bytes.Buffer
 
        fmt.Fprintf(&buf,
-               "package %s; const _ = %s // %d digits",
-               name, strings.Repeat("9", length), length,
+               "package %s; const _ = 0b%s // %d bits",
+               name, strings.Repeat("1", length), length,
        )
 
        filename := filepath.Join(dir, fmt.Sprintf("%s.go", name))
@@ -41,7 +41,7 @@ func testProg(dir, name string, length int, ok bool) {
        cmd.Dir = dir
        output, err := cmd.CombinedOutput()
 
-       if ok {
+       if msg == "" {
                // no error expected
                if err != nil {
                        log.Fatalf("%s: compile failed unexpectedly: %v", name, err)
@@ -53,7 +53,7 @@ func testProg(dir, name string, length int, ok bool) {
        if err == nil {
                log.Fatalf("%s: compile succeeded unexpectedly", name)
        }
-       if !bytes.Contains(output, []byte("excessively long constant")) {
+       if !bytes.Contains(output, []byte(msg)) {
                log.Fatalf("%s: wrong compiler error message:\n%s\n", name, output)
        }
 }
@@ -69,7 +69,10 @@ func main() {
        }
        defer os.RemoveAll(dir)
 
-       const limit = 10000 // compiler-internal constant length limit
-       testProg(dir, "x1", limit, true)
-       testProg(dir, "x2", limit+1, false)
+       const bitLimit = 512
+       const charLimit = 10000 // compiler-internal constant length limit
+       testProg(dir, "x1", bitLimit, "")
+       testProg(dir, "x2", bitLimit+1, "constant overflow")
+       testProg(dir, "x3", charLimit-2, "constant overflow") // -2 because literal contains 0b prefix
+       testProg(dir, "x4", charLimit-1, "excessively long constant")
 }
diff --git a/test/fixedbugs/issue54280.go b/test/fixedbugs/issue54280.go
new file mode 100644 (file)
index 0000000..4f9103d
--- /dev/null
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2022 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.
+
+// Don't crash in export of oversized integer constant.
+
+package p
+
+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"