[libcxx-commits] [libcxx] [libc++] Make std::filesystem::canonical throw when given empty path (PR #77223)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jan 7 00:30:55 PST 2024


https://github.com/Yuki-cpp updated https://github.com/llvm/llvm-project/pull/77223

>From 19f5fb22944f79c672e192c75b90b3d94ad542c8 Mon Sep 17 00:00:00 2001
From: Leo <leo.ghafari at gmail.com>
Date: Sun, 7 Jan 2024 10:46:46 +0900
Subject: [PATCH 1/2] [libc++] Make std::filesystem::canonical throw when given
 empty path

Adds a check for empty paths in std::filesystem::canonical and raise an
error accordingly. Since std::filesystem::weakly_canonical uses this function
and should not raise an error when given an empty path, it was updated
to return an empty path instead of the results of canonical.
---
 libcxx/src/filesystem/operations.cpp          |  6 +++--
 .../fs.op.canonical/canonical.pass.cpp        | 26 +++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 6bee340e0d15c8..8f5b70a071373d 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -82,6 +82,8 @@ path __canonical(path const& orig_p, error_code* ec) {
   path cwd;
   ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
 
+  if (orig_p.empty())
+    return err.report(capture_errno());
   path p = __do_absolute(orig_p, &cwd, ec);
 #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API)
   std::unique_ptr<path::value_type, decltype(&::free)> hold(detail::realpath(p.c_str(), nullptr), &::free);
@@ -912,7 +914,7 @@ path __weakly_canonical(const path& p, error_code* ec) {
   ErrorHandler<path> err("weakly_canonical", ec, &p);
 
   if (p.empty())
-    return __canonical("", ec);
+    return __current_path(ec);
 
   path result;
   path tmp;
@@ -935,7 +937,7 @@ path __weakly_canonical(const path& p, error_code* ec) {
     --PP;
   }
   if (PP.State == PathParser::PS_BeforeBegin)
-    result = __canonical("", ec);
+    result = __current_path(ec);
   if (ec)
     ec->clear();
   if (DNEParts.empty())
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp
index 0098fe8ee698ef..000fb47096ba19 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp
@@ -92,6 +92,31 @@ static void test_dne_path()
     }
 }
 
+static void test_empty_path()
+{
+    std::error_code ec = GetTestEC();
+    {
+        const path ret = canonical(path{}, ec);
+        assert(ec != GetTestEC());
+        assert(ec);
+        assert(ret == path{});
+    }
+    {
+        TEST_THROWS_TYPE(filesystem_error, canonical(path{}));
+    }
+
+    ec = GetTestEC();
+    {
+        const path ret = canonical("", ec);
+        assert(ec != GetTestEC());
+        assert(ec);
+        assert(ret == path{});
+    }
+    {
+        TEST_THROWS_TYPE(filesystem_error, canonical(""));
+    }
+}
+
 static void test_exception_contains_paths()
 {
 #ifndef TEST_HAS_NO_EXCEPTIONS
@@ -121,6 +146,7 @@ int main(int, char**) {
     signature_test();
     test_canonical();
     test_dne_path();
+    test_empty_path();
     test_exception_contains_paths();
 
     return 0;

>From 614ec4b47f0c986092a95fc64e9f9f1b59de3f84 Mon Sep 17 00:00:00 2001
From: Leo <leo.ghafari at gmail.com>
Date: Sun, 7 Jan 2024 17:25:26 +0900
Subject: [PATCH 2/2] fixup! [libc++] Make std::filesystem::canonical throw
 when given empty path

---
 .../fs.op.canonical/canonical.pass.cpp        | 39 ++++++++-----------
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp
index 000fb47096ba19..c5935f20510844 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp
@@ -92,29 +92,24 @@ static void test_dne_path()
     }
 }
 
-static void test_empty_path()
-{
-    std::error_code ec = GetTestEC();
-    {
-        const path ret = canonical(path{}, ec);
-        assert(ec != GetTestEC());
-        assert(ec);
-        assert(ret == path{});
-    }
-    {
-        TEST_THROWS_TYPE(filesystem_error, canonical(path{}));
-    }
+static void test_empty_path() {
+  std::error_code ec = GetTestEC();
+  {
+    const path ret = canonical(path{}, ec);
+    assert(ec != GetTestEC());
+    assert(ec);
+    assert(ret == path{});
+  }
+  { TEST_THROWS_TYPE(filesystem_error, canonical(path{})); }
 
-    ec = GetTestEC();
-    {
-        const path ret = canonical("", ec);
-        assert(ec != GetTestEC());
-        assert(ec);
-        assert(ret == path{});
-    }
-    {
-        TEST_THROWS_TYPE(filesystem_error, canonical(""));
-    }
+  ec = GetTestEC();
+  {
+    const path ret = canonical("", ec);
+    assert(ec != GetTestEC());
+    assert(ec);
+    assert(ret == path{});
+  }
+  { TEST_THROWS_TYPE(filesystem_error, canonical("")); }
 }
 
 static void test_exception_contains_paths()



More information about the libcxx-commits mailing list