]> Cypherpunks repositories - gostls13.git/commitdiff
debug/buildinfo: correct a typo in calculating next align index
authorZeke Lu <lvzecai@gmail.com>
Tue, 13 Sep 2022 18:05:53 +0000 (18:05 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 6 Oct 2022 14:46:33 +0000 (14:46 +0000)
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 <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>

src/debug/buildinfo/buildinfo.go
src/debug/buildinfo/buildinfo_test.go

index ef77f28ce59aba5acedf785176de6790c0178a26..255e6d3d503736da6f5b325263e8cdda4ad5ff74 100644 (file)
@@ -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.
index a0a816be17f42726a54121d6e1d21dd9f24cfcf9..ae04b4cb1dc92c26f20e5c6b885c722fe1d4cef9 100644 (file)
@@ -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)
+                       }
+               })
+       }
+}