Skip to content

debug/elf: Incorrectly double-decompressing ELF section #59208

@brancz

Description

@brancz

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

$ go version
go version go1.20.1 darwin/arm64

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="arm64"
GOBIN="/Users/brancz/bin"
GOCACHE="/Users/brancz/Library/Caches/go-build"
GOENV="/Users/brancz/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/brancz/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/brancz"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.20.1/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.20.1/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.1"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/brancz/src/github.com/polarsignals/polarsignals/go.mod"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/var/folders/rl/8sh8jb5s1c1fl77ztzy4zw6m0000gn/T/go-build2747742421=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Downloaded the debuginfo for liblzma5:

curl https://debuginfod.ubuntu.com/buildid/0e13b0f27b3bc79a2828c11199ce4336a348af37/debuginfo > liblzma5.debuginfo

Tried to look at the DWARF entries:

package main

import (
	"bytes"
	"debug/elf"
	"fmt"
	"io"
	"net/http"
)

func main() {
	resp, err := http.Get("https://debuginfod.ubuntu.com/buildid/0e13b0f27b3bc79a2828c11199ce4336a348af37/debuginfo")
	if err != nil {
		panic(err)
	}

	if resp.StatusCode != 200 {
		panic("unexpected status code")
	}

	content, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	f, err := elf.NewFile(bytes.NewReader(content))
	if err != nil {
		panic(err)
	}

	_, err = f.DWARF()
	fmt.Println("DWARF ERROR:", err)
}

And running that returns an error:

$ go run main.go
DWARF ERROR: zlib: invalid header

What did you expect to see?

No error.

What did you see instead?

An error, and I suspect I know why: debug/elf in extremely rare cases attempts to double-decompress an ELF section.

First the call to .Data() returns the decompressed section:

b, err := s.Data()

And if by pure chance the first 4 bytes of the decompressed bytes also happen to be what trigger a decompression, then the .DWARF() function will attempt to decompress the section a second time:

go/src/debug/elf/file.go

Lines 1317 to 1319 in 0aa14fc

if dlen == 0 && len(b) >= 12 && s.Flags&SHF_COMPRESSED != 0 &&
s.Flags&SHF_ALLOC == 0 &&
f.FileHeader.ByteOrder.Uint32(b[:]) == uint32(COMPRESS_ZLIB) {

cc @mengzhuo since you recently added this case

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions