diff options
| author | Meng Zhuo <mzh@golangcn.org> | 2023-04-02 20:01:28 +0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2023-04-11 13:16:24 +0000 |
| commit | 705e2e987e229a913b687561a6370e77dbab4165 (patch) | |
| tree | c973c5cfbc7297d1f0de509c976c97f6a730827c /src/debug/elf/file.go | |
| parent | f736a9ad0105b7906636aab43df96123d0f32d70 (diff) | |
| download | go-705e2e987e229a913b687561a6370e77dbab4165.tar.xz | |
debug/elf: avoid decompress of section twice
In rare cases, elf will get a corrupted section starts with 0x1,
which happens to be COMPRESS_ZLIB that causing decompress twice.
This CL drops sectionData decompress data after open section.
Fixes #59208
Change-Id: I7999a55868b3b3481509e1ac35985f7580f0f688
Reviewed-on: https://go-review.googlesource.com/c/go/+/480895
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: M Zhuo <mzh@golangcn.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src/debug/elf/file.go')
| -rw-r--r-- | src/debug/elf/file.go | 86 |
1 files changed, 37 insertions, 49 deletions
diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go index 3ff5f9554b..04737e6b2f 100644 --- a/src/debug/elf/file.go +++ b/src/debug/elf/file.go @@ -137,20 +137,46 @@ func (s *Section) Open() io.ReadSeeker { if s.Type == SHT_NOBITS { return io.NewSectionReader(&nobitsSectionReader{}, 0, int64(s.Size)) } + + var zrd func(io.Reader) (io.ReadCloser, error) if s.Flags&SHF_COMPRESSED == 0 { - return io.NewSectionReader(s.sr, 0, 1<<63-1) - } - if s.compressionType == COMPRESS_ZLIB { - return &readSeekerFromReader{ - reset: func() (io.Reader, error) { - fr := io.NewSectionReader(s.sr, s.compressionOffset, int64(s.FileSize)-s.compressionOffset) - return zlib.NewReader(fr) - }, - size: int64(s.Size), + + if !strings.HasPrefix(s.Name, ".zdebug") { + return io.NewSectionReader(s.sr, 0, 1<<63-1) } + + b := make([]byte, 12) + n, _ := s.sr.ReadAt(b, 0) + if n != 12 || string(b[:4]) != "ZLIB" { + return io.NewSectionReader(s.sr, 0, 1<<63-1) + } + + s.compressionOffset = 12 + s.compressionType = COMPRESS_ZLIB + s.Size = binary.BigEndian.Uint64(b[4:12]) + zrd = zlib.NewReader + + } else if s.Flags&SHF_ALLOC != 0 { + return errorReader{&FormatError{int64(s.Offset), + "SHF_COMPRESSED applies only to non-allocable sections", s.compressionType}} + } + + switch s.compressionType { + case COMPRESS_ZLIB: + zrd = zlib.NewReader + } + + if zrd == nil { + return errorReader{&FormatError{int64(s.Offset), "unknown compression type", s.compressionType}} + } + + return &readSeekerFromReader{ + reset: func() (io.Reader, error) { + fr := io.NewSectionReader(s.sr, s.compressionOffset, int64(s.FileSize)-s.compressionOffset) + return zrd(fr) + }, + size: int64(s.Size), } - err := &FormatError{int64(s.Offset), "unknown compression type", s.compressionType} - return errorReader{err} } // A ProgHeader represents a single ELF program header. @@ -1309,44 +1335,6 @@ func (f *File) DWARF() (*dwarf.Data, error) { if err != nil && uint64(len(b)) < s.Size { return nil, err } - var dlen uint64 - if len(b) >= 12 && string(b[:4]) == "ZLIB" { - dlen = binary.BigEndian.Uint64(b[4:12]) - s.compressionOffset = 12 - } - if dlen == 0 && len(b) >= 12 && s.Flags&SHF_COMPRESSED != 0 && - s.Flags&SHF_ALLOC == 0 && - f.FileHeader.ByteOrder.Uint32(b[:]) == uint32(COMPRESS_ZLIB) { - s.compressionType = COMPRESS_ZLIB - switch f.FileHeader.Class { - case ELFCLASS32: - // Chdr32.Size offset - dlen = uint64(f.FileHeader.ByteOrder.Uint32(b[4:])) - s.compressionOffset = 12 - case ELFCLASS64: - if len(b) < 24 { - return nil, errors.New("invalid compress header 64") - } - // Chdr64.Size offset - dlen = f.FileHeader.ByteOrder.Uint64(b[8:]) - s.compressionOffset = 24 - default: - return nil, fmt.Errorf("unsupported compress header:%s", f.FileHeader.Class) - } - } - if dlen > 0 { - r, err := zlib.NewReader(bytes.NewBuffer(b[s.compressionOffset:])) - if err != nil { - return nil, err - } - b, err = saferio.ReadData(r, dlen) - if err != nil { - return nil, err - } - if err := r.Close(); err != nil { - return nil, err - } - } if f.Type == ET_EXEC { // Do not apply relocations to DWARF sections for ET_EXEC binaries. |
