Skip to content

Commit 06ba6a9

Browse files
committed
interp: support lowercase volume names in $PATH
On Windows, "C:" is a valid volume name, just like "c:". We were incorrectly assuming that the letter had to be uppercase. Add a simple regression test for Windows, which sets up a PATH with a script in a directory, then tries to execute it via such a PATH with a lowercase volume name. Fixes mvdan#355.
1 parent ecd349c commit 06ba6a9

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

interp/interp.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,10 @@ func (r *Runner) findExecutable(file string, exts []string) string {
12091209
return ""
12101210
}
12111211

1212+
func driveLetter(c byte) bool {
1213+
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
1214+
}
1215+
12121216
// splitList is like filepath.SplitList, but always using the unix path
12131217
// list separator ':'. On Windows, it also makes sure not to split
12141218
// [A-Z]:[/\].
@@ -1225,8 +1229,7 @@ func splitList(path string) []string {
12251229
for i := 0; i < len(list); i++ {
12261230
s := list[i]
12271231
switch {
1228-
case len(s) != 1, s[0] < 'A', s[0] > 'Z':
1229-
// not a disk name
1232+
case len(s) != 1, !driveLetter(s[0]):
12301233
case i+1 >= len(list):
12311234
// last element
12321235
case strings.IndexAny(list[i+1], `/\`) != 0:

interp/interp_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,3 +2728,35 @@ func TestRunnerEnvNoModify(t *testing.T) {
27282728
t.Fatalf("\nwant: %q\ngot: %q", want, got)
27292729
}
27302730
}
2731+
2732+
func TestMalformedPathOnWindows(t *testing.T) {
2733+
if runtime.GOOS != "windows" {
2734+
t.Skip("Skipping windows test on non-windows GOOS")
2735+
}
2736+
dir, err := ioutil.TempDir("", "interp-test")
2737+
if err != nil {
2738+
t.Fatal(err)
2739+
}
2740+
defer os.RemoveAll(dir)
2741+
2742+
path := filepath.Join(dir, "test.cmd")
2743+
script := []byte("@echo foo")
2744+
if err := ioutil.WriteFile(path, script, 0777); err != nil {
2745+
t.Fatal(err)
2746+
}
2747+
2748+
// set PATH to c:\tmp\dir instead of C:\tmp\dir
2749+
volume := filepath.VolumeName(dir)
2750+
pathList := strings.ToLower(volume) + dir[len(volume):]
2751+
2752+
file, _ := syntax.NewParser().Parse(strings.NewReader("test.cmd"), "")
2753+
var cb concBuffer
2754+
r, _ := New(Env(expand.ListEnviron("PATH="+pathList)), StdIO(nil, &cb, &cb))
2755+
if err := r.Run(context.Background(), file); err != nil {
2756+
t.Fatal(err)
2757+
}
2758+
want := "foo\r\n"
2759+
if got := cb.String(); got != want {
2760+
t.Fatalf("wrong output:\nwant: %q\ngot: %q", want, got)
2761+
}
2762+
}

0 commit comments

Comments
 (0)