]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: strengthen SetFields/Width safety guarantee
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 23 Mar 2017 18:40:47 +0000 (11:40 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 28 Mar 2017 18:06:36 +0000 (18:06 +0000)
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 <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/type.go

index 42543312f90d8579710d2729c81677c4fab93a2f..bd2ab1dc454ddb549714aa6bead2f3be91a7aa1d 100644 (file)
@@ -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 {
index 476a80b1b9d84233fbd9dc6377b63af7fdac1ace..7f4796d60ce175b26f1c42bc80acdefbcbd17b2e 100644 (file)
@@ -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