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

Commit eec7c00

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 efa03bc commit eec7c00

File tree

4 files changed

+122
-29
lines changed

4 files changed

+122
-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

+16-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
type command interface {
@@ -121,33 +122,40 @@ func (c *Config) Run() (exitCode int) {
121122
for _, cmd := range commands {
122123
if cmd.Name() == cmdName {
123124
// Build flag set with global flags in there.
124-
fs := flag.NewFlagSet(cmdName, flag.ContinueOnError)
125-
fs.SetOutput(c.Stderr)
126-
verbose := fs.Bool("v", false, "enable verbose logging")
125+
flags := flag.NewFlagSet(cmdName, flag.ContinueOnError)
126+
flags.SetOutput(c.Stderr)
127+
verbose := flags.Bool("v", false, "enable verbose logging")
127128

128129
// Register the subcommand flags in there, too.
129-
cmd.Register(fs)
130+
cmd.Register(flags)
130131

131132
// Override the usage text to something nicer.
132-
resetUsage(errLogger, fs, cmdName, cmd.Args(), cmd.LongHelp())
133+
resetUsage(errLogger, flags, cmdName, cmd.Args(), cmd.LongHelp())
133134

134135
if printCommandHelp {
135-
fs.Usage()
136+
flags.Usage()
136137
exitCode = 1
137138
return
138139
}
139140

140141
// Parse the flags the user gave us.
141142
// flag package automatically prints usage and error message in err != nil
142143
// or if '-h' flag provided
143-
if err := fs.Parse(c.Args[2:]); err != nil {
144+
if err := flags.Parse(c.Args[2:]); err != nil {
144145
exitCode = 1
145146
return
146147
}
147148

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

152160
// Set up dep context.
153161
ctx := &dep.Ctx{
@@ -162,7 +170,7 @@ func (c *Config) Run() (exitCode int) {
162170
ctx.SetPaths(c.WorkingDir, GOPATHS...)
163171

164172
// Run the command with the post-flag-processing args.
165-
if err := cmd.Run(ctx, fs.Args()); err != nil {
173+
if err := cmd.Run(ctx, flags.Args()); err != nil {
166174
errLogger.Printf("%v\n", err)
167175
exitCode = 1
168176
return

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)