From 1082e2390e55519a576f21c0424f41246d232808 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 10 Jul 2015 14:38:35 -0700 Subject: [PATCH] cmd/link/internal/ld: stricter object file decoding Instead of silently truncating integers to their expected range, check that they're within range and emit errors if not. Intended to help narrow down the cause of issue #11617. Change-Id: Ia7b577270f8438ca7479262702371e26277f1ea7 Reviewed-on: https://go-review.googlesource.com/12050 Reviewed-by: Ian Lance Taylor --- src/cmd/link/internal/ld/objfile.go | 86 ++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go index f716ea43bb..36a65ba40e 100644 --- a/src/cmd/link/internal/ld/objfile.go +++ b/src/cmd/link/internal/ld/objfile.go @@ -164,22 +164,22 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) { if obj.Bgetc(f) != 0xfe { log.Fatalf("readsym out of sync") } - t := int(rdint(f)) + t := rdint(f) name := expandpkg(rdstring(f), pkg) - v := int(rdint(f)) + v := rdint(f) if v != 0 && v != 1 { log.Fatalf("invalid symbol version %d", v) } - flags := int(rdint(f)) + flags := rdint(f) dupok := flags & 1 local := false if flags&2 != 0 { local = true } - size := int(rdint(f)) + size := rdint(f) typ := rdsym(ctxt, f, pkg) data := rddata(f) - nreloc := int(rdint(f)) + nreloc := rdint(f) if v != 0 { v = ctxt.Version @@ -241,11 +241,11 @@ overwrite: var r *Reloc for i := 0; i < nreloc; i++ { r = &s.R[i] - r.Off = int32(rdint(f)) - r.Siz = uint8(rdint(f)) - r.Type = int32(rdint(f)) - r.Add = rdint(f) - rdint(f) // Xadd, ignored + r.Off = rdint32(f) + r.Siz = rduint8(f) + r.Type = rdint32(f) + r.Add = rdint64(f) + rdint64(f) // Xadd, ignored r.Sym = rdsym(ctxt, f, pkg) rdsym(ctxt, f, pkg) // Xsym, ignored } @@ -260,19 +260,19 @@ overwrite: } if s.Type == obj.STEXT { - s.Args = int32(rdint(f)) - s.Locals = int32(rdint(f)) - s.Nosplit = uint8(rdint(f)) - v := int(rdint(f)) + s.Args = rdint32(f) + s.Locals = rdint32(f) + s.Nosplit = rduint8(f) + v := rdint(f) s.Leaf = uint8(v & 1) s.Cfunc = uint8(v & 2) - n := int(rdint(f)) + n := rdint(f) var a *Auto for i := 0; i < n; i++ { a = new(Auto) a.Asym = rdsym(ctxt, f, pkg) - a.Aoffset = int32(rdint(f)) - a.Name = int16(rdint(f)) + a.Aoffset = rdint32(f) + a.Name = rdint16(f) a.Gotype = rdsym(ctxt, f, pkg) a.Link = s.Autom s.Autom = a @@ -283,13 +283,13 @@ overwrite: pc.Pcsp.P = rddata(f) pc.Pcfile.P = rddata(f) pc.Pcline.P = rddata(f) - n = int(rdint(f)) + n = rdint(f) pc.Pcdata = make([]Pcdata, n) pc.Npcdata = n for i := 0; i < n; i++ { pc.Pcdata[i].P = rddata(f) } - n = int(rdint(f)) + n = rdint(f) pc.Funcdata = make([]*LSym, n) pc.Funcdataoff = make([]int64, n) pc.Nfuncdata = n @@ -297,9 +297,9 @@ overwrite: pc.Funcdata[i] = rdsym(ctxt, f, pkg) } for i := 0; i < n; i++ { - pc.Funcdataoff[i] = rdint(f) + pc.Funcdataoff[i] = rdint64(f) } - n = int(rdint(f)) + n = rdint(f) pc.File = make([]*LSym, n) pc.Nfile = n for i := 0; i < n; i++ { @@ -374,7 +374,7 @@ overwrite: } } -func rdint(f *obj.Biobuf) int64 { +func rdint64(f *obj.Biobuf) int64 { var c int uv := uint64(0) @@ -392,15 +392,47 @@ func rdint(f *obj.Biobuf) int64 { return int64(uv>>1) ^ (int64(uint64(uv)<<63) >> 63) } +func rdint(f *obj.Biobuf) int { + n := rdint64(f) + if int64(int(n)) != n { + log.Panicf("%v out of range for int", n) + } + return int(n) +} + +func rdint32(f *obj.Biobuf) int32 { + n := rdint64(f) + if int64(int32(n)) != n { + log.Panicf("%v out of range for int32", n) + } + return int32(n) +} + +func rdint16(f *obj.Biobuf) int16 { + n := rdint64(f) + if int64(int16(n)) != n { + log.Panicf("%v out of range for int16", n) + } + return int16(n) +} + +func rduint8(f *obj.Biobuf) uint8 { + n := rdint64(f) + if int64(uint8(n)) != n { + log.Panicf("%v out of range for uint8", n) + } + return uint8(n) +} + func rdstring(f *obj.Biobuf) string { - n := rdint(f) + n := rdint64(f) p := make([]byte, n) obj.Bread(f, p) return string(p) } func rddata(f *obj.Biobuf) []byte { - n := rdint(f) + n := rdint64(f) p := make([]byte, n) obj.Bread(f, p) return p @@ -409,9 +441,9 @@ func rddata(f *obj.Biobuf) []byte { var symbuf []byte func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym { - n := int(rdint(f)) + n := rdint(f) if n == 0 { - rdint(f) + rdint64(f) return nil } @@ -420,7 +452,7 @@ func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym { } obj.Bread(f, symbuf[:n]) p := string(symbuf[:n]) - v := int(rdint(f)) + v := rdint(f) if v != 0 { v = ctxt.Version }