Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit ab78af5

Browse files
committed
validate env var DEPCACHEDIR is a valid path if set
- fs.go - Add method `IsValidPath` to check if given file path string is valid. Add tests as well. - main.go - After loading cachedir from env, if it has been set, check validity, exit with status 1 if not. Update integration tests for this scenario.
1 parent 8eccd8b commit ab78af5

File tree

4 files changed

+121
-29
lines changed

4 files changed

+121
-29
lines changed

cmd/dep/integration_test.go

+47-21
Original file line numberDiff line numberDiff line change
@@ -65,31 +65,57 @@ func TestDepCachedir(t *testing.T) {
6565

6666
initPath := filepath.Join("testdata", "cachedir")
6767

68-
testProj := integration.NewTestProject(t, initPath, wd, runMain)
69-
defer testProj.Cleanup()
68+
t.Run("env-cachedir", func(t *testing.T) {
69+
t.Parallel()
70+
testProj := integration.NewTestProject(t, initPath, wd, runMain)
71+
defer testProj.Cleanup()
7072

71-
testProj.TempDir("cachedir")
72-
cachedir := testProj.Path("cachedir")
73-
testProj.Setenv("DEPCACHEDIR", cachedir)
73+
testProj.TempDir("cachedir")
74+
cachedir := testProj.Path("cachedir")
75+
testProj.Setenv("DEPCACHEDIR", cachedir)
7476

75-
// Running `dep ensure` will pull in the dependency into cachedir.
76-
err = testProj.DoRun([]string{"ensure"})
77-
if err != nil {
78-
// Log the error output from running `dep ensure`, could be useful.
79-
t.Log(testProj.GetStderr())
80-
t.Fatalf("got an unexpected error: %s", err.Error())
81-
}
77+
// Running `dep ensure` will pull in the dependency into cachedir.
78+
err = testProj.DoRun([]string{"ensure"})
79+
if err != nil {
80+
// Log the error output from running `dep ensure`, could be useful.
81+
t.Logf("`dep ensure` error output: \n%s", testProj.GetStderr())
82+
t.Errorf("got an unexpected error: %s", err)
83+
}
8284

83-
// Check that the cache was created in the cachedir. Our fixture has the dependency
84-
// `github.com/sdboyer/deptest`
85-
_, err = os.Stat(testProj.Path("cachedir", "sources", "https---github.lhy31512.workers.dev-sdboyer-deptest"))
86-
if err != nil {
87-
if os.IsNotExist(err) {
88-
t.Fatal("Expected cachedir to have been populated but none was found")
89-
} else {
90-
t.Fatalf("Got unexpected error: %s", err)
85+
// Check that the cache was created in the cachedir. Our fixture has the dependency
86+
// `github.com/sdboyer/deptest`
87+
_, err = os.Stat(testProj.Path("cachedir", "sources", "https---github.lhy31512.workers.dev-sdboyer-deptest"))
88+
if err != nil {
89+
if os.IsNotExist(err) {
90+
t.Error("expected cachedir to have been populated but none was found")
91+
} else {
92+
t.Errorf("got an unexpected error: %s", err)
93+
}
9194
}
92-
}
95+
})
96+
t.Run("env-invalid-cachedir", func(t *testing.T) {
97+
t.Parallel()
98+
testProj := integration.NewTestProject(t, initPath, wd, runMain)
99+
defer testProj.Cleanup()
100+
101+
cachedir := "/invalid/path"
102+
testProj.Setenv("DEPCACHEDIR", cachedir)
103+
wantErr := fmt.Sprintf(
104+
"dep: $DEPCACHEDIR set to an invalid or inaccessible path: %q", cachedir,
105+
)
106+
107+
// Running `dep ensure` will pull in the dependency into cachedir.
108+
err = testProj.DoRun([]string{"ensure"})
109+
110+
if err == nil {
111+
// Log the output from running `dep ensure`, could be useful.
112+
t.Logf("test run output: \n%s\n%s", testProj.GetStdout(), testProj.GetStderr())
113+
t.Error("unexpected result: \n\t(GOT) nil\n\t(WNT) exit status 1")
114+
} else if gotErr := strings.TrimSpace(testProj.GetStderr()); gotErr != wantErr {
115+
t.Errorf("unexpected error output: \n\t(GOT) %s\n\t(WNT) %s", gotErr, wantErr)
116+
}
117+
})
118+
93119
}
94120

95121
// execCmd is a test.RunFunc which runs the program in another process.

cmd/dep/main.go

+15-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"text/tabwriter"
1818

1919
"github.com/golang/dep"
20+
"github.com/golang/dep/internal/fs"
2021
)
2122

