]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[release-branch.go1.20] path/filepath: don't drop .. elements when cleaning invalid...
authorDamien Neil <dneil@google.com>
Tue, 8 Aug 2023 21:07:08 +0000 (14:07 -0700)
committerCarlos Amedee <carlos@golang.org>
Wed, 23 Aug 2023 17:53:16 +0000 (17:53 +0000)
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>
src/path/filepath/path.go
src/path/filepath/path_test.go

index 32dd887998650bff7cff4456c1ea1e023fcaa522..326ca006b2452904c944fa418c9619ce513fa3e1 100644 (file)
@@ -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())
 }
 
index 697bcc672d73c300482e335eeee3523cd82721a8..1a2e53a795a9f710e2833a7e26bca80418b1b839 100644 (file)
@@ -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) {