-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
Go version
go1.26-devel_ce0e803ab9 Mon Aug 11 11:12:55 2025 -0700
Output of go env in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-I/Users/emmanuelodeke/Desktop/openSrc/rocksdb/include'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-L/Users/emmanuelodeke/Desktop/openSrc/rocksdb -lrocksdb -lstdc++ -lm -lz -lbz2 -lsnappy -llz4 -lzstd'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN='/Users/emmanuelodeke/go/bin'
GOCACHE='/Users/emmanuelodeke/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/emmanuelodeke/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/v3/7z434qpx5v3bw0wh8h2myfpw0000gn/T/go-build3287023084=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/emmanuelodeke/Desktop/openSrc/bugs/golang/73548/go.mod'
GOMODCACHE='/Users/emmanuelodeke/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/emmanuelodeke/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/emmanuelodeke/go/src/go.googlesource.com/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='on'
GOTELEMETRYDIR='/Users/emmanuelodeke/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/emmanuelodeke/go/src/go.googlesource.com/go/pkg/tool/darwin_amd64'
GOVCS=''
GOVERSION='go1.26-devel_ce0e803ab9 Mon Aug 11 11:12:55 2025 -0700'
GOWORK=''
PKG_CONFIG='pkg-config'What did you do?
I write here to report an issue that I've found while investigating pe.NewFile and how to crash programs that use it like symbolicators in security scanners to bypass them while doing security research work.
This is my reproduction:
package main
import (
"bytes"
"debug/pe"
)
func main() {
br := bytes.NewReader([]byte("MZ0000000000000000000000000000000000000000000000000000000000\x10\x01\x00\x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000PE\x00\x00d\x86\b\x000000\x00\x00\x00\x000000\xf0\x0000\v\x020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\x10\x00\x00\x00000000000\xb0\x00\x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\x00\x0000000000000000000000\x00\x000000000000000000\x00\x0000000000000000000000\x00\x000000000000000000\x00\x00\x000000000000000000000\x00\x00000000000000000 \x00\x00\x000000000000000000000\x00\x00000000000000000\x00\x00\x0000000000000000000000\x00\x0000000000000000000000\x00\x000\x02\x00\x000\x00\x00\x0000000000\x00\x0000000000000000000000000000000000000000\x00\x0000000000000000000000000000000000000000\x00\x00000000"))
f, err := pe.NewFile(br)
if err != nil {
panic(err)
}
defer f.Close()
f.ImportedSymbols()
}or via the playground https://go.dev/play/p/TjfLufg_qPp
What did you see happen?
It crashes on the past 3 go versions with:
$ go run main.go
panic: runtime error: slice bounds out of range [32768:560]
goroutine 1 [running]:
debug/pe.(*File).ImportedSymbols(0x95b3d48?)
/Users/emmanuelodeke/go/src/[go.googlesource.com/go/src/debug/pe/file.go:382](http://go.googlesource.com/go/src/debug/pe/file.go:382) +0x9f5
main.main()
/Users/emmanuelodeke/Desktop/openSrc/bugs/golang/repro/main.go:15 +0x10f
exit status 2
What did you expect to see?
No crash!
Diagnosis
The issue stems from the fact that inside pe.File.ImportedSymbols, after retrieving the data after the invocation f.Data() we don't check that the slice of data we are dereferencing is within correct bounds and this call happens at
Line 382 in 67d4a28
| d = d[idd.VirtualAddress-ds.VirtualAddress:] |
// didn't find a section, so no import libraries were found
if ds == nil {
return nil, nil
}
d, err := ds.Data()
if err != nil {
return nil, err
}
// seek to the virtual address specified in the import data directory
d = d[idd.VirtualAddress-ds.VirtualAddress:]but really we should correctly check the address bounds and return an error before that dereference or even catch it earlier if we can but this is my mitigation:
diff --git a/src/debug/pe/file.go b/src/debug/pe/file.go
index ed63a11cb6..756ff63574 100644
--- a/src/debug/pe/file.go
+++ b/src/debug/pe/file.go
@@ -379,7 +379,11 @@ func (f *File) ImportedSymbols() ([]string, error) {
}
// seek to the virtual address specified in the import data directory
- d = d[idd.VirtualAddress-ds.VirtualAddress:]
+ if seek := idd.VirtualAddress - ds.VirtualAddress; uint64(seek) >= uint64(len(d)) {
+ return nil, errors.New("optional header data directory virtual size doesn't fit within data seek")
+ } else {
+ d = d[seek:]
+ }Kindly cc-ing @alexbrainman