Commit 452bbfc1 authored by Russ Cox's avatar Russ Cox

path/filepath: fix match of \\?\c:\* on Windows

\\?\c:\ is a "root directory" that is not subject to further matching,
but the ? makes it look like a pattern, which was causing an
infinite recursion. Make sure the code understands the ? is not a pattern.

Fixes #15879.

Change-Id: I3a4310bbc398bcae764b9f8859c875317345e757
Reviewed-on: https://go-review.googlesource.com/31460Reviewed-by: 's avatarQuentin Smith <quentin@golang.org>
parent c5ccbdd2
...@@ -240,13 +240,14 @@ func Glob(pattern string) (matches []string, err error) { ...@@ -240,13 +240,14 @@ func Glob(pattern string) (matches []string, err error) {
} }
dir, file := Split(pattern) dir, file := Split(pattern)
volumeLen := 0
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
dir = cleanGlobPathWindows(dir) volumeLen, dir = cleanGlobPathWindows(dir)
} else { } else {
dir = cleanGlobPath(dir) dir = cleanGlobPath(dir)
} }
if !hasMeta(dir) { if !hasMeta(dir[volumeLen:]) {
return glob(dir, file, nil) return glob(dir, file, nil)
} }
...@@ -283,18 +284,21 @@ func cleanGlobPath(path string) string { ...@@ -283,18 +284,21 @@ func cleanGlobPath(path string) string {
} }
// cleanGlobPathWindows is windows version of cleanGlobPath. // cleanGlobPathWindows is windows version of cleanGlobPath.
func cleanGlobPathWindows(path string) string { func cleanGlobPathWindows(path string) (prefixLen int, cleaned string) {
vollen := volumeNameLen(path) vollen := volumeNameLen(path)
switch { switch {
case path == "": case path == "":
return "." return 0, "."
case vollen+1 == len(path) && os.IsPathSeparator(path[len(path)-1]): // /, \, C:\ and C:/ case vollen+1 == len(path) && os.IsPathSeparator(path[len(path)-1]): // /, \, C:\ and C:/
// do nothing to the path // do nothing to the path
return path return vollen + 1, path
case vollen == len(path) && len(path) == 2: // C: case vollen == len(path) && len(path) == 2: // C:
return path + "." // convert C: into C:. return vollen, path + "." // convert C: into C:.
default: default:
return path[0 : len(path)-1] // chop off trailing separator if vollen >= len(path) {
vollen = len(path) - 1
}
return vollen, path[0 : len(path)-1] // chop off trailing separator
} }
} }
......
...@@ -37,7 +37,7 @@ func volumeNameLen(path string) int { ...@@ -37,7 +37,7 @@ func volumeNameLen(path string) int {
if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
return 2 return 2
} }
// is it UNC // is it UNC? https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) && if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
!isSlash(path[2]) && path[2] != '.' { !isSlash(path[2]) && path[2] != '.' {
// first, leading `\\` and next shouldn't be `\`. its server name. // first, leading `\\` and next shouldn't be `\`. its server name.
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime/debug"
"strings" "strings"
"testing" "testing"
) )
...@@ -413,3 +414,10 @@ func TestToNorm(t *testing.T) { ...@@ -413,3 +414,10 @@ func TestToNorm(t *testing.T) {
} }
} }
} }
func TestUNC(t *testing.T) {
// Test that this doesn't go into an infinite recursion.
// See golang.org/issue/15879.
defer debug.SetMaxStack(debug.SetMaxStack(1e6))
filepath.Glob(`\\?\c:\*`)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment