From 9dfadf911d2dcb093c3a37c79869bead0f9f6349 Mon Sep 17 00:00:00 2001 From: Zeke Lu Date: Tue, 13 Sep 2022 18:05:53 +0000 Subject: [PATCH] debug/buildinfo: correct a typo in calculating next align index When it calculates the smallest n such that: n >= i && n % buildInfoAlign == 0 the expression should be (i+buildInfoAlign-1)&^(buildInfoAlign-1) instead of (i+buildInfoAlign-1)&^buildInfoAlign Fixes #54968. Change-Id: Ibb7bdf568a521545b2609acc85e2ab4e05da5dae GitHub-Last-Rev: 479ebc140af9809f0bea039e643cb95b4f857614 GitHub-Pull-Request: golang/go#54971 Reviewed-on: https://go-review.googlesource.com/c/go/+/429815 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Auto-Submit: Bryan Mills --- src/debug/buildinfo/buildinfo.go | 2 +- src/debug/buildinfo/buildinfo_test.go | 70 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go index ef77f28ce5..255e6d3d50 100644 --- a/src/debug/buildinfo/buildinfo.go +++ b/src/debug/buildinfo/buildinfo.go @@ -164,7 +164,7 @@ func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) { data = data[i:] break } - data = data[(i+buildInfoAlign-1)&^buildInfoAlign:] + data = data[(i+buildInfoAlign-1)&^(buildInfoAlign-1):] } // Decode the blob. diff --git a/src/debug/buildinfo/buildinfo_test.go b/src/debug/buildinfo/buildinfo_test.go index a0a816be17..ae04b4cb1d 100644 --- a/src/debug/buildinfo/buildinfo_test.go +++ b/src/debug/buildinfo/buildinfo_test.go @@ -7,6 +7,8 @@ package buildinfo_test import ( "bytes" "debug/buildinfo" + "debug/pe" + "encoding/binary" "flag" "fmt" "internal/testenv" @@ -245,3 +247,71 @@ func TestReadFile(t *testing.T) { }) } } + +// TestIssue54968 is a regression test for golang.org/issue/54968. +// +// The cause of issue 54968 is when the first buildInfoMagic is invalid, it +// enters an infinite loop. +func TestIssue54968(t *testing.T) { + t.Parallel() + + const ( + paddingSize = 200 + buildInfoAlign = 16 + ) + buildInfoMagic := []byte("\xff Go buildinf:") + + // Construct a valid PE header. + var buf bytes.Buffer + + buf.Write([]byte{'M', 'Z'}) + buf.Write(bytes.Repeat([]byte{0}, 0x3c-2)) + // At location 0x3c, the stub has the file offset to the PE signature. + binary.Write(&buf, binary.LittleEndian, int32(0x3c+4)) + + buf.Write([]byte{'P', 'E', 0, 0}) + + binary.Write(&buf, binary.LittleEndian, pe.FileHeader{NumberOfSections: 1}) + + sh := pe.SectionHeader32{ + Name: [8]uint8{'t', 0}, + SizeOfRawData: uint32(paddingSize + len(buildInfoMagic)), + PointerToRawData: uint32(buf.Len()), + } + sh.PointerToRawData = uint32(buf.Len() + binary.Size(sh)) + + binary.Write(&buf, binary.LittleEndian, sh) + + start := buf.Len() + buf.Write(bytes.Repeat([]byte{0}, paddingSize+len(buildInfoMagic))) + data := buf.Bytes() + + if _, err := pe.NewFile(bytes.NewReader(data)); err != nil { + t.Fatalf("need a valid PE header for the misaligned buildInfoMagic test: %s", err) + } + + // Place buildInfoMagic after the header. + for i := 1; i < paddingSize-len(buildInfoMagic); i++ { + // Test only misaligned buildInfoMagic. + if i%buildInfoAlign == 0 { + continue + } + + t.Run(fmt.Sprintf("start_at_%d", i), func(t *testing.T) { + d := data[:start] + // Construct intentionally-misaligned buildInfoMagic. + d = append(d, bytes.Repeat([]byte{0}, i)...) + d = append(d, buildInfoMagic...) + d = append(d, bytes.Repeat([]byte{0}, paddingSize-i)...) + + _, err := buildinfo.Read(bytes.NewReader(d)) + + wantErr := "not a Go executable" + if err == nil { + t.Errorf("got error nil; want error containing %q", wantErr) + } else if errMsg := err.Error(); !strings.Contains(errMsg, wantErr) { + t.Errorf("got error %q; want error containing %q", errMsg, wantErr) + } + }) + } +} -- 2.48.1