]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: prevent panic in go work use
authorFilippo Rossi <filipporossi@hey.com>
Mon, 4 Apr 2022 06:25:32 +0000 (06:25 +0000)
committerEmmanuel Odeke <emmanuel@orijtech.com>
Mon, 4 Apr 2022 06:48:45 +0000 (06:48 +0000)
Check if paths passed as arguments are existing directories.

Fixes #51841
Fixes #51749

Change-Id: Icfd148627e6f2c4651d6f923a37d413e68c67f6c
GitHub-Last-Rev: 77fffa7635052f11dc93488ee23fd1c895284b4d
GitHub-Pull-Request: golang/go#51845
Reviewed-on: https://go-review.googlesource.com/c/go/+/394154
Trust: Bryan Mills <bcmills@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/internal/workcmd/use.go
src/cmd/go/testdata/script/work_use_file.txt [deleted file]
src/cmd/go/testdata/script/work_use_only_dirs.txt [new file with mode: 0644]

index 07bc9b05009b3f75eb9175a6c5535922edad0e13..6da64b3f09e053480bdb3fe97d3743c9d2bd6ee1 100644 (file)
@@ -12,7 +12,6 @@ import (
        "cmd/go/internal/modload"
        "cmd/go/internal/str"
        "context"
-       "errors"
        "fmt"
        "io/fs"
        "os"
@@ -109,17 +108,33 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
                base.Fatalf("go: 'go work use' requires one or more directory arguments")
        }
        for _, useDir := range args {
-               if !*useR {
-                       if target, err := fsys.Stat(useDir); err == nil && !target.IsDir() {
-                               base.Errorf(`go: argument "%s" is not a directory`, useDir)
+               absArg, _ := pathRel(workDir, useDir)
+
+               info, err := fsys.Stat(absArg)
+               if err != nil {
+                       // Errors raised from os.Stat are formatted to be more user-friendly.
+                       if os.IsNotExist(err) {
+                               base.Errorf("go: directory %v does not exist", absArg)
                        } else {
-                               lookDir(useDir)
+                               base.Errorf("go: %v", err)
                        }
                        continue
+               } else if !info.IsDir() {
+                       base.Errorf("go: %s is not a directory", absArg)
+                       continue
+               }
+
+               if !*useR {
+                       lookDir(useDir)
+                       continue
                }
 
                // Add or remove entries for any subdirectories that still exist.
-               err := fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
+               fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
+                       if err != nil {
+                               return err
+                       }
+
                        if !info.IsDir() {
                                if info.Mode()&fs.ModeSymlink != 0 {
                                        if target, err := fsys.Stat(path); err == nil && target.IsDir() {
@@ -131,13 +146,9 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
                        lookDir(path)
                        return nil
                })
-               if err != nil && !errors.Is(err, os.ErrNotExist) {
-                       base.Errorf("go: %v", err)
-               }
 
                // Remove entries for subdirectories that no longer exist.
                // Because they don't exist, they will be skipped by Walk.
-               absArg, _ := pathRel(workDir, useDir)
                for absDir, _ := range haveDirs {
                        if str.HasFilePathPrefix(absDir, absArg) {
                                if _, ok := keepDirs[absDir]; !ok {
diff --git a/src/cmd/go/testdata/script/work_use_file.txt b/src/cmd/go/testdata/script/work_use_file.txt
deleted file mode 100644 (file)
index 807dd96..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-cp go.work go.work.orig
-
-# If an argument to 'go work use' is a file it should be handled gracefully as
-# an error and go.work should not be modified
-! go work use foo.txt
-stderr '^go: argument "foo\.txt" is not a directory$'
-cmp go.work go.work.orig
-
-
--- go.work --
-go 1.18
--- foo.txt --
diff --git a/src/cmd/go/testdata/script/work_use_only_dirs.txt b/src/cmd/go/testdata/script/work_use_only_dirs.txt
new file mode 100644 (file)
index 0000000..aa6dd78
--- /dev/null
@@ -0,0 +1,17 @@
+! go work use foo bar baz
+
+stderr '^go: '$WORK'[/\\]gopath[/\\]src[/\\]foo is not a directory'
+stderr '^go: directory '$WORK'[/\\]gopath[/\\]src[/\\]baz does not exist'
+cmp go.work go.work_want
+
+! go work use -r qux
+stderr '^go: '$WORK'[/\\]gopath[/\\]src[/\\]qux is not a directory'
+
+-- go.work --
+go 1.18
+-- go.work_want --
+go 1.18
+-- foo --
+-- qux --
+-- bar/go.mod --
+module bar
\ No newline at end of file