cmd/gc: pad structs which end in zero-sized fields

For a non-zero-sized struct with a final zero-sized field,
add a byte to the size (before rounding to alignment).  This
change ensures that taking the address of the zero-sized field
will not incorrectly leak the following object in memory.

reflect.funcLayout also needs this treatment.

Fixes #9401

Change-Id: I1dc503dc5af4ca22c8f8c048fb7b4541cc957e0f
Reviewed-on: https://go-review.googlesource.com/2452
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Keith Randall 2015-01-07 09:25:23 -08:00
parent 654a185f20
commit 6f07ac2f28
3 changed files with 69 additions and 8 deletions

View file

@ -1527,9 +1527,10 @@ func isReflexive(t *rtype) bool {
// gcProg is a helper type for generatation of GC pointer info.
type gcProg struct {
gc []byte
size uintptr // size of type in bytes
hasPtr bool
gc []byte
size uintptr // size of type in bytes
hasPtr bool
lastZero uintptr // largest offset of a zero-byte field
}
func (gc *gcProg) append(v byte) {
@ -1542,6 +1543,9 @@ func (gc *gcProg) appendProg(t *rtype) {
gc.align(uintptr(t.align))
if !t.pointers() {
gc.size += t.size
if t.size == 0 {
gc.lastZero = gc.size
}
return
}
switch t.Kind() {
@ -1566,11 +1570,15 @@ func (gc *gcProg) appendProg(t *rtype) {
gc.appendWord(bitsPointer)
gc.appendWord(bitsPointer)
case Struct:
oldsize := gc.size
c := t.NumField()
for i := 0; i < c; i++ {
gc.appendProg(t.Field(i).Type.common())
}
gc.align(uintptr(t.align))
if gc.size > oldsize + t.size {
panic("reflect: struct components are larger than the struct itself")
}
gc.size = oldsize + t.size
}
}
@ -1595,6 +1603,9 @@ func (gc *gcProg) finalize() (unsafe.Pointer, bool) {
if gc.size == 0 {
return nil, false
}
if gc.lastZero == gc.size {
gc.size++
}
ptrsize := unsafe.Sizeof(uintptr(0))
gc.align(ptrsize)
nptr := gc.size / ptrsize