mirror of
https://github.com/golang/go
synced 2024-11-26 13:28:27 -07:00
fbdaa96563
The old code ignored the field alignment, and only looked at the field offset: if the field offset required padding, cgo added padding. But while that approach works for Go (at least with the gc toolchain) it doesn't work for C code using packed structs. With a packed struct the added padding may leave the struct at a misaligned position, and the inserted alignment, which cgo is not considering, may introduce additional, unexpected, padding. Padding that ignores alignment is not a good idea when the struct is not packed, and Go structs are never packed. So don't ignore alignment. Fixes #28896 Change-Id: Ie50ea15fa6dc35557497097be9fecfecb11efd8a Reviewed-on: https://go-review.googlesource.com/c/150602 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
84 lines
1.4 KiB
Go
84 lines
1.4 KiB
Go
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// cgo was incorrectly adding padding after a packed struct.
|
|
|
|
package cgotest
|
|
|
|
/*
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef struct {
|
|
void *f1;
|
|
uint32_t f2;
|
|
} __attribute__((__packed__)) innerPacked;
|
|
|
|
typedef struct {
|
|
innerPacked g1;
|
|
uint64_t g2;
|
|
} outerPacked;
|
|
|
|
typedef struct {
|
|
void *f1;
|
|
uint32_t f2;
|
|
} innerUnpacked;
|
|
|
|
typedef struct {
|
|
innerUnpacked g1;
|
|
uint64_t g2;
|
|
} outerUnpacked;
|
|
|
|
size_t offset(int x) {
|
|
switch (x) {
|
|
case 0:
|
|
return offsetof(innerPacked, f2);
|
|
case 1:
|
|
return offsetof(outerPacked, g2);
|
|
case 2:
|
|
return offsetof(innerUnpacked, f2);
|
|
case 3:
|
|
return offsetof(outerUnpacked, g2);
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
func offset(i int) uintptr {
|
|
var pi C.innerPacked
|
|
var po C.outerPacked
|
|
var ui C.innerUnpacked
|
|
var uo C.outerUnpacked
|
|
switch i {
|
|
case 0:
|
|
return unsafe.Offsetof(pi.f2)
|
|
case 1:
|
|
return unsafe.Offsetof(po.g2)
|
|
case 2:
|
|
return unsafe.Offsetof(ui.f2)
|
|
case 3:
|
|
return unsafe.Offsetof(uo.g2)
|
|
default:
|
|
panic("can't happen")
|
|
}
|
|
}
|
|
|
|
func test28896(t *testing.T) {
|
|
for i := 0; i < 4; i++ {
|
|
c := uintptr(C.offset(C.int(i)))
|
|
g := offset(i)
|
|
if c != g {
|
|
t.Errorf("%d: C: %d != Go %d", i, c, g)
|
|
}
|
|
}
|
|
}
|