Skip to content

Commit 1b59b01

Browse files
neildgopherbot
authored andcommitted
[release-branch.go1.20] path/filepath: consider \\?\c: as a volume on Windows
While fixing several bugs in path handling on Windows, beginning with \\?\. Prior to #540277, VolumeName considered the first path component after the \\?\ prefix to be part of the volume name. After, it considered only the \\? prefix to be the volume name. Restore the previous behavior. For #64028. Fixes #64040. Change-Id: I6523789e61776342800bd607fb3f29d496257e68 Reviewed-on: https://go-review.googlesource.com/c/go/+/541175 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> (cherry picked from commit eda42f7) Reviewed-on: https://go-review.googlesource.com/c/go/+/541520 Auto-Submit: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> Reviewed-by: Damien Neil <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 46bc338 commit 1b59b01

File tree

2 files changed

+17
-18
lines changed

2 files changed

+17
-18
lines changed

src/path/filepath/path_test.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ var wincleantests = []PathTest{
108108
{`//abc`, `\\abc`},
109109
{`///abc`, `\\\abc`},
110110
{`//abc//`, `\\abc\\`},
111+
{`\\?\C:\`, `\\?\C:\`},
112+
{`\\?\C:\a`, `\\?\C:\a`},
111113

112114
// Don't allow cleaning to move an element with a colon to the start of the path.
113115
{`a/../c:`, `.\c:`},
@@ -1472,10 +1474,13 @@ var volumenametests = []VolumeNameTest{
14721474
{`//.`, `\\.`},
14731475
{`//./`, `\\.\`},
14741476
{`//./NUL`, `\\.\NUL`},
1475-
{`//?/`, `\\?`},
1477+
{`//?`, `\\?`},
1478+
{`//?/`, `\\?\`},
1479+
{`//?/NUL`, `\\?\NUL`},
1480+
{`/??`, `\??`},
1481+
{`/??/`, `\??\`},
1482+
{`/??/NUL`, `\??\NUL`},
14761483
{`//./a/b`, `\\.\a`},
1477-
{`//?/`, `\\?`},
1478-
{`//?/`, `\\?`},
14791484
{`//./C:`, `\\.\C:`},
14801485
{`//./C:/`, `\\.\C:`},
14811486
{`//./C:/a/b/c`, `\\.\C:`},
@@ -1484,8 +1489,8 @@ var volumenametests = []VolumeNameTest{
14841489
{`//./UNC/host\`, `\\.\UNC\host\`},
14851490
{`//./UNC`, `\\.\UNC`},
14861491
{`//./UNC/`, `\\.\UNC\`},
1487-
{`\\?\x`, `\\?`},
1488-
{`\??\x`, `\??`},
1492+
{`\\?\x`, `\\?\x`},
1493+
{`\??\x`, `\??\x`},
14891494
}
14901495

14911496
func TestVolumeName(t *testing.T) {

src/path/filepath/path_windows.go

+7-13
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,14 @@ func volumeNameLen(path string) int {
102102
// \\.\unc\a\b\..\c into \\.\unc\a\c.
103103
return uncLen(path, len(`\\.\UNC\`))
104104

105-
case pathHasPrefixFold(path, `\\.`):
106-
// Path starts with \\., and is a Local Device path.
105+
case pathHasPrefixFold(path, `\\.`) ||
106+
pathHasPrefixFold(path, `\\?`) || pathHasPrefixFold(path, `\??`):
107+
// Path starts with \\.\, and is a Local Device path; or
108+
// path starts with \\?\ or \??\ and is a Root Local Device path.
107109
//
108-
// We currently treat the next component after the \\.\ prefix
109-
// as part of the volume name, although there doesn't seem to be
110-
// a principled reason to do this.
110+
// We treat the next component after the \\.\ prefix as
111+
// part of the volume name, which means Clean(`\\?\c:\`)
112+
// won't remove the trailing \. (See #64028.)
111113
if len(path) == 3 {
112114
return 3 // exactly \\.
113115
}
@@ -117,14 +119,6 @@ func volumeNameLen(path string) int {
117119
}
118120
return len(path) - len(rest) - 1
119121

120-
case pathHasPrefixFold(path, `\\?`) || pathHasPrefixFold(path, `\??`):
121-
// Path starts with \\?\ or \??\, and is a Root Local Device path.
122-
//
123-
// While Windows usually treats / and \ as equivalent,
124-
// /??/ does not seem to be recognized as a Root Local Device path.
125-
// We treat it as one anyway here to be safe.
126-
return 3
127-
128122
case len(path) >= 2 && isSlash(path[1]):
129123
// Path starts with \\, and is a UNC path.
130124
return uncLen(path, 2)

0 commit comments

Comments
 (0)