diff --git a/src/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go index 55835bf8aca..8efa47346c3 100644 --- a/src/cmd/internal/buildid/buildid_test.go +++ b/src/cmd/internal/buildid/buildid_test.go @@ -7,6 +7,8 @@ package buildid import ( "bytes" "crypto/sha256" + "debug/elf" + "encoding/binary" "internal/obscuretestdata" "os" "reflect" @@ -90,6 +92,69 @@ func TestReadFile(t *testing.T) { if id != newID || err != nil { t.Errorf("ReadFile(%s after Rewrite) = %q, %v, want %q, nil", f, id, err, newID) } + + // Test an ELF PT_NOTE segment with an Align field of 0. + // Do this by rewriting the file data. + if strings.Contains(name, "elf") { + // We only expect a 64-bit ELF file. + if elf.Class(data[elf.EI_CLASS]) != elf.ELFCLASS64 { + continue + } + + // We only expect a little-endian ELF file. + if elf.Data(data[elf.EI_DATA]) != elf.ELFDATA2LSB { + continue + } + order := binary.LittleEndian + + var hdr elf.Header64 + if err := binary.Read(bytes.NewReader(data), order, &hdr); err != nil { + t.Error(err) + continue + } + + phoff := hdr.Phoff + phnum := int(hdr.Phnum) + phsize := uint64(hdr.Phentsize) + + for i := 0; i < phnum; i++ { + var phdr elf.Prog64 + if err := binary.Read(bytes.NewReader(data[phoff:]), order, &phdr); err != nil { + t.Error(err) + continue + } + + if elf.ProgType(phdr.Type) == elf.PT_NOTE { + // Increase the size so we keep + // reading notes. + order.PutUint64(data[phoff+4*8:], phdr.Filesz+1) + + // Clobber the Align field to zero. + order.PutUint64(data[phoff+6*8:], 0) + + // Clobber the note type so we + // keep reading notes. + order.PutUint32(data[phdr.Off+12:], 0) + } + + phoff += phsize + } + + if err := os.WriteFile(tmp, data, 0666); err != nil { + t.Error(err) + continue + } + + id, err := ReadFile(tmp) + // Because we clobbered the note type above, + // we don't expect to see a Go build ID. + // The issue we are testing for was a crash + // in Readefile; see issue #62097. + if id != "" || err != nil { + t.Errorf("ReadFile with zero ELF Align = %q, %v, want %q, nil", id, err, "") + continue + } + } } } diff --git a/src/cmd/internal/buildid/note.go b/src/cmd/internal/buildid/note.go index ab98701fb56..e0e8683c8ef 100644 --- a/src/cmd/internal/buildid/note.go +++ b/src/cmd/internal/buildid/note.go @@ -153,9 +153,11 @@ func readELF(name string, f *os.File, data []byte) (buildid string, err error) { } off += notesz align := p.Align - alignedOff := (off + align - 1) &^ (align - 1) - notesz += alignedOff - off - off = alignedOff + if align != 0 { + alignedOff := (off + align - 1) &^ (align - 1) + notesz += alignedOff - off + off = alignedOff + } filesz -= notesz note = note[notesz:] }