switch lit.Kind {
        case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
                checkLangCompat(lit)
+               // The max. mantissa precision for untyped numeric values
+               // is 512 bits, or 4048 bits for each of the two integer
+               // parts of a fraction for floating-point numbers that are
+               // represented accurately in the go/constant package.
+               // Constant literals that are longer than this many bits
+               // are not meaningful; and excessively long constants may
+               // consume a lot of space and time for a useless conversion.
+               // Cap constant length with a generous upper limit that also
+               // allows for separators between all digits.
+               const limit = 10000
+               if len(lit.Value) > limit {
+                       p.errorAt(lit.Pos(), "excessively long constant: %s... (%d chars)", lit.Value[:10], len(lit.Value))
+                       return constant.MakeUnknown()
+               }
        }
 
        v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
 
                if e.Bad {
                        goto Error // error reported during parsing
                }
+               switch e.Kind {
+               case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
+                       // The max. mantissa precision for untyped numeric values
+                       // is 512 bits, or 4048 bits for each of the two integer
+                       // parts of a fraction for floating-point numbers that are
+                       // represented accurately in the go/constant package.
+                       // Constant literals that are longer than this many bits
+                       // are not meaningful; and excessively long constants may
+                       // consume a lot of space and time for a useless conversion.
+                       // Cap constant length with a generous upper limit that also
+                       // allows for separators between all digits.
+                       const limit = 10000
+                       if len(e.Value) > limit {
+                               check.errorf(e, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
+                               goto Error
+                       }
+               }
                x.setConst(e.Kind, e.Value)
                if x.mode == invalid {
                        // The parser already establishes syntactic correctness.
 
--- /dev/null
+// run
+
+// Copyright 2021 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.
+
+// Check that the compiler refuses excessively long constants.
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strings"
+)
+
+// testProg creates a package called name, with path dir/name.go,
+// 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, G_option, length int, ok bool) {
+       var buf bytes.Buffer
+
+       fmt.Fprintf(&buf,
+               "package %s; const _ = %s // %d digits",
+               name, strings.Repeat("9", length), length,
+       )
+
+       filename := filepath.Join(dir, fmt.Sprintf("%s.go", name))
+       if err := os.WriteFile(filename, buf.Bytes(), 0666); err != nil {
+               log.Fatal(err)
+       }
+
+       cmd := exec.Command("go", "tool", "compile", fmt.Sprintf("-G=%d", G_option), filename)
+       cmd.Dir = dir
+       output, err := cmd.CombinedOutput()
+
+       if ok {
+               // no error expected
+               if err != nil {
+                       log.Fatalf("%s: compile failed unexpectedly: %v", name, err)
+               }
+               return
+       }
+
+       // error expected
+       if err == nil {
+               log.Fatalf("%s: compile succeeded unexpectedly", name)
+       }
+       if !bytes.Contains(output, []byte("excessively long constant")) {
+               log.Fatalf("%s: wrong compiler error message:\n%s\n", name, output)
+       }
+}
+
+func main() {
+       if runtime.GOOS == "js" || runtime.Compiler != "gc" {
+               return
+       }
+
+       dir, err := ioutil.TempDir("", "const7_")
+       if err != nil {
+               log.Fatalf("creating temp dir: %v\n", err)
+       }
+       defer os.RemoveAll(dir)
+
+       const limit = 10000 // compiler-internal constant length limit
+       testProg(dir, "x1", 0, limit, true)    // -G=0
+       testProg(dir, "x2", 0, limit+1, false) // -G=0
+       testProg(dir, "x1", 1, limit, true)    // -G=1 (new type checker)
+       testProg(dir, "x2", 1, limit+1, false) // -G=1 (new type checker)
+}