From a1813fcb839e21e46208a5294df87097a44bd05a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 21 Oct 2016 15:01:03 -0400 Subject: [PATCH] cmd/go: referee another vendor vs symlink fight Avoid crash in the specific case reported in #15201 but also print more useful error message, avoiding slice panic. Fixes #15201. Fixes #16167. Fixes #16566. Change-Id: I66499621e9678a05bc9b12b0da77906cd7027bdd Reviewed-on: https://go-review.googlesource.com/31665 Run-TryBot: Russ Cox TryBot-Result: Gobot Gobot Reviewed-by: Quentin Smith --- src/cmd/go/go_test.go | 21 +++++++++++++++++++++ src/cmd/go/pkg.go | 19 ++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 4a82fdef6c1..f445aef5bd0 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -1759,6 +1759,27 @@ func TestSymlinksVendor(t *testing.T) { tg.run("install") } +// Issue 15201. +func TestSymlinksVendor15201(t *testing.T) { + switch runtime.GOOS { + case "plan9", "windows": + t.Skipf("skipping symlink test on %s", runtime.GOOS) + } + + tg := testgo(t) + defer tg.cleanup() + + tg.tempDir("gopath/src/x/y/_vendor/src/x") + tg.must(os.Symlink("../../..", tg.path("gopath/src/x/y/_vendor/src/x/y"))) + tg.tempFile("gopath/src/x/y/w/w.go", "package w\nimport \"x/y/z\"\n") + tg.must(os.Symlink("../_vendor/src", tg.path("gopath/src/x/y/w/vendor"))) + tg.tempFile("gopath/src/x/y/z/z.go", "package z\n") + + tg.setenv("GOPATH", tg.path("gopath/src/x/y/_vendor")+string(filepath.ListSeparator)+tg.path("gopath")) + tg.cd(tg.path("gopath/src")) + tg.run("list", "./...") +} + func TestSymlinksInternal(t *testing.T) { switch runtime.GOOS { case "plan9", "windows": diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index 69367eefb13..a3018bce453 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -415,13 +415,26 @@ func vendoredImportPath(parent *Package, path string) (found string) { dir := filepath.Clean(parent.Dir) root := filepath.Join(parent.Root, "src") - if !hasFilePathPrefix(dir, root) { + if !hasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir { // Look for symlinks before reporting error. dir = expandPath(dir) root = expandPath(root) } - if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator { - fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator)) + + if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir { + fatalf("unexpected directory layout:\n"+ + " import path: %s\n"+ + " root: %s\n"+ + " dir: %s\n"+ + " expand root: %s\n"+ + " expand dir: %s\n"+ + " separator: %s", + parent.ImportPath, + filepath.Join(parent.Root, "src"), + filepath.Clean(parent.Dir), + root, + dir, + string(filepath.Separator)) } vpath := "vendor/" + path