]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Ignore trailing slash in prefix in util::path_starts_with
authorJoel Rosdahl <joel@rosdahl.net>
Tue, 5 Nov 2024 20:22:06 +0000 (21:22 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 7 Nov 2024 10:22:28 +0000 (11:22 +0100)
Fixes #1265.

src/ccache/util/path.cpp
unittest/test_util_path.cpp

index 282cca0c98ad04e9b0a7684825cac2062111af6b..93f703b9a9ccfd6e357964d9764ead05e4da3701 100644 (file)
@@ -128,14 +128,24 @@ path_starts_with(const fs::path& path, const fs::path& prefix)
   // Note: Not all paths on Windows are case insensitive, but for our purposes
   // (checking whether a path is below the base directory) users will expect
   // them to be.
-  fs::path p1 = util::to_lowercase(path.string());
-  fs::path p2 = util::to_lowercase(prefix.string());
+  fs::path p1 = util::to_lowercase(path.lexically_normal().string());
+  fs::path p2 = util::to_lowercase(prefix.lexically_normal().string());
 #else
   const fs::path& p1 = path;
   const fs::path& p2 = prefix;
 #endif
-  return std::mismatch(p1.begin(), p1.end(), p2.begin(), p2.end()).second
-         == p2.end();
+
+  // Skip empty part at the end that originates from a trailing slash.
+  auto p2_end = p2.end();
+  if (!p2.empty()) {
+    --p2_end;
+    if (!p2_end->empty()) {
+      ++p2_end;
+    }
+  }
+
+  return std::mismatch(p1.begin(), p1.end(), p2.begin(), p2_end).second
+         == p2_end;
 }
 
 } // namespace util
index a3cbbaf13550fa9a45cdce1220c960229eb56acc..83425c4cabeba1fb26c3366fb8e7b94ecae8acab 100644 (file)
@@ -103,6 +103,17 @@ TEST_CASE("util::make_relative_path")
   {
     CHECK(make_relative_path(actual_cwd, apparent_cwd, actual_cwd + "/x")
           == "x");
+    CHECK(make_relative_path(actual_cwd, apparent_cwd, actual_cwd + "/d")
+          == "d");
+    CHECK(make_relative_path(
+            actual_cwd + "/", apparent_cwd + "/", actual_cwd + "/d")
+          == "d");
+    CHECK(make_relative_path(
+            actual_cwd + "/", apparent_cwd + "/", actual_cwd + "/d/")
+          == "d");
+    CHECK(make_relative_path(
+            actual_cwd + "/", apparent_cwd + "/", actual_cwd + "/d/.")
+          == "d");
 #ifdef _WIN32
     CHECK(make_relative_path(actual_cwd, apparent_cwd, actual_cwd + "\\x")
           == "x");
@@ -131,16 +142,22 @@ TEST_CASE("util::path_starts_with")
   CHECK(util::path_starts_with("", ""));
   CHECK(!util::path_starts_with("", "/"));
   CHECK(util::path_starts_with("/foo/bar", "/foo"));
+  CHECK(util::path_starts_with("/foo/bar/", "/foo"));
+  CHECK(util::path_starts_with("/foo/bar", "/foo/"));
   CHECK(!util::path_starts_with("/batz/bar", "/foo"));
   CHECK(!util::path_starts_with("/foo/bar", "/foo/baz"));
   CHECK(!util::path_starts_with("/beh/foo", "/foo"));
 #ifdef _WIN32
   CHECK(util::path_starts_with("C:/foo/bar", "C:\\foo"));
+  CHECK(util::path_starts_with("C:/foo/bar\\", "C:\\foo"));
+  CHECK(util::path_starts_with("C:/foo/bar", "C:\\foo\\"));
   CHECK(util::path_starts_with("C:/foo/bar", "C:\\\\foo"));
   CHECK(util::path_starts_with("C:\\foo\\bar", "C:/foo"));
   CHECK(util::path_starts_with("C:\\\\foo\\\\bar", "C:/foo"));
   CHECK(util::path_starts_with("C:/FOO/BAR", "c:\\foo"));
   CHECK(util::path_starts_with("c:/foo/bar", "C:\\FOO"));
+  CHECK(util::path_starts_with("c:/foo/bar/", "C:\\FOO"));
+  CHECK(util::path_starts_with("c:/foo/bar", "C:\\FOO\\"));
   CHECK(!util::path_starts_with("C:\\foo\\bar", "/foo/baz"));
   CHECK(!util::path_starts_with("C:\\foo\\bar", "C:/foo/baz"));
   CHECK(!util::path_starts_with("C:\\beh\\foo", "/foo"));