aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2023-08-08 14:07:08 -0700
committerCarlos Amedee <carlos@golang.org>2023-08-23 17:53:16 +0000
commitf0b8768dbcf74bddedc32febd36732beb690b8aa (patch)
treeea18e23c9060ee912d9ab24fd9c6af6c9b6e1e1b
parentb4636682759ea7cd7a8ed480e4f98f401127306f (diff)
downloadgo-f0b8768dbcf74bddedc32febd36732beb690b8aa.tar.gz
go-f0b8768dbcf74bddedc32febd36732beb690b8aa.zip
[release-branch.go1.20] path/filepath: don't drop .. elements when cleaning invalid Windows paths
Fix a bug where Clean could improperly drop .. elements from a path on Windows, when the path contains elements containing a ':'. For example, Clean("a/../b:/../../c") now correctly returns "..\c" rather than "c". For #61866. Fixes #61867. Change-Id: I97b0238953c183b2ce19ca89c14f26700008ea72 Reviewed-on: https://go-review.googlesource.com/c/go/+/517216 Run-TryBot: Damien Neil <dneil@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Quim Muntal <quimmuntal@gmail.com> (cherry picked from commit 6e43407931ee4acc204620a9fae59c7903164901) Reviewed-on: https://go-review.googlesource.com/c/go/+/519636 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Damien Neil <dneil@google.com>
-rw-r--r--src/path/filepath/path.go32
-rw-r--r--src/path/filepath/path_test.go4
2 files changed, 24 insertions, 12 deletions
diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
index 32dd887998..326ca006b2 100644
--- a/src/path/filepath/path.go
+++ b/src/path/filepath/path.go
@@ -52,6 +52,11 @@ func (b *lazybuf) append(c byte) {
b.w++
}
+func (b *lazybuf) prepend(prefix ...byte) {
+ b.buf = append(prefix, b.buf...)
+ b.w += len(prefix)
+}
+
func (b *lazybuf) string() string {
if b.buf == nil {
return b.volAndPath[:b.volLen+b.w]
@@ -146,18 +151,6 @@ func Clean(path string) string {
if rooted && out.w != 1 || !rooted && out.w != 0 {
out.append(Separator)
}
- // If a ':' appears in the path element at the start of a Windows path,
- // insert a .\ at the beginning to avoid converting relative paths
- // like a/../c: into c:.
- if runtime.GOOS == "windows" && out.w == 0 && out.volLen == 0 && r != 0 {
- for i := r; i < n && !os.IsPathSeparator(path[i]); i++ {
- if path[i] == ':' {
- out.append('.')
- out.append(Separator)
- break
- }
- }
- }
// copy element
for ; r < n && !os.IsPathSeparator(path[r]); r++ {
out.append(path[r])
@@ -170,6 +163,21 @@ func Clean(path string) string {
out.append('.')
}
+ if runtime.GOOS == "windows" && out.volLen == 0 && out.buf != nil {
+ // If a ':' appears in the path element at the start of a Windows path,
+ // insert a .\ at the beginning to avoid converting relative paths
+ // like a/../c: into c:.
+ for _, c := range out.buf {
+ if os.IsPathSeparator(c) {
+ break
+ }
+ if c == ':' {
+ out.prepend('.', Separator)
+ break
+ }
+ }
+ }
+
return FromSlash(out.string())
}
diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go
index 697bcc672d..1a2e53a795 100644
--- a/src/path/filepath/path_test.go
+++ b/src/path/filepath/path_test.go
@@ -66,6 +66,7 @@ var cleantests = []PathTest{
{"/abc/def/../../..", "/"},
{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
{"/../abc", "/abc"},
+ {"a/../b:/../../c", `../c`},
// Combinations
{"abc/./../def", "def"},
@@ -88,6 +89,7 @@ var wincleantests = []PathTest{
{`c:\abc\def\..\..`, `c:\`},
{`c:\..\abc`, `c:\abc`},
{`c:..\abc`, `c:..\abc`},
+ {`c:\b:\..\..\..\d`, `c:\d`},
{`\`, `\`},
{`/`, `\`},
{`\\i\..\c$`, `\\i\..\c$`},
@@ -168,6 +170,7 @@ var islocaltests = []IsLocalTest{
{"a/", true},
{"a/.", true},
{"a/./b/./c", true},
+ {`a/../b:/../../c`, false},
}
var winislocaltests = []IsLocalTest{
@@ -379,6 +382,7 @@ var winjointests = []JoinTest{
{[]string{`\\a`, `b`, `c`}, `\\a\b\c`},
{[]string{`\\a\`, `b`, `c`}, `\\a\b\c`},
{[]string{`//`, `a`}, `\\a`},
+ {[]string{`a:\b\c`, `x\..\y:\..\..\z`}, `a:\b\z`},
}
func TestJoin(t *testing.T) {