From 216720de55359828c2dc915b50e6ead44e00cd15 Mon Sep 17 00:00:00 2001 From: Beman Date: Wed, 23 Nov 2016 09:58:43 -0500 Subject: [PATCH] Fix #12495, create_directories() crashes when passed empty string as path, from Samantha Ritter. Also affected create_directory(). Charles Olivi submitted a pull request with some particularly helpful test cases. --- doc/release_history.html | 4 ++++ src/operations.cpp | 15 +++++++++++++- test/operations_test.cpp | 43 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/doc/release_history.html b/doc/release_history.html index 074fc29ac..840c79ec0 100644 --- a/doc/release_history.html +++ b/doc/release_history.html @@ -62,6 +62,10 @@

1.63.0

recursive_directory_iterator equality testing has existed more than a dozen years. Nowadays test driven development would likely have detected the problem in early development. Sigh. +
  • Fix #12495, + create_directories() crashes when passed empty string as path, + from Samantha Ritter. Also affected create_directory(). Charles + Olivi submitted a pull request with some particularly helpful test cases.
  • Fix broken link to #7506 in 1.60.0 Release History (Daniel Krügler).
  • Refactor push_directory()internal logic so it is easier to diff --git a/src/operations.cpp b/src/operations.cpp index f34b07612..1b3298e3a 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -937,6 +937,17 @@ namespace detail BOOST_FILESYSTEM_DECL bool create_directories(const path& p, system::error_code* ec) { + if (p.empty()) + { + if (ec == 0) + BOOST_FILESYSTEM_THROW(filesystem_error( + "boost::filesystem::create_directories", p, + system::errc::make_error_code(system::errc::invalid_argument))); + else + ec->assign(system::errc::invalid_argument, system::generic_category()); + return false; + } + if (p.filename_is_dot() || p.filename_is_dot_dot()) return create_directories(p.parent_path(), ec); @@ -990,7 +1001,8 @@ namespace detail // attempt to create directory failed int errval(BOOST_ERRNO); // save reason for failure error_code dummy; - if (errval == BOOST_ERROR_ALREADY_EXISTS && is_directory(p, dummy)) + + if (is_directory(p, dummy)) { if (ec != 0) ec->clear(); @@ -1003,6 +1015,7 @@ namespace detail p, error_code(errval, system_category()))); else ec->assign(errval, system_category()); + return false; } diff --git a/test/operations_test.cpp b/test/operations_test.cpp index 09c28e036..400b12bd8 100644 --- a/test/operations_test.cpp +++ b/test/operations_test.cpp @@ -1038,8 +1038,26 @@ namespace { cout << "create_directory_tests..." << endl; - BOOST_TEST(!fs::create_directory(".")); - BOOST_TEST(!fs::create_directory("..")); + error_code ec; + BOOST_TEST(!fs::create_directory("", ec)); + BOOST_TEST(ec); + + ec.clear(); + BOOST_TEST(!fs::create_directory(" ", ec)); + BOOST_TEST(ec); + + ec.clear(); + BOOST_TEST(!fs::create_directory("/", ec)); + BOOST_TEST(!ec); + BOOST_TEST(fs::is_directory("/")); // this is a post-condition + + ec.clear(); + BOOST_TEST(!fs::create_directory(".", ec)); + BOOST_TEST(!ec); + + ec.clear(); + BOOST_TEST(!fs::create_directory("..", ec)); + BOOST_TEST(!ec); // create a directory, then check it for consistency // take extra care to report problems, since if this fails @@ -1114,7 +1132,25 @@ namespace { cout << "create_directories_tests..." << endl; - BOOST_TEST(!fs::create_directories("/")); + error_code ec; + BOOST_TEST(!fs::create_directories("", ec)); + BOOST_TEST(ec); + + ec.clear(); + BOOST_TEST(!fs::create_directories(" ", ec)); + BOOST_TEST(ec); + + ec.clear(); + BOOST_TEST(!fs::create_directories("/", ec)); + BOOST_TEST(!ec); + + ec.clear(); + BOOST_TEST(!fs::create_directories(".", ec)); + BOOST_TEST(ec); + + ec.clear(); + BOOST_TEST(!fs::create_directories("..", ec)); + BOOST_TEST(ec); fs::path p = dir / "level1/." / "level2/./.." / "level3/"; // trailing "/.", "/./..", and "/" in the above elements test ticket #7258 and @@ -1128,7 +1164,6 @@ namespace if (fs::exists("/permissions_test")) { - error_code ec; BOOST_TEST(!fs::create_directories("/permissions_test", ec)); BOOST_TEST(!fs::create_directories("/permissions_test/another_directory", ec)); BOOST_TEST(ec);