aboutsummaryrefslogtreecommitdiff
path: root/src/path/filepath/path.go
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2022-11-09 17:49:44 -0800
committerDamien Neil <dneil@google.com>2022-11-16 23:17:58 +0000
commit6d0bf438e302afcb0db5422ea2da59d1995e08c1 (patch)
treeb931b814d4a959903ea32c37ec69d92fcb0ca7c5 /src/path/filepath/path.go
parentfd59c6cf8cb600f2911864948303016581abf016 (diff)
downloadgo-6d0bf438e302afcb0db5422ea2da59d1995e08c1.tar.xz
path/filepath: add IsLocal
IsLocal reports whether a path lexically refers to a location contained within the directory in which it is evaluated. It identifies paths that are absolute, escape a directory with ".." elements, and (on Windows) paths that reference reserved device names. For #56219. Change-Id: I35edfa3ce77b40b8e66f1fc8e0ff73cfd06f2313 Reviewed-on: https://go-review.googlesource.com/c/go/+/449239 Run-TryBot: Damien Neil <dneil@google.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Joedian Reid <joedian@golang.org>
Diffstat (limited to 'src/path/filepath/path.go')
-rw-r--r--src/path/filepath/path.go40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
index c5c54fc9a5..a6578cbb72 100644
--- a/src/path/filepath/path.go
+++ b/src/path/filepath/path.go
@@ -172,6 +172,46 @@ func Clean(path string) string {
return FromSlash(out.string())
}
+// IsLocal reports whether path, using lexical analysis only, has all of these properties:
+//
+// - is within the subtree rooted at the directory in which path is evaluated
+// - is not an absolute path
+// - is not empty
+// - on Windows, is not a reserved name such as "NUL"
+//
+// If IsLocal(path) returns true, then
+// Join(base, path) will always produce a path contained within base and
+// Clean(path) will always produce an unrooted path with no ".." path elements.
+//
+// IsLocal is a purely lexical operation.
+// In particular, it does not account for the effect of any symbolic links
+// that may exist in the filesystem.
+func IsLocal(path string) bool {
+ return isLocal(path)
+}
+
+func unixIsLocal(path string) bool {
+ if IsAbs(path) || path == "" {
+ return false
+ }
+ hasDots := false
+ for p := path; p != ""; {
+ var part string
+ part, p, _ = strings.Cut(p, "/")
+ if part == "." || part == ".." {
+ hasDots = true
+ break
+ }
+ }
+ if hasDots {
+ path = Clean(path)
+ }
+ if path == ".." || strings.HasPrefix(path, "../") {
+ return false
+ }
+ return true
+}
+
// ToSlash returns the result of replacing each separator character
// in path with a slash ('/') character. Multiple separators are
// replaced by multiple slashes.