From f9cb859d45887f3f9aafdd535df0fc65718651af Mon Sep 17 00:00:00 2001 From: Laszlo Csomor Date: Tue, 24 Apr 2018 05:52:37 -0700 Subject: runfiles: rlocation() checks if arg is normalized rlocation() now validates that the path argument is normalized, i.e. contains none of: - current directory references (".") - uplevel references ("..") - double slash ("//") This helps avoiding a bug similar to https://github.com/bazelbuild/bazel/pull/5083. See https://github.com/bazelbuild/bazel/pull/4460 Change-Id: Ia73fa2df1eae86fc7084162c24e144129672742d Closes #5085. Change-Id: Ia73fa2df1eae86fc7084162c24e144129672742d PiperOrigin-RevId: 194074072 --- src/tools/runfiles/runfiles.cc | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'src/tools/runfiles/runfiles.cc') diff --git a/src/tools/runfiles/runfiles.cc b/src/tools/runfiles/runfiles.cc index b1a870558b..801e44e374 100644 --- a/src/tools/runfiles/runfiles.cc +++ b/src/tools/runfiles/runfiles.cc @@ -42,6 +42,36 @@ using std::vector; namespace { +bool starts_with(const string& s, const string& prefix) { + if (prefix.empty()) { + return true; + } + if (s.empty()) { + return false; + } + return s.find(prefix) == 0; +} + +bool contains(const string& s, const string& substr) { + if (substr.empty()) { + return true; + } + if (s.empty()) { + return false; + } + return s.find(substr) != string::npos; +} + +bool ends_with(const string& s, const string& suffix) { + if (suffix.empty()) { + return true; + } + if (s.empty()) { + return false; + } + return s.rfind(suffix) == s.size() - suffix.size(); +} + class RunfilesImpl : public Runfiles { public: static Runfiles* Create(const string& argv0, @@ -163,9 +193,10 @@ bool IsAbsolute(const string& path) { return false; } char c = path.front(); - return (c == '/') || (path.size() >= 3 && - ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) && - path[1] == ':' && (path[2] == '\\' || path[2] == '/')); + return (c == '/' && (path.size() < 2 || path[1] != '/')) || + (path.size() >= 3 && + ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) && + path[1] == ':' && (path[2] == '\\' || path[2] == '/')); } string GetEnv(const string& key) { @@ -184,7 +215,9 @@ string GetEnv(const string& key) { } string RunfilesImpl::Rlocation(const string& path) const { - if (path.empty() || path.find("..") != string::npos) { + if (path.empty() || starts_with(path, "../") || contains(path, "/..") || + starts_with(path, "./") || contains(path, "/./") || + ends_with(path, "/.") || contains(path, "//")) { return std::move(string()); } if (IsAbsolute(path)) { -- cgit v1.2.3