go: runtime: writebarrierptr panic in isolated code snippet on Go 1.8.3
What version of Go are you using (go version
)?
1.8.3.
Does this issue reproduce with the latest release?
The issue does not repro with 1.9
What operating system and processor architecture are you using (go env
)?
Repro’ed on macOS and linux.
What did you do?
package main
import (
"fmt"
"unsafe"
"time"
)
func main() {
for i := 0; i < 1000000; i++ {
x := unsafe.Pointer(uintptr(0x27))
fmt.Printf("%p\n", x)
time.Sleep(1)
}
}
What did you expect to see?
No crash
What did you see instead?
....
0x27
0x27
0x27
0x27
0x27
0x27
runtime: writebarrierptr *0xc4200e80e0 = 0x27
fatal error: bad pointer in write barrier
runtime stack:
runtime.throw(0x10b6a19, 0x1c)
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/panic.go:596 +0x95
runtime.writebarrierptr.func1()
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/mbarrier.go:208 +0xbd
runtime.systemstack(0xc42001e600)
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/asm_amd64.s:327 +0x79
runtime.mstart()
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/proc.go:1132
goroutine 1 [running]:
runtime.systemstack_switch()
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/asm_amd64.s:281 fp=0xc420042cb8 sp=0xc420042cb0
runtime.writebarrierptr(0xc4200e80e0, 0x27)
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/mbarrier.go:209 +0x96 fp=0xc420042cf0 sp=0xc420042cb8
fmt.(*pp).printArg(0xc4200e80c0, 0x1097480, 0x27, 0x70)
/usr/local/Cellar/go/1.8.3/libexec/src/fmt/print.go:605 +0xa10 fp=0xc420042d78 sp=0xc420042cf0
fmt.(*pp).doPrintf(0xc4200e80c0, 0x10b37d3, 0x3, 0xc420042f68, 0x1, 0x1)
/usr/local/Cellar/go/1.8.3/libexec/src/fmt/print.go:998 +0x11e7 fp=0xc420042e58 sp=0xc420042d78
fmt.Fprintf(0x110a140, 0xc42000c018, 0x10b37d3, 0x3, 0xc420042f68, 0x1, 0x1, 0x13, 0x2, 0xc420446000)
/usr/local/Cellar/go/1.8.3/libexec/src/fmt/print.go:181 +0x76 fp=0xc420042ec0 sp=0xc420042e58
fmt.Printf(0x10b37d3, 0x3, 0xc420042f68, 0x1, 0x1, 0x5, 0x0, 0x0)
/usr/local/Cellar/go/1.8.3/libexec/src/fmt/print.go:190 +0x72 fp=0xc420042f20 sp=0xc420042ec0
main.main()
/Users/max/src/go/src/play/play.go:12 +0x8c fp=0xc420042f88 sp=0xc420042f20
runtime.main()
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/proc.go:185 +0x20a fp=0xc420042fe0 sp=0xc420042f88
runtime.goexit()
/usr/local/Cellar/go/1.8.3/libexec/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc420042fe8 sp=0xc420042fe0
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 21 (9 by maintainers)
Commits related to this issue
- cmd/cgo: make JNI's jobject type map to uintptr in Go The jobject type is declared as a pointer, but some JVMs (Dalvik, ART) store non-pointer values in them. In Go, we must use uintptr instead of a ... — committed to golang/go by randall77 7 years ago
- doc: add doc about C types that we map to uintptr instead of ptr Update #22906 Update #21897 Change-Id: I73709b2fdac6981d4bc2f7dab0767f2dd7be3be5 Reviewed-on: https://go-review.googlesource.com/8291... — committed to golang/go by randall77 7 years ago
@akalin-keybase Go is not C, and Go has a simple rule: a variable of pointer type must hold a pointer value. Tricks like converting an integer to a pointer type, while valid in C, are not valid in Go.
@akalin-keybase That is unsafe at the moment. There are two reasons:
The first we might be able to fix with the right sprinkling of nosplit directives in cgo generated code. The second seems harder, as the test should fail on some pointers, and from C we can manufacture almost any pointer. Unless we turn this check off altogether.
Neither can happen on returns, so there immediately casting to uintptr is ok.
The only workaround I can see at the moment is to do the cast on the C side and pass uintptr across the c/go boundary.