[libcxx-commits] [libcxx] [libc++] Fix filesystem::remove_all bug with read-only nested directory (PR #197104)
Jake Egan via libcxx-commits
libcxx-commits at lists.llvm.org
Mon May 25 13:17:23 PDT 2026
https://github.com/jakeegan updated https://github.com/llvm/llvm-project/pull/197104
>From a429230b2471fa6ff4b84d83fc60dcc40b109dc7 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 12 May 2026 00:14:03 -0400
Subject: [PATCH 1/6] [libc++] Fix filesystem::remove_all bug with read-only
nested directory
---
libcxx/src/filesystem/operations.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 745db87ce3736..6afcec07b374d 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -904,6 +904,9 @@ uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) {
break; // we're done iterating through the directory
} else {
count += remove_all_impl(fd, str, ec);
+ // If there's an error removing the child, return immediately to preserve the error code.
+ if (ec)
+ return count;
}
}
>From 9c04e74b3a2d7cd5116798e3035be53de332e920 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Fri, 15 May 2026 10:58:36 -0400
Subject: [PATCH 2/6] Add test
---
.../bad_perms_parent.pass.cpp | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
diff --git a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
new file mode 100644
index 0000000000000..1c129e9c08c39
--- /dev/null
+++ b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: no-filesystem
+
+// Verify that remove_all reports the correct error (permission_denied)
+// when the parent directory has insufficient permissions.
+
+// <filesystem>
+
+#include <filesystem>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.h"
+namespace fs = std::filesystem;
+using namespace fs;
+
+int main(int, char**) {
+ scoped_test_env env;
+
+ const path parent_dir = env.create_dir("parent");
+ const path child_dir = env.create_dir(parent_dir / "child");
+ permissions(parent_dir, perms::owner_read | perms::owner_write);
+
+ const auto BadRet = static_cast<std::uintmax_t>(-1);
+ std::error_code ec;
+ assert(fs::remove_all(parent_dir, ec) == BadRet);
+ assert(ec == std::errc::permission_denied);
+
+ permissions(parent_dir, perms::owner_all);
+ return 0;
+}
>From a4182b96d5378b144773ac26f826dad0a501cc07 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Fri, 15 May 2026 11:03:25 -0400
Subject: [PATCH 3/6] Fix formatting
---
.../bad_perms_parent.pass.cpp | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
index 1c129e9c08c39..f1bd148a94e75 100644
--- a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
+++ b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
@@ -22,17 +22,17 @@ namespace fs = std::filesystem;
using namespace fs;
int main(int, char**) {
- scoped_test_env env;
+ scoped_test_env env;
- const path parent_dir = env.create_dir("parent");
- const path child_dir = env.create_dir(parent_dir / "child");
- permissions(parent_dir, perms::owner_read | perms::owner_write);
+ const path parent_dir = env.create_dir("parent");
+ const path child_dir = env.create_dir(parent_dir / "child");
+ permissions(parent_dir, perms::owner_read | perms::owner_write);
- const auto BadRet = static_cast<std::uintmax_t>(-1);
- std::error_code ec;
- assert(fs::remove_all(parent_dir, ec) == BadRet);
- assert(ec == std::errc::permission_denied);
+ const auto BadRet = static_cast<std::uintmax_t>(-1);
+ std::error_code ec;
+ assert(fs::remove_all(parent_dir, ec) == BadRet);
+ assert(ec == std::errc::permission_denied);
- permissions(parent_dir, perms::owner_all);
- return 0;
+ permissions(parent_dir, perms::owner_all);
+ return 0;
}
>From 2bb7b5a905c12cffbab7738915426ebd00042d35 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Fri, 15 May 2026 13:54:12 -0400
Subject: [PATCH 4/6] Unsupport windows
---
.../fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
index f1bd148a94e75..a8f86af127e7b 100644
--- a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
+++ b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
@@ -9,6 +9,8 @@
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: windows
+
// Verify that remove_all reports the correct error (permission_denied)
// when the parent directory has insufficient permissions.
>From 98aa585a8d4b2dbdec9229c72f813879c77de228 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Mon, 25 May 2026 10:44:57 -0400
Subject: [PATCH 5/6] XFAIL for apple configs using older library versions
---
.../fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
index a8f86af127e7b..fbdfa15da38a6 100644
--- a/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
+++ b/libcxx/test/libcxx/input.output/filesystems/fs.op.funcs/fs.op.remove_all/bad_perms_parent.pass.cpp
@@ -10,6 +10,7 @@
// UNSUPPORTED: no-filesystem
// UNSUPPORTED: windows
+// XFAIL: using-built-library-before-llvm-23
// Verify that remove_all reports the correct error (permission_denied)
// when the parent directory has insufficient permissions.
>From 519c311e74adbea9b756ce7d3bde6c7b3a90e16b Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Mon, 25 May 2026 16:16:43 -0400
Subject: [PATCH 6/6] Add 23 feature
---
libcxx/utils/libcxx/test/features/availability.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/utils/libcxx/test/features/availability.py b/libcxx/utils/libcxx/test/features/availability.py
index 39c6cf45a1708..c345ed244fe64 100644
--- a/libcxx/utils/libcxx/test/features/availability.py
+++ b/libcxx/utils/libcxx/test/features/availability.py
@@ -128,7 +128,7 @@
# a libc++ flavor that enables availability markup. Similarly, a test could fail when
# run against the system library of an older version of FreeBSD, even though FreeBSD
# doesn't provide availability markup at the time of writing this.
-for version in ("12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22"):
+for version in ("12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"):
features.append(
Feature(
name="using-built-library-before-llvm-{}".format(version),
More information about the libcxx-commits
mailing list