You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Cgo panics if C function is called with pointer to []byte assigned to interface{} variable.
I've tested it with simple function returning []byte in same package, but error does not occur.
package main
/*
static void _test_ptr(void *p) {}
*/
import "C"
import (
"encoding/json"
"fmt"
"unsafe"
)
func main() {
var err error
var val interface{}
val, err = json.Marshal(struct{ A, B int }{1, 2})
if err != nil {
fmt.Println("marshal error:", err)
return
}
// crashes
var b = val.([]byte)
var p *byte
p = &b[0]
C._test_ptr(unsafe.Pointer(p))
// works
var copied = append([]byte(nil), b...)
p = &copied[0]
C._test_ptr(unsafe.Pointer(p))
}
run:
$ go run crashtest.go
panic: runtime error: cgo argument has Go pointer to Go pointer
goroutine 1 [running]:
panic(0x40af460, 0xc4200782c0)
/usr/local/Cellar/go/1.7.4/libexec/src/runtime/panic.go:500 +0x1a1
main._cgoCheckPointer0(0xc42009e024, 0x0, 0x0, 0x0, 0xc42009c120)
command-line-arguments/_obj/_cgo_gotypes.go:35 +0x59
main.main()
/tmp/crashtest.go:28 +0x280
exit status 2
env:
$ go version
go version go1.7.4 darwin/amd64
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/cubix/Developing/godaemon/"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.7.4/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.7.4/libexec/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/5w/7t9m60w12390mjlr63qvxg1h0000gn/T/go-build441330328=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
The text was updated successfully, but these errors were encountered:
This is essentially a duplicate of #14210. The problem is that json.Marshal returns a slice that points into scratch space stored in a larger struct (json.encodeState). When you set p = &b[0] in a statement separate from the call to the cgo function, the cgo command is not smart enough to see that you are passing the address of a slice element to the C function. Since it doesn't see that, it assumes that the argument points to the entire heap block, and the entire heap block does contain a pointer.
A simple workaround until cgo is fixed is to change
C._test_ptr(unsafe.Pointer(p))
to
C._test_ptr(unsafe.Pointer(&b[0]))
That will let cgo see that you are passing the address of a slice element and that it should only check the slice, not the entire heap block.
Cgo panics if C function is called with pointer to []byte assigned to interface{} variable.
I've tested it with simple function returning []byte in same package, but error does not occur.
run:
env:
The text was updated successfully, but these errors were encountered: