},
fail: true,
},
+ {
+ // Don't check non-pointer data.
+ // Uses unsafe code to get a pointer we shouldn't check.
+ // Although we use unsafe, the uintptr represents an integer
+ // that happens to have the same representation as a pointer;
+ // that is, we are testing something that is not unsafe.
+ name: "ptrdata1",
+ c: `#include <stdlib.h>
+ void f(void* p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [8*8]byte; u uintptr }`,
+ body: `i := 0; p := &S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f(unsafe.Pointer(q))`,
+ fail: false,
+ },
+ {
+ // Like ptrdata1, but with a type that uses a GC program.
+ name: "ptrdata2",
+ c: `#include <stdlib.h>
+ void f(void* p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [32769*8]byte; q *int; u uintptr }`,
+ body: `i := 0; p := S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f(unsafe.Pointer(q))`,
+ fail: false,
+ },
}
func main() {
//go:nosplit
//go:nowritebarrier
func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
+ // Anything past typ.ptrdata is not a pointer.
+ if typ.ptrdata <= off {
+ return
+ }
+ if ptrdataSize := typ.ptrdata - off; size > ptrdataSize {
+ size = ptrdataSize
+ }
+
if typ.kind&kindGCProg == 0 {
cgoCheckBits(src, typ.gcdata, off, size)
return
// cgoCheckUsingType is like cgoCheckTypedBlock, but is a last ditch
// fall back to look for pointers in src using the type information.
-// We only this when looking at a value on the stack when the type
+// We only use this when looking at a value on the stack when the type
// uses a GC program, because otherwise it's more efficient to use the
// GC bits. This is called on the system stack.
//go:nowritebarrier
if typ.kind&kindNoPointers != 0 {
return
}
+
+ // Anything past typ.ptrdata is not a pointer.
+ if typ.ptrdata <= off {
+ return
+ }
+ if ptrdataSize := typ.ptrdata - off; size > ptrdataSize {
+ size = ptrdataSize
+ }
+
if typ.kind&kindGCProg == 0 {
cgoCheckBits(src, typ.gcdata, off, size)
return