mirror of
https://github.com/golang/go
synced 2024-11-22 03:34:40 -07:00
debug/buildinfo: stop searchMagic search at EOF
An invalid executable may claim to have a data section bigger than the executable, causing readData in searchMagic to hit EOF. Since readData suppresses all EOF errors, searchData would keep attempting to search through a potentially huge "section" despite readData continuously failing. Fix by suppressing EOF only on partial read. If nothing is read, allow EOF. Note that most of the admittedly tedious EOF handling in this package is around ensuring we return errNotGoExe in most cases. This was discovered by the new fuzz test. This fuzz test was inspired by #69066, though it has not found that specific bug. Change-Id: Icf413e996cecc583c084c9e44249b9294c3d8f10 Reviewed-on: https://go-review.googlesource.com/c/go/+/608637 Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
aa2e8b9ce2
commit
61e00ae134
@ -179,9 +179,14 @@ func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) {
|
||||
|
||||
// Read in the full header first.
|
||||
header, err := readData(x, addr, buildInfoHeaderSize)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return "", "", errNotGoExe
|
||||
} else if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if len(header) < buildInfoHeaderSize {
|
||||
return "", "", errNotGoExe
|
||||
}
|
||||
|
||||
const (
|
||||
ptrSizeOffset = 14
|
||||
@ -283,7 +288,9 @@ func decodeString(x exe, addr uint64) (string, uint64, error) {
|
||||
// addr. So we don't need to check that size doesn't overflow the
|
||||
// section.
|
||||
b, err := readData(x, addr, binary.MaxVarintLen64)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return "", 0, errNotGoExe
|
||||
} else if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
@ -294,11 +301,12 @@ func decodeString(x exe, addr uint64) (string, uint64, error) {
|
||||
addr += uint64(n)
|
||||
|
||||
b, err = readData(x, addr, length)
|
||||
if err != nil {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
// Length too large to allocate. Clearly bogus value.
|
||||
return "", 0, errNotGoExe
|
||||
}
|
||||
if err == io.EOF {
|
||||
return "", 0, errNotGoExe
|
||||
} else if err == io.ErrUnexpectedEOF {
|
||||
// Length too large to allocate. Clearly bogus value.
|
||||
return "", 0, errNotGoExe
|
||||
} else if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
if uint64(len(b)) < length {
|
||||
@ -364,7 +372,10 @@ func searchMagic(x exe, start, size uint64) (uint64, error) {
|
||||
}
|
||||
|
||||
n, err := readDataInto(x, start, buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// EOF before finding the magic; must not be a Go executable.
|
||||
return 0, errNotGoExe
|
||||
} else if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@ -407,7 +418,7 @@ func readData(x exe, addr, size uint64) ([]byte, error) {
|
||||
}
|
||||
|
||||
b, err := saferio.ReadDataAt(r, size, 0)
|
||||
if err == io.EOF {
|
||||
if len(b) > 0 && err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return b, err
|
||||
@ -420,7 +431,7 @@ func readDataInto(x exe, addr uint64, b []byte) (int, error) {
|
||||
}
|
||||
|
||||
n, err := r.ReadAt(b, 0)
|
||||
if err == io.EOF {
|
||||
if n > 0 && err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return n, err
|
||||
|
@ -408,3 +408,21 @@ func TestIssue54968(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzRead(f *testing.F) {
|
||||
go117, err := os.ReadFile("testdata/go117")
|
||||
if err != nil {
|
||||
f.Errorf("Error reading go117: %v", err)
|
||||
}
|
||||
f.Add(go117)
|
||||
|
||||
notgo, err := os.ReadFile("testdata/notgo")
|
||||
if err != nil {
|
||||
f.Errorf("Error reading notgo: %v", err)
|
||||
}
|
||||
f.Add(notgo)
|
||||
|
||||
f.Fuzz(func(t *testing.T, in []byte) {
|
||||
buildinfo.Read(bytes.NewReader(in))
|
||||
})
|
||||
}
|
||||
|
2
src/debug/buildinfo/testdata/fuzz/FuzzRead/36aeb674e3454016
vendored
Normal file
2
src/debug/buildinfo/testdata/fuzz/FuzzRead/36aeb674e3454016
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user