Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime/cgo: "bad pointer in frame" caused by non-pointer Android EGLDisplay #27054

Closed
eliasnaur opened this issue Aug 17, 2018 · 2 comments
Closed
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@eliasnaur
Copy link
Contributor

What version of Go are you using (go version)?

go version devel +5a720d229d Sat Aug 4 16:37:47 2018 +0000 linux/amd64

What operating system and processor architecture are you using (go env)?

android/arm64

What did you do?

$ cat badpointer.go
package main

/*
#cgo LDFLAGS: -lEGL

#include <EGL/egl.h>
*/
import "C"
import "fmt"

func main() {
    eglDisp := C.eglGetDisplay(C.EGL_DEFAULT_DISPLAY)
    fmt.Println(eglDisp)
    growStack()
}

func growStack() {
    var v [1000000]byte
    fmt.Println(len(v))
}

$ CC=<arm64-ndk-toolchain>/bin/clang CGO_ENABLED=1 GOOS=android GOARCH=arm64 go run badpointer.go 

What did you expect to see?

No crash.

What did you see instead?

go_android_exec: adb shell mkdir -p /data/local/tmp/badpointer-23297
go_android_exec: adb push /tmp/go-build190416256/b001/exe/badpointer /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[  3%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[  7%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 10%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 14%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 17%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 21%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 24%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 28%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 31%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 35%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 38%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 42%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 45%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 49%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 53%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 56%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 60%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 63%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 67%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 70%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 74%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 77%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 81%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 84%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 88%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 91%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 95%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[ 99%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
[100%] /data/local/tmp/badpointer-23297/badpointer-23297-tmp
/tmp/go-build190416256/b001/exe/badpointer: 1 file pushed. 24.1 MB/s (1852272 bytes in 0.073s)
go_android_exec: adb shell cp '/data/local/tmp/badpointer-23297/badpointer-23297-tmp' '/data/local/tmp/badpointer-23297/badpointer-23297'
go_android_exec: adb shell rm '/data/local/tmp/badpointer-23297/badpointer-23297-tmp'
go_android_exec: adb shell export TMPDIR="/data/local/tmp/badpointer-23297"; export GOROOT="/data/local/tmp/goroot"; export GOPATH="/data/local/tmp/gopath"; cd "/data/local/tmp/gopath/src"; '/data/local/tmp/badpointer-23297/badpointer-23297' ; echo -n exitcode=$?
/system/bin/sh: cd: /data/local/tmp/gopath/src: No such file or directory
runtime: bad pointer in frame main.main at 0x4000044f88: 0x1
fatal error: invalid pointer found on stack

runtime stack:
runtime.throw(0x620b7cc43b, 0x1e)
	/home/elias/dev/go-tip/src/runtime/panic.go:608 +0x4c fp=0x7fd7fb8cc0 sp=0x7fd7fb8c90 pc=0x620b771924
runtime.adjustpointers(0x4000044f80, 0x7fd7fb8d60, 0x7fd7fb9140, 0x620b89eba0, 0x620b8acfa0)
	/home/elias/dev/go-tip/src/runtime/stack.go:591 +0x1e4 fp=0x7fd7fb8d10 sp=0x7fd7fb8cc0 pc=0x620b785d7c
runtime.adjustframe(0x7fd7fb9058, 0x7fd7fb9140, 0x620b8acfa0)
	/home/elias/dev/go-tip/src/runtime/stack.go:633 +0x100 fp=0x7fd7fb8d80 sp=0x7fd7fb8d10 pc=0x620b785e98
runtime.gentraceback(0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x4000000180, 0x0, 0x0, 0x7fffffff, 0x620b831a28, 0x7fd7fb9140, 0x0, ...)
	/home/elias/dev/go-tip/src/runtime/traceback.go:325 +0xe7c fp=0x7fd7fb90b0 sp=0x7fd7fb8d80 pc=0x620b78deb4
runtime.copystack(0x4000000180, 0x1000, 0x7248df5501)
	/home/elias/dev/go-tip/src/runtime/stack.go:845 +0x1b4 fp=0x7fd7fb9260 sp=0x7fd7fb90b0 pc=0x620b7863dc
runtime.newstack()
	/home/elias/dev/go-tip/src/runtime/stack.go:1017 +0x24c fp=0x7fd7fb9400 sp=0x7fd7fb9260 pc=0x620b786714
runtime.morestack()
	/home/elias/dev/go-tip/src/runtime/asm_arm64.s:298 +0x68 fp=0x7fd7fb9400 sp=0x7fd7fb9400 pc=0x620b796090

goroutine 1 [copystack]:
runtime.mapaccess1_fast32(0x620b8188a0, 0x0, 0x29ba0, 0x0)
	/home/elias/dev/go-tip/src/runtime/map_fast32.go:12 +0x1a4 fp=0x4000044b50 sp=0x4000044b50 pc=0x620b759d3c
runtime.resolveTypeOff(0x620b81b1c0, 0x6200029ba0, 0x0)
	/home/elias/dev/go-tip/src/runtime/type.go:246 +0x70 fp=0x4000044bb0 sp=0x4000044b50 pc=0x620b790b58
runtime.(*_type).typeOff(0x620b81b1c0, 0x6200029ba0, 0x0)
	/home/elias/dev/go-tip/src/runtime/type.go:258 +0x28 fp=0x4000044bd0 sp=0x4000044bb0 pc=0x620b790de0
runtime.(*itab).init(0x724b6c1000, 0x0, 0x620b8d2540)
	/home/elias/dev/go-tip/src/runtime/iface.go:201 +0x244 fp=0x4000044c80 sp=0x4000044bd0 pc=0x620b754adc
runtime.getitab(0x620b81b1c0, 0x620b811c40, 0x1, 0x4000098018)
	/home/elias/dev/go-tip/src/runtime/iface.go:69 +0x284 fp=0x4000044cd0 sp=0x4000044c80 pc=0x620b7545ac
runtime.assertE2I2(0x620b81b1c0, 0x620b811c40, 0x1, 0x724c16cd80, 0x1a, 0x620b7571b8)
	/home/elias/dev/go-tip/src/runtime/iface.go:560 +0x34 fp=0x4000044d00 sp=0x4000044cd0 pc=0x620b75528c
fmt.(*pp).handleMethods(0x40000a8000, 0x6200000076, 0x620b8b5700)
	/home/elias/dev/go-tip/src/fmt/print.go:567 +0x44 fp=0x4000044d90 sp=0x4000044d00 pc=0x620b7c3fdc
fmt.(*pp).printArg(0x40000a8000, 0x620b811c40, 0x1, 0x4000000076)
	/home/elias/dev/go-tip/src/fmt/print.go:686 +0x184 fp=0x4000044e20 sp=0x4000044d90 pc=0x620b7c44ec
fmt.(*pp).doPrintln(0x40000a8000, 0x4000044f80, 0x1, 0x1)
	/home/elias/dev/go-tip/src/fmt/print.go:1146 +0x9c fp=0x4000044e90 sp=0x4000044e20 pc=0x620b7c7124
fmt.Fprintln(0x620b832360, 0x4000098008, 0x4000036780, 0x1, 0x1, 0x1, 0x0, 0x0)
	/home/elias/dev/go-tip/src/fmt/print.go:254 +0x3c fp=0x4000044ef0 sp=0x4000044e90 pc=0x620b7c1954
fmt.Println(0x4000036780, 0x1, 0x1, 0x1d, 0x620b832320, 0x620b77302c)
	/home/elias/dev/go-tip/src/fmt/print.go:264 +0x4c fp=0x4000044f40 sp=0x4000044ef0 pc=0x620b7c1a24
main.main()
	/home/elias/dev/go/src/badpointer.go:13 +0x4c fp=0x4000044f90 sp=0x4000044f40 pc=0x620b7c7614
runtime.main()
	/home/elias/dev/go-tip/src/runtime/proc.go:201 +0x1f4 fp=0x4000044fd0 sp=0x4000044f90 pc=0x620b77305c
runtime.goexit()
	/home/elias/dev/go-tip/src/runtime/asm_arm64.s:1114 +0x4 fp=0x4000044fd0 sp=0x4000044fd0 pc=0x620b7986cc

goroutine 2 [force gc (idle)]:
runtime.gopark(0x620b831c38, 0x620b8b4e10, 0x1410, 0x1)
	/home/elias/dev/go-tip/src/runtime/proc.go:302 +0xc4 fp=0x4000036f70 sp=0x4000036f50 pc=0x620b77341c
runtime.goparkunlock(0x620b8b4e10, 0x1410, 0x1)
	/home/elias/dev/go-tip/src/runtime/proc.go:308 +0x44 fp=0x4000036fa0 sp=0x4000036f70 pc=0x620b7734ac
runtime.forcegchelper()
	/home/elias/dev/go-tip/src/runtime/proc.go:251 +0xa4 fp=0x4000036fd0 sp=0x4000036fa0 pc=0x620b7732bc
runtime.goexit()
	/home/elias/dev/go-tip/src/runtime/asm_arm64.s:1114 +0x4 fp=0x4000036fd0 sp=0x4000036fd0 pc=0x620b7986cc
created by runtime.init.3
	/home/elias/dev/go-tip/src/runtime/proc.go:240 +0x28

goroutine 3 [GC sweep wait]:
runtime.gopark(0x620b831c38, 0x620b8b4f20, 0x140c, 0x1)
	/home/elias/dev/go-tip/src/runtime/proc.go:302 +0xc4 fp=0x4000037780 sp=0x4000037760 pc=0x620b77341c
runtime.goparkunlock(0x620b8b4f20, 0x620b7d140c, 0x1)
	/home/elias/dev/go-tip/src/runtime/proc.go:308 +0x44 fp=0x40000377b0 sp=0x4000037780 pc=0x620b7734ac
runtime.bgsweep(0x400005e000)
	/home/elias/dev/go-tip/src/runtime/mgcsweep.go:52 +0x90 fp=0x40000377d0 sp=0x40000377b0 pc=0x620b767ab8
runtime.goexit()
	/home/elias/dev/go-tip/src/runtime/asm_arm64.s:1114 +0x4 fp=0x40000377d0 sp=0x40000377d0 pc=0x620b7986cc
created by runtime.gcenable
	/home/elias/dev/go-tip/src/runtime/mgc.go:216 +0x4c

goroutine 18 [finalizer wait]:
runtime.gopark(0x620b831c38, 0x620b8d1208, 0x140f, 0x1)
	/home/elias/dev/go-tip/src/runtime/proc.go:302 +0xc4 fp=0x4000032700 sp=0x40000326e0 pc=0x620b77341c
runtime.goparkunlock(0x620b8d1208, 0x140f, 0x1)
	/home/elias/dev/go-tip/src/runtime/proc.go:308 +0x44 fp=0x4000032730 sp=0x4000032700 pc=0x620b7734ac
runtime.runfinq()
	/home/elias/dev/go-tip/src/runtime/mfinal.go:175 +0x9c fp=0x40000327d0 sp=0x4000032730 pc=0x620b75f7d4
runtime.goexit()
	/home/elias/dev/go-tip/src/runtime/asm_arm64.s:1114 +0x4 fp=0x40000327d0 sp=0x40000327d0 pc=0x620b7986cc
created by runtime.createfing
	/home/elias/dev/go-tip/src/runtime/mfinal.go:156 +0x64
exitcode=2go_android_exec: adb shell rm -rf /data/local/tmp/badpointer-23297
exit status 2

It seems that on Android, an EGLDIsplay is declared as a pointer ("typedef void *EGLDisplay;"), but can contain values. If I replace "fmt.Println" with "println" (that presumably doesn't trigger stack growth) I get

$ CC=<arm64-ndk-toolchain>/bin/clang CGO_ENABLED=1 GOOS=android GOARCH=arm64 go 0x1

Which is the value (0x1) the bad pointer crash complained about.

To fix this we might need to treat EGL* types uintptr, the same as JNI jobject and Objective-C CFTypeRef. Perhaps it's an aspect of #22906.

Some thoughts:

  • Is it guaranteed safe to immediately cast the result of eglGetDisplay to uintptr and back? For example:
disp := uintptr(unsafe.Pointer(C.eglGetDisplay(C.EGL_DEFAULT_DISPLAY)))
...
C.eglInitialize(C.EGLDisplay(unsafe.Pointer(disp)), nil, nil)
  • Is it viable to add a pointer check for the return value of Cgo functions? That way, the crash would happen at the return of eglGetDisplay, not when the stack grows some time later.

@randall77 @ianlancetaylor

@andybons andybons changed the title runtime: "bad pointer in frame" caused by non-pointer Android EGLDisplay runtime/cgo: "bad pointer in frame" caused by non-pointer Android EGLDisplay Sep 4, 2018
@andybons andybons added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Sep 4, 2018
@andybons andybons added this to the Unplanned milestone Sep 4, 2018
@gopherbot
Copy link

Change https://golang.org/cl/154417 mentions this issue: cmd/fix,cmd/cgo,misc/cgo: map the EGLDisplay C type to uintptr in Go

@eliasnaur
Copy link
Contributor Author

It turns out that casting from uintptr to a pointer at the call site isn't enough to avoid the crash. I sent CL 154417 to turn EGLDisplay into uintptr in Go.

@golang golang locked and limited conversation to collaborators Dec 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

3 participants