]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: fix size of StructOf ending in zero-sized field
authorIan Lance Taylor <iant@golang.org>
Tue, 22 Nov 2016 23:50:03 +0000 (15:50 -0800)
committerIan Lance Taylor <iant@golang.org>
Wed, 23 Nov 2016 00:44:01 +0000 (00:44 +0000)
Update #9401.
Fixes #18016.

Change-Id: Icc24dd10dab1ad8e5cf295e0727d437afa5025c0
Reviewed-on: https://go-review.googlesource.com/33475
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/reflect/all_test.go
src/reflect/type.go

index e26c20148f3e3b9f0cce80f022622fcdbcbe2a96..033a18171de96b966bc9f2233689dd5d49191d93 100644 (file)
@@ -4059,6 +4059,38 @@ func TestStructOf(t *testing.T) {
                }
        }
 
+       // Check size and alignment with a trailing zero-sized field.
+       st = StructOf([]StructField{
+               {
+                       Name: "F1",
+                       Type: TypeOf(byte(0)),
+               },
+               {
+                       Name: "F2",
+                       Type: TypeOf([0]*byte{}),
+               },
+       })
+       stt = TypeOf(struct {
+               G1 byte
+               G2 [0]*byte
+       }{})
+       if st.Size() != stt.Size() {
+               t.Errorf("constructed zero-padded struct size = %v, want %v", st.Size(), stt.Size())
+       }
+       if st.Align() != stt.Align() {
+               t.Errorf("constructed zero-padded struct align = %v, want %v", st.Align(), stt.Align())
+       }
+       if st.FieldAlign() != stt.FieldAlign() {
+               t.Errorf("constructed zero-padded struct field align = %v, want %v", st.FieldAlign(), stt.FieldAlign())
+       }
+       for i := 0; i < st.NumField(); i++ {
+               o1 := st.Field(i).Offset
+               o2 := stt.Field(i).Offset
+               if o1 != o2 {
+                       t.Errorf("constructed zero-padded struct field %v offset = %v, want %v", i, o1, o2)
+               }
+       }
+
        // check duplicate names
        shouldPanic(func() {
                StructOf([]StructField{
index 4985ba81653eaa79e2bced2734fdbc4575679824..7216fb63c86ca8361169c8e168606f35dcc35b6a 100644 (file)
@@ -2400,6 +2400,7 @@ func StructOf(fields []StructField) Type {
                hasGCProg = false // records whether a struct-field type has a GCProg
        )
 
+       lastzero := uintptr(0)
        repr = append(repr, "struct {"...)
        for i, field := range fields {
                if field.Type == nil {
@@ -2570,9 +2571,22 @@ func StructOf(fields []StructField) Type {
                }
                size = f.offset + ft.size
 
+               if ft.size == 0 {
+                       lastzero = size
+               }
+
                fs[i] = f
        }
 
+       if size > 0 && lastzero == size {
+               // This is a non-zero sized struct that ends in a
+               // zero-sized field. We add an extra byte of padding,
+               // to ensure that taking the address of the final
+               // zero-sized field can't manufacture a poitner to the
+               // next object in the heap. See issue 9401.
+               size++
+       }
+
        var typ *structType
        var ut *uncommonType
        var typPin interface {