From f0b8768dbcf74bddedc32febd36732beb690b8aa Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 8 Aug 2023 14:07:08 -0700 Subject: [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 Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Quim Muntal (cherry picked from commit 6e43407931ee4acc204620a9fae59c7903164901) Reviewed-on: https://go-review.googlesource.com/c/go/+/519636 Reviewed-by: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov Reviewed-by: Damien Neil --- src/path/filepath/path.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'src/path/filepath/path.go') 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()) } -- cgit v1.3