]> Cypherpunks repositories - gostls13.git/commitdiff
path/filepath: fix match of \\?\c:\* on Windows
authorRuss Cox <rsc@golang.org>
Wed, 19 Oct 2016 04:01:31 +0000 (00:01 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 24 Oct 2016 16:24:20 +0000 (16:24 +0000)
\\?\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/31460
Reviewed-by: Quentin Smith <quentin@golang.org>
src/path/filepath/match.go
src/path/filepath/path_windows.go
src/path/filepath/path_windows_test.go

index 9fa68f578d00b829db9240cd2540832c66b428da..5168e037b539f5153d94948cca82205db6a8210a 100644 (file)
@@ -240,13 +240,14 @@ func Glob(pattern string) (matches []string, err error) {
        }
 
        dir, file := Split(pattern)
+       volumeLen := 0
        if runtime.GOOS == "windows" {
-               dir = cleanGlobPathWindows(dir)
+               volumeLen, dir = cleanGlobPathWindows(dir)
        } else {
                dir = cleanGlobPath(dir)
        }
 
-       if !hasMeta(dir) {
+       if !hasMeta(dir[volumeLen:]) {
                return glob(dir, file, nil)
        }
 
@@ -283,18 +284,21 @@ func cleanGlobPath(path string) string {
 }
 
 // cleanGlobPathWindows is windows version of cleanGlobPath.
-func cleanGlobPathWindows(path string) string {
+func cleanGlobPathWindows(path string) (prefixLen int, cleaned string) {
        vollen := volumeNameLen(path)
        switch {
        case path == "":
-               return "."
+               return 0, "."
        case vollen+1 == len(path) && os.IsPathSeparator(path[len(path)-1]): // /, \, C:\ and C:/
                // do nothing to the path
-               return path
+               return vollen + 1, path
        case vollen == len(path) && len(path) == 2: // C:
-               return path + "." // convert C: into C:.
+               return vollen, path + "." // convert C: into C:.
        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
        }
 }
 
index 41c57df73869c6fe302ad4ba36869b244ed7c930..a74b6469a915584857c910212f96f1b7bd7cbaa4 100644 (file)
@@ -37,7 +37,7 @@ func volumeNameLen(path string) int {
        if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
                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]) &&
                !isSlash(path[2]) && path[2] != '.' {
                // first, leading `\\` and next shouldn't be `\`. its server name.
index 8d552d06f754ae67644b04a93359f2ff101b2914..6393629cccb77ffc9f9c8d80a0a801bc47f736fb 100644 (file)
@@ -12,6 +12,7 @@ import (
        "os/exec"
        "path/filepath"
        "reflect"
+       "runtime/debug"
        "strings"
        "testing"
 )
@@ -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:\*`)
+}