Skip to content

Commit 069f9fb

Browse files
ianlancetaylorgopherbot
authored andcommitted
debug/pe: return error on reading from section with uninitialized data
A section with uninitialized data contains no bytes and occupies no space in the file. This change makes it return an error on reading from this section so that it will force the caller to check for a section with uninitialized data. This is the debug/pe version of CL 429601. This will break programs that expect a byte slice with the length described by the SizeOfRawData field. There are two reasons to introduce this breaking change: 1) uninitialized data is uninitialized and there is no reason to allocate memory for it; 2) it could result in an OOM if the file is corrupted and has a large invalid SizeOfRawData. No test case because the problem can only happen for invalid data. Let the fuzzer find cases like this. For #47653 Fixes #59817 Change-Id: I1ae94e9508f803b37926275d9a571f724a09af9f Reviewed-on: https://go-review.googlesource.com/c/go/+/488475 Reviewed-by: Bryan Mills <[email protected]> Reviewed-by: kortschak <[email protected]> Reviewed-by: Alex Brainman <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent 2380d17 commit 069f9fb

File tree

3 files changed

+17
-20
lines changed

3 files changed

+17
-20
lines changed

src/debug/pe/file.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"compress/zlib"
2121
"debug/dwarf"
2222
"encoding/binary"
23+
"errors"
2324
"fmt"
2425
"io"
2526
"os"
@@ -165,7 +166,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
165166
}
166167
r2 := r
167168
if sh.PointerToRawData == 0 { // .bss must have all 0s
168-
r2 = zeroReaderAt{}
169+
r2 = &nobitsSectionReader{}
169170
}
170171
s.sr = io.NewSectionReader(r2, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size))
171172
s.ReaderAt = s.sr
@@ -182,15 +183,10 @@ func NewFile(r io.ReaderAt) (*File, error) {
182183
return f, nil
183184
}
184185

185-
// zeroReaderAt is ReaderAt that reads 0s.
186-
type zeroReaderAt struct{}
186+
type nobitsSectionReader struct{}
187187

188-
// ReadAt writes len(p) 0s into p.
189-
func (w zeroReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
190-
for i := range p {
191-
p[i] = 0
192-
}
193-
return len(p), nil
188+
func (*nobitsSectionReader) ReadAt(p []byte, off int64) (n int, err error) {
189+
return 0, errors.New("unexpected read from section with uninitialized data")
194190
}
195191

196192
// getString extracts a string from symbol string table.
@@ -363,6 +359,9 @@ func (f *File) ImportedSymbols() ([]string, error) {
363359
var ds *Section
364360
ds = nil
365361
for _, s := range f.Sections {
362+
if s.Offset == 0 {
363+
continue
364+
}
366365
// We are using distance between s.VirtualAddress and idd.VirtualAddress
367366
// to avoid potential overflow of uint32 caused by addition of s.VirtualSize
368367
// to s.VirtualAddress.

src/debug/pe/file_test.go

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -511,17 +511,9 @@ main(void)
511511
if bss == nil {
512512
t.Fatal("could not find .bss section")
513513
}
514-
data, err := bss.Data()
515-
if err != nil {
516-
t.Fatal(err)
517-
}
518-
if len(data) == 0 {
519-
t.Fatalf("%s file .bss section cannot be empty", objpath)
520-
}
521-
for _, b := range data {
522-
if b != 0 {
523-
t.Fatalf(".bss section has non zero bytes: %v", data)
524-
}
514+
// We expect an error from bss.Data, as there are no contents.
515+
if _, err := bss.Data(); err == nil {
516+
t.Error("bss.Data succeeded, expected error")
525517
}
526518
}
527519

src/debug/pe/section.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,17 @@ type Section struct {
9797
}
9898

9999
// Data reads and returns the contents of the PE section s.
100+
//
101+
// If s.Offset is 0, the section has no contents,
102+
// and Data will always return a non-nil error.
100103
func (s *Section) Data() ([]byte, error) {
101104
return saferio.ReadDataAt(s.sr, uint64(s.Size), 0)
102105
}
103106

104107
// Open returns a new ReadSeeker reading the PE section s.
108+
//
109+
// If s.Offset is 0, the section has no contents, and all calls
110+
// to the returned reader will return a non-nil error.
105111
func (s *Section) Open() io.ReadSeeker {
106112
return io.NewSectionReader(s.sr, 0, 1<<63-1)
107113
}

0 commit comments

Comments
 (0)