2223
var (
@@ -125,31 +126,37 @@ func (c *Config) Run() int {
125126
for _, cmd := range commands {
126127
if cmd.Name() == cmdName {
127128
// Build flag set with global flags in there.
128-
fs := flag.NewFlagSet(cmdName, flag.ContinueOnError)
129-
fs.SetOutput(c.Stderr)
130-
verbose := fs.Bool("v", false, "enable verbose logging")
129+
flags := flag.NewFlagSet(cmdName, flag.ContinueOnError)
130+
flags.SetOutput(c.Stderr)
131+
verbose := flags.Bool("v", false, "enable verbose logging")
131132

132133
// Register the subcommand flags in there, too.
133-
cmd.Register(fs)
134+
cmd.Register(flags)
134135

135136
// Override the usage text to something nicer.
136-
resetUsage(errLogger, fs, cmdName, cmd.Args(), cmd.LongHelp())
137+
resetUsage(errLogger, flags, cmdName, cmd.Args(), cmd.LongHelp())
137138

138139
if printCommandHelp {
139-
fs.Usage()
140+
flags.Usage()
140141
return errorExitCode
141142
}
142143

143144
// Parse the flags the user gave us.
144145
// flag package automatically prints usage and error message in err != nil
145146
// or if '-h' flag provided
146-
if err := fs.Parse(c.Args[2:]); err != nil {
147+
if err := flags.Parse(c.Args[2:]); err != nil {
147148
return errorExitCode
148149
}
149150

150151
// Cachedir is loaded from env if present. `$GOPATH/pkg/dep` is used as the
151152
// fallback cache location.
152153
cachedir := getEnv(c.Env, "DEPCACHEDIR")
154+
if cachedir != "" && !fs.IsValidPath(cachedir) {
155+
errLogger.Printf(
156+
"dep: $DEPCACHEDIR set to an invalid or inaccessible path: %q\n", cachedir,
157+
)
158+
return errorExitCode
159+
}
153160

154161
// Set up dep context.
155162
ctx := &dep.Ctx{
@@ -164,7 +171,7 @@ func (c *Config) Run() int {
164171
ctx.SetPaths(c.WorkingDir, GOPATHS...)
165172

166173
// Run the command with the post-flag-processing args.
167-
if err := cmd.Run(ctx, fs.Args()); err != nil {
174+
if err := cmd.Run(ctx, flags.Args()); err != nil {
168175
errLogger.Printf("%v\n", err)
169176
return errorExitCode
170177
}

internal/fs/fs.go

+18
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,24 @@ func cloneSymlink(sl, dst string) error {
480480
return os.Symlink(resolved, dst)
481481
}
482482

483+
// IsValidPath checks if the given string is a valid path.
484+
func IsValidPath(fp string) bool {
485+
// See https://stackoverflow.com/questions/35231846/golang-check-if-string-is-valid-path
486+
// Check if file/dir already exists
487+
if _, err := os.Stat(fp); err == nil {
488+
return true
489+
}
490+
491+
// Attempt to create it
492+
var d []byte
493+
if err := ioutil.WriteFile(fp, d, 0644); err == nil {
494+
os.Remove(fp) // And delete it
495+
return true
496+
}
497+
498+
return false
499+
}
500+
483501
// IsDir determines is the path given is a directory or not.
484502
func IsDir(name string) (bool, error) {
485503
fi, err := os.Stat(name)

internal/fs/fs_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,47 @@ func setupInaccessibleDir(t *testing.T, op func(dir string) error) func() {
837837
return cleanup
838838
}
839839

840+
func TestIsValidPath(t *testing.T) {
841+
wd, err := os.Getwd()
842+
if err != nil {
843+
t.Fatal(err)
844+
}
845+
846+
var dn string
847+
848+
cleanup := setupInaccessibleDir(t, func(dir string) error {
849+
dn = filepath.Join(dir, "dir")
850+
return os.Mkdir(dn, 0777)
851+
})
852+
defer cleanup()
853+
854+
tests := map[string]bool{
855+
wd: true,
856+
filepath.Join(wd, "testdata"): true,
857+
filepath.Join(wd, "main.go"): true,
858+
filepath.Join(wd, "this_file_does_not_exist.thing"): true,
859+
dn: false,
860+
"": false,
861+
"/invalid/path": false,
862+
}
863+
864+
if runtime.GOOS == "windows" {
865+
// This test doesn't work on Microsoft Windows because
866+
// of the differences in how file permissions are
867+
// implemented. For this to work, the directory where
868+
// the directory exists should be inaccessible.
869+
delete(tests, dn)
870+
}
871+
872+
for fp, want := range tests {
873+
got := IsValidPath(fp)
874+
875+
if got != want {
876+
t.Fatalf("expected %t for %s, got %t", want, fp, got)
877+
}
878+
}
879+
}
880+
840881
func TestIsRegular(t *testing.T) {
841882
wd, err := os.Getwd()
842883
if err != nil {

0 commit comments

Comments
 (0)