Skip to content

cmd/cgo: Null pointer is accessed in C code, causing the stack to be destroyed #41070

Open
@fananchong

Description

@fananchong

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

$ go version
go version go1.14.3 linux/amd64

Does this issue reproduce with the latest release?

YES

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

go env Output
$ 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"

What did you do?

test.cpp:

#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:

#pragma once

#if __cplusplus
extern "C"
{
#endif

    extern void test_crash2();

#if __cplusplus
}
#endif

main.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:

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:

(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:

    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?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Triage Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions