diff options
author | Damien Neil <dneil@google.com> | 2023-08-08 14:07:08 -0700 |
---|---|---|
committer | Carlos Amedee <carlos@golang.org> | 2023-08-23 17:53:26 +0000 |
commit | 45b98bfb793923c539f9a959c3047d2e5fe2ebf0 (patch) | |
tree | a0b5798c077c0699cf78fea3085daf2a009230ab | |
parent | bac083a5847a53bb726f65d6e9c2aeb54066bcf0 (diff) | |
download | go-45b98bfb793923c539f9a959c3047d2e5fe2ebf0.tar.gz go-45b98bfb793923c539f9a959c3047d2e5fe2ebf0.zip |
[release-branch.go1.21] 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 #61868.
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/+/519655
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
-rw-r--r-- | src/path/filepath/path.go | 32 | ||||
-rw-r--r-- | src/path/filepath/path_test.go | 4 |
2 files changed, 24 insertions, 12 deletions
diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go index 9772de4342..ca1d8b3116 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] @@ -150,18 +155,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]) @@ -174,6 +167,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 3c78e415d2..621208d31e 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -67,6 +67,7 @@ var cleantests = []PathTest{ {"/abc/def/../../..", "/"}, {"abc/def/../../../ghi/jkl/../../../mno", "../../mno"}, {"/../abc", "/abc"}, + {"a/../b:/../../c", `../c`}, // Combinations {"abc/./../def", "def"}, @@ -89,6 +90,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$`}, @@ -169,6 +171,7 @@ var islocaltests = []IsLocalTest{ {"a/", true}, {"a/.", true}, {"a/./b/./c", true}, + {`a/../b:/../../c`, false}, } var winislocaltests = []IsLocalTest{ @@ -380,6 +383,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) { |