From: Josh Bleecher Snyder Date: Thu, 23 Mar 2017 18:40:47 +0000 (-0700) Subject: cmd/compile: strengthen SetFields/Width safety guarantee X-Git-Tag: go1.9beta1~951 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=8ee2d5bc00c5cc2313d87e001961294907cee133;p=gostls13.git cmd/compile: strengthen SetFields/Width safety guarantee It is currently possible in the compiler to create a struct type, calculate the widths of types that depend on it, and then alter the struct type. transformclosure has local protection against this. Protect against it at a deeper level. This is preparation to call dowidth automatically, rather than explicitly. This is a re-roll of CL 38469. Change-Id: Ic5b4baa250618504611fc57cbf51ab01d1eddf80 Reviewed-on: https://go-review.googlesource.com/38534 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky Reviewed-by: Brad Fitzpatrick --- diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 42543312f9..bd2ab1dc45 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -364,10 +364,6 @@ func transformclosure(xfunc *Node) { xfunc.Func.Dcl = append(decls, xfunc.Func.Dcl...) } - // Recalculate param offsets. - if f.Type.Width > 0 { - Fatalf("transformclosure: width is already calculated") - } dowidth(f.Type) xfunc.Type = f.Type // update type of ODCLFUNC } else { diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index 476a80b1b9..7f4796d60c 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -864,6 +864,15 @@ func (t *Type) FieldSlice() []*Field { // SetFields sets struct/interface type t's fields/methods to fields. func (t *Type) SetFields(fields []*Field) { + // If we've calculated the width of t before, + // then some other type such as a function signature + // might now have the wrong type. + // Rather than try to track and invalidate those, + // enforce that SetFields cannot be called once + // t's width has been calculated. + if t.WidthCalculated() { + Fatalf("SetFields of %v: width previously calculated", t) + } t.wantEtype(TSTRUCT) for _, f := range fields { // If type T contains a field F with a go:notinheap