From 1303b3ed7d731dac4754eb3a6e1a370b9cf985dc Mon Sep 17 00:00:00 2001 From: Brad Spencer Date: Wed, 13 Sep 2017 10:19:46 -0300 Subject: [PATCH 1/2] Fix remove_all(path, ec) to not throw filesystem_error via ++itr According to the documentation, uintmax_t remove_all(const path& p, system::error_code& ec) is not supposed to throw filesystem_error. However, when the directory_iterator used in the loop inside the implementation helper function remove_all_aux() is incremented, it's not done in a way that considers the ec argument. So, when incrementing the iterator fails, the operator++() on the directory_iterator throws, which leads to remove_all() incorrectly throwing. To fix this, it seems that one can take the same approach as the recent changes for Fix #7307 https://github.com/boostorg/filesystem/commit/4e4374336c640c2717f6a1b168406e11bdf7d6f1 and replace the ++itr call in the loop with an explicit call to either directory_iterator::increment(system::error_code& ec) whenever an ec argument is in effect. This should prevent remove_all() from throwing in such cases and thus allow it to conform to its interface specification. --- src/operations.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/operations.cpp b/src/operations.cpp index 4114e02a1..69f7e955f 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -395,7 +395,7 @@ namespace } else itr = fs::directory_iterator(p); - for (; itr != end_dir_itr; ++itr) + while (itr != end_dir_itr) { fs::file_type tmp_type = query_file_type(itr->path(), ec); if (ec != 0 && *ec) @@ -403,6 +403,18 @@ namespace count += remove_all_aux(itr->path(), tmp_type, ec); if (ec != 0 && *ec) return count; + + // Don't let ++itr throw when reporting errors via ec. + if (ec != 0) + { + itr.increment(*ec); + if (*ec) + return count; + } + else + { + ++itr; + } } } remove_file_or_directory(p, type, ec); From aa2a58a4e63f7c433423c17546bc738c9a46de22 Mon Sep 17 00:00:00 2001 From: Brad Spencer Date: Thu, 12 Oct 2017 16:12:07 -0300 Subject: [PATCH 2/2] Fix dereference of ec pointer in directory_iterator_constructor that can be null by selecting it.increment() or ++it appropriately for throwing or non-throwing behaviour. --- src/operations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operations.cpp b/src/operations.cpp index 69f7e955f..6b480d429 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -2406,7 +2406,7 @@ namespace detail && (filename.size()== 1 || (filename[1] == dot && filename.size()== 2))) - { it.increment(*ec); } + { ec ? it.increment(*ec) : ++it; } } }