Repository: go
Issue: cmd/cgo: Null pointer is accessed in C code, causing the stack to be destroyed
Labels: NeedsInvestigation,compiler/runtime

<!--
Please answer these questions before submitting your issue. Thanks!
For questions please use one of our forums: https://github.com/golang/go/wiki/Questions
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.14.3 linux/amd64
</pre>

### Does this issue reproduce with the latest release?

YES

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/fananchong/.cache/go-build"
GOENV="/home/fananchong/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/fananchong/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build984316541=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

<!--
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.
-->

test.cpp:

```c++
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "test.h"

class A
{
public:
    void release() { free(ptr); }

private:
    void *ptr;
};

void test_crash2()
{
    A *a = (A *)0;
    a->release();
}
```

test.h:

```c++
#pragma once

#if __cplusplus
extern "C"
{
#endif

    extern void test_crash2();

#if __cplusplus
}
#endif
```

main.go:

```go
package main

/*
#include "test.h"
#include <stdlib.h>
#cgo LDFLAGS: -L. -ltest
*/
import "C"

import (
	_ "fmt"
)

func main() {
	C.test_crash2()
	select {}
}
```

build cmd:

```vim
gcc -I. -g3 -O0 -c test.cpp
ar cr libtest.a test.o
go build main.go
```

then run `env GOTRACEBACK=crash ./main`

the core dump is:

```vim
(gdb) bt
#0  runtime.raise () at /usr/local/go/src/runtime/sys_linux_amd64.s:165
#1  0x000000000044435b in runtime.dieFromSignal (sig=6) at /usr/local/go/src/runtime/signal_unix.go:729
#2  0x00000000004447ee in runtime.sigfwdgo (sig=6, info=0xc000009af0, ctx=0xc0000099c0, ~r3=<optimized out>) at /usr/local/go/src/runtime/signal_unix.go:943
#3  0x0000000000443264 in runtime.sigtrampgo (sig=6, info=0xc000009af0, ctx=0xc0000099c0) at /usr/local/go/src/runtime/signal_unix.go:412
#4  0x000000000045efc3 in runtime.sigtramp () at /usr/local/go/src/runtime/sys_linux_amd64.s:389
#5  <signal handler called>
#6  runtime.raise () at /usr/local/go/src/runtime/sys_linux_amd64.s:165
#7  0x000000000044435b in runtime.dieFromSignal (sig=6) at /usr/local/go/src/runtime/signal_unix.go:729
#8  0x00000000004444ea in runtime.crash () at /usr/local/go/src/runtime/signal_unix.go:821
#9  0x0000000000459c61 in runtime.fatalthrow.func1 () at /usr/local/go/src/runtime/panic.go:1175
#10 0x0000000000430637 in runtime.fatalthrow () at /usr/local/go/src/runtime/panic.go:1168
#11 0x0000000000430472 in runtime.throw (s=...) at /usr/local/go/src/runtime/panic.go:1116
#12 0x000000000044430a in runtime.sigpanic () at /usr/local/go/src/runtime/signal_unix.go:679
#13 0x000000000047fa06 in A::release (this=0x47fa06 <A::release()+20>) at test.cpp:33
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
```


### What did you expect to see?

code is:

```c++
    A *a = (A *)0;
    a->release();
```

I expect `this` pointer to be 0, and the stack is not destroyed

### What did you see instead?

`#13 0x000000000047fa06 in A::release (this=0x47fa06 <A::release()+20>) at test.cpp:33`

`this` pointer is `0x47fa06` and `Backtrace stopped: previous frame inner to this frame (corrupt stack?)`