]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: do not write slices/strings > 2g
authorJeff R. Allen <jra@nella.org>
Wed, 8 Nov 2017 08:43:56 +0000 (09:43 +0100)
committerRobert Griesemer <gri@golang.org>
Thu, 9 Nov 2017 18:50:22 +0000 (18:50 +0000)
The linker will refuse to work on objects larger than
2e9 bytes (see issue #9862 for why).

With this change, the compiler gives a useful error
message explaining this, instead of leaving it to the
linker to give a cryptic message later.

Fixes #1700.

Change-Id: I3933ce08ef846721ece7405bdba81dff644cb004
Reviewed-on: https://go-review.googlesource.com/74330
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/walk.go
src/cmd/link/internal/ld/data.go

index fdde0ce35beb008be7ac698438750f750539b495..874c59cb44897416f4bb5e94581e4568c2af379c 100644 (file)
@@ -9,6 +9,7 @@ import (
        "cmd/internal/bio"
        "cmd/internal/obj"
        "cmd/internal/objabi"
+       "cmd/internal/src"
        "crypto/sha256"
        "fmt"
        "io"
@@ -330,7 +331,7 @@ func dbvec(s *obj.LSym, off int, bv bvec) int {
        return off
 }
 
-func stringsym(s string) (data *obj.LSym) {
+func stringsym(pos src.XPos, s string) (data *obj.LSym) {
        var symname string
        if len(s) > 100 {
                // Huge strings are hashed to avoid long names in object files.
@@ -351,7 +352,7 @@ func stringsym(s string) (data *obj.LSym) {
 
        if !symdata.SeenGlobl() {
                // string data
-               off := dsname(symdata, 0, s)
+               off := dsname(symdata, 0, s, pos, "string")
                ggloblsym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
        }
 
@@ -367,7 +368,7 @@ func slicebytes(nam *Node, s string, len int) {
        sym.Def = asTypesNode(newname(sym))
 
        lsym := sym.Linksym()
-       off := dsname(lsym, 0, s)
+       off := dsname(lsym, 0, s, nam.Pos, "slice")
        ggloblsym(lsym, int32(off), obj.NOPTR|obj.LOCAL)
 
        if nam.Op != ONAME {
@@ -380,7 +381,15 @@ func slicebytes(nam *Node, s string, len int) {
        duintptr(nsym, off, uint64(len))
 }
 
-func dsname(s *obj.LSym, off int, t string) int {
+func dsname(s *obj.LSym, off int, t string, pos src.XPos, what string) int {
+       // Objects that are too large will cause the data section to overflow right away,
+       // causing a cryptic error message by the linker. Check for oversize objects here
+       // and provide a useful error message instead.
+       if int64(len(t)) > 2e9 {
+               yyerrorl(pos, "%v with length %v is too big", what, len(t))
+               return 0
+       }
+
        s.WriteString(Ctxt, int64(off), len(t), t)
        return off + len(t)
 }
@@ -445,7 +454,7 @@ func gdata(nam *Node, nr *Node, wid int) {
                        }
 
                case string:
-                       symdata := stringsym(u)
+                       symdata := stringsym(nam.Pos, u)
                        s.WriteAddr(Ctxt, nam.Xoffset, Widthptr, symdata, 0)
                        s.WriteInt(Ctxt, nam.Xoffset+int64(Widthptr), Widthptr, int64(len(u)))
 
index 7780953e90f506b702e0d38a9b02596dd422eb4d..f30016b8a949b9f1a83d042626339655c7997f87 100644 (file)
@@ -5067,7 +5067,7 @@ func (e *ssafn) StringData(s string) interface{} {
        if e.strings == nil {
                e.strings = make(map[string]interface{})
        }
-       data := stringsym(s)
+       data := stringsym(e.curfn.Pos, s)
        e.strings[s] = data
        return data
 }
index 847f6991ee95f7467c4074674762bcc24553cb2d..7e47c286e28156acc0cccd6f5156d8f4a5d36f78 100644 (file)
@@ -1744,7 +1744,7 @@ opswitch:
                // Emit string symbol now to avoid emitting
                // any concurrently during the backend.
                if s, ok := n.Val().U.(string); ok {
-                       _ = stringsym(s)
+                       _ = stringsym(n.Pos, s)
                }
        }
 
index a6e03baafa00ce27386d4f6fa5c8a00f4ab72a09..e8e7a53bdb7f5db7adc9779c04af731b0dadbb3f 100644 (file)
@@ -1008,11 +1008,13 @@ func (d bySizeAndName) Less(i, j int) bool {
        return s1.name < s2.name
 }
 
-const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31)
+// cutoff is the maximum data section size permitted by the linker
+// (see issue #9862).
+const cutoff = 2e9 // 2 GB (or so; looks better in errors than 2^31)
 
 func checkdatsize(ctxt *Link, datsize int64, symn sym.SymKind) {
        if datsize > cutoff {
-               Errorf(nil, "too much data in section %v (over %d bytes)", symn, cutoff)
+               Errorf(nil, "too much data in section %v (over %v bytes)", symn, cutoff)
        }
 }