-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
I'm testing some code with Go 1.14 and found that some tests are failing which passed in Go 1.13 while running under -race
.
This is due to the new checkptr checks that are enabled by -race
. Here's a minimized repro:
// +build ignore
package main
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
b := make([]byte, 20)
s := unsafeInts(b, 1) // with 0 or 8, no failure
fmt.Println(s)
}
func unsafeInts(b []byte, offs int) []int64 {
var s []int64
sh := (*reflect.SliceHeader)(unsafe.Pointer(&s))
sh.Data = uintptr(unsafe.Pointer(&b[offs]))
sh.Cap = (len(b) - offs) / 8
sh.Len = sh.Cap
return s
}
$ go1.13.4 run -race checkptr.go
[0 0]
$ go1.14beta1 run -race checkptr.go
panic: runtime error: unsafe pointer conversion
goroutine 1 [running]:
reflect.Value.Int(...)
/home/caleb/sdk/go1.14beta1/src/reflect/value.go:974
fmt.(*pp).printValue(0xc0000a08f0, 0x5150a0, 0xc0000bc001, 0x186, 0x76, 0x1)
/home/caleb/sdk/go1.14beta1/src/fmt/print.go:749 +0x3694
fmt.(*pp).printValue(0xc0000a08f0, 0x5136e0, 0xc0000aa020, 0x97, 0x76, 0x0)
/home/caleb/sdk/go1.14beta1/src/fmt/print.go:869 +0xfd3
fmt.(*pp).printArg(0xc0000a08f0, 0x5136e0, 0xc0000aa020, 0x76)
/home/caleb/sdk/go1.14beta1/src/fmt/print.go:716 +0x25b
fmt.(*pp).doPrintln(0xc0000a08f0, 0xc00005af50, 0x1, 0x1)
/home/caleb/sdk/go1.14beta1/src/fmt/print.go:1173 +0xae
fmt.Fprintln(0x55d520, 0xc0000b8008, 0xc00005af50, 0x1, 0x1, 0x432142, 0xc000092058, 0x0)
/home/caleb/sdk/go1.14beta1/src/fmt/print.go:264 +0x66
fmt.Println(...)
/home/caleb/sdk/go1.14beta1/src/fmt/print.go:274
main.main()
/home/caleb/p/misc/checkptr/checkptr.go:14 +0x18f
exit status 2
$
This error isn't particularly helpful (why is it unsafe?) and when I looked at the source, it still wasn't clear to me what the problem is.
// Check that (*[n]elem)(p) is appropriately aligned.
// TODO(mdempsky): What about fieldAlign?
if uintptr(p)&(uintptr(elem.align)-1) != 0 {
throw("checkptr: unsafe pointer conversion")
}
Even if there's some problem with unaligned pointers into the Go heap, in my application the backing data doesn't come from make([]byte)
but rather from unix.Mmap
. And my CPU (amd64) should have no problem with reading unaligned data, right?
It's also strange that the crash didn't happen in my code, but inside the reflect-y fmt code that looked at my data. (Not that it matters, but in my real code the crash isn't triggered by fmt but rather by go-cmp, also via use of reflect.Value.Int
.)
/cc @mdempsky