Closed
Description
What version of Go are you using (go version
)?
$ go version go version go1.11 darwin/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 GOARCH="amd64" GOBIN="" GOCACHE="/Users/ilya/Library/Caches/go-build" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOOS="darwin" GOPATH="/Users/ilya/volx/go" GOPROXY="" GORACE="" GOROOT="/usr/local/go" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" GCCGO="gccgo" CC="clang" CXX="clang++" 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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/nk/ft8bd8fx68n2gv_l5ft8yhvw0000gn/T/go-build278199837=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
Tried to parse the dwarf information of an elf file.
Compile the following:
//g++ -g test.cc int i = 3; int &bad = i; int main() { return 0; }
Then try to parse the DWARF information from the compiled ELF file, using:
//crash.go
package main
import (
"debug/dwarf"
"debug/elf"
"fmt"
"os"
)
func main() {
elf_file, err := elf.Open(os.Args[1])
defer elf_file.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "open failed %v", err)
os.Exit(1)
}
data, err := elf_file.DWARF()
r := data.Reader()
for {
e, err := r.Next()
if err != nil || e == nil {
break
}
if e.Tag == dwarf.TagVariable {
genAttr := e.Val(dwarf.AttrType)
typOff, ok := genAttr.(dwarf.Offset)
if !ok {
fmt.Fprint(os.Stderr, "Bad type")
os.Exit(1)
}
_, err := data.Type(typOff)
if err != nil {
fmt.Fprint(os.Stderr, "err in type decode: %v\n", err)
os.Exit(1)
}
}
}
}
Run:
<prog> a.out
What did you expect to see?
data.Type()
extracting the type of each variable
What did you see instead?
$ ./crash ../a.out panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x10a182e] goroutine 1 [running]: debug/dwarf.(*Data).readType(0xc0000ba000, 0x10fd3ae, 0x4, 0x1118540, 0xc0000c0240, 0xc00000005c, 0xc000066c00, 0xc00006e0e0, 0x0, 0x0, ...) /usr/local/go/src/debug/dwarf/type.go:703 +0xe1e debug/dwarf.(*Data).readType.func3(0xc000066db0, 0xc000066c00, 0xc000000062) /usr/local/go/src/debug/dwarf/type.go:365 +0x1a0 debug/dwarf.(*Data).readType(0xc0000ba000, 0x10fd3ae, 0x4, 0x1118540, 0xc0000c01b0, 0xc000000062, 0xc000066c00, 0xc00006e0e0, 0x0, 0x0, ...) /usr/local/go/src/debug/dwarf/type.go:576 +0x260a debug/dwarf.(*Data).Type(0xc0000ba000, 0xc000000062, 0x10d1540, 0xc00007f020, 0x0, 0x0) /usr/local/go/src/debug/dwarf/type.go:278 +0x85 main.main() /Users/ilya/test/crash/example.go:31 +0x1c9
It appears that the switch e.Tag {
in debug/dwarf/type.go:readType()
does not handle some dwarf tag types. This results in no error generated and use of a uninitialized global variable (that was not initialized in the switch statements), which ultimately causes the nil dereference.