From: Jeff R. Allen Date: Wed, 8 Nov 2017 08:43:56 +0000 (+0100) Subject: cmd/compile: do not write slices/strings > 2g X-Git-Tag: go1.10beta1~338 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d7ac9bb9927bfdbb1e6aa582d94e10b3374b88ce;p=gostls13.git cmd/compile: do not write slices/strings > 2g 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 Run-TryBot: Robert Griesemer TryBot-Result: Gobot Gobot --- diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index fdde0ce35b..874c59cb44 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -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))) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 7780953e90..f30016b8a9 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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 } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 847f6991ee..7e47c286e2 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -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) } } diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index a6e03baafa..e8e7a53bdb 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -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) } }