]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: fix export data truncation bug
authorMatthew Dempsky <mdempsky@google.com>
Tue, 21 Nov 2017 19:27:20 +0000 (11:27 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 22 Nov 2017 18:12:36 +0000 (18:12 +0000)
Similar fix as in CL 60773 for fixing cmd/pack.

Fixes #21703.

Change-Id: I457ed8a3be828fd458abc5c8c1cc766a9f7aab13
Reviewed-on: https://go-review.googlesource.com/79135
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/ld/lib.go
src/cmd/link/link_test.go

index 81f8e4cb446eec6c5ffe3cdc9c615001aaeb15f7..cd8b45cd2ee94e23597f897020af7d6ba741cc1f 100644 (file)
@@ -1474,13 +1474,29 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
                }
        }
 
-       /* skip over exports and other info -- ends with \n!\n */
+       // Skip over exports and other info -- ends with \n!\n.
+       //
+       // Note: It's possible for "\n!\n" to appear within the binary
+       // package export data format. To avoid truncating the package
+       // definition prematurely (issue 21703), we keep keep track of
+       // how many "$$" delimiters we've seen.
+
        import0 := f.Offset()
 
        c1 = '\n' // the last line ended in \n
        c2 = bgetc(f)
        c3 = bgetc(f)
-       for c1 != '\n' || c2 != '!' || c3 != '\n' {
+       markers := 0
+       for {
+               if c1 == '\n' {
+                       if markers%2 == 0 && c2 == '!' && c3 == '\n' {
+                               break
+                       }
+                       if c2 == '$' && c3 == '$' {
+                               markers++
+                       }
+               }
+
                c1 = c2
                c2 = c3
                c3 = bgetc(f)
index 4ef184518e66ed70643ae0a1887c54c2f06ea7e7..4ec03abc8587151bcc2c4ead5e9b80700e146f65 100644 (file)
@@ -1,6 +1,13 @@
 package main
 
-import "testing"
+import (
+       "internal/testenv"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "testing"
+)
 
 var AuthorPaidByTheColumnInch struct {
        fog int `
@@ -28,3 +35,38 @@ func TestLargeSymName(t *testing.T) {
        // the bufio buffer. Issue #15104.
        _ = AuthorPaidByTheColumnInch
 }
+
+func TestIssue21703(t *testing.T) {
+       testenv.MustHaveGoBuild(t)
+
+       const source = `
+package main
+const X = "\n!\n"
+func main() {}
+`
+
+       tmpdir, err := ioutil.TempDir("", "issue21703")
+       if err != nil {
+               t.Fatalf("failed to create temp dir: %v\n", err)
+       }
+       defer os.RemoveAll(tmpdir)
+
+       err = ioutil.WriteFile(filepath.Join(tmpdir, "main.go"), []byte(source), 0666)
+       if err != nil {
+               t.Fatalf("failed to write main.go: %v\n", err)
+       }
+
+       cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "main.go")
+       cmd.Dir = tmpdir
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("failed to compile main.go: %v, output: %s\n", err, out)
+       }
+
+       cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "main.o")
+       cmd.Dir = tmpdir
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("failed to link main.o: %v, output: %s\n", err, out)
+       }
+}