mirror of
https://github.com/golang/go
synced 2024-11-12 04:40:22 -07:00
runtime: check only up to ptrdata bytes for pointers
Fixes #14508. Change-Id: I237d0c5a79a73e6c97bdb2077d8ede613128b978 Reviewed-on: https://go-review.googlesource.com/23224 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
ebbe4f8db7
commit
538537a28d
@ -290,6 +290,30 @@ var ptrTests = []ptrTest{
|
||||
},
|
||||
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() {
|
||||
|
@ -94,6 +94,14 @@ func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
|
||||
//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
|
||||
@ -184,7 +192,7 @@ func cgoCheckBits(src unsafe.Pointer, gcbits *byte, off, size uintptr) {
|
||||
|
||||
// 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
|
||||
@ -193,6 +201,15 @@ func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user