Opened 5 years ago
Last modified 5 years ago
#13189 new Bugs
copy throws exception from a function defined as noexcept
Reported by: | Owned by: | Beman Dawes | |
---|---|---|---|
Milestone: | To Be Determined | Component: | filesystem |
Version: | Boost 1.63.0 | Severity: | Problem |
Keywords: | Cc: |
Description
When copy
fails because access to the file specified by from
is denied, the corresponding exception reaches a function defined as noexcept
. Stack trace:
bool <anon. namespace>::error(err_t error_num, const path& p1, const path& p2, error_code* ec, const char* message) void detail::copy_file(const path& from, const path& to, copy_option option, error_code* ec) void copy_file(const path& from, const path& to, BOOST_SCOPED_ENUM(copy_option) option, system::error_code& ec) BOOST_NOEXCEPT void detail::copy(const path& from, const path& to, system::error_code* ec) void copy(const path& from, const path& to)
The exception is thrown from error
, and isn't caught anywhere along the calling path. The problem is that copy_file
is defined as noexcept
(BOOST_NOEXCEPT
to be precise, but it is resolved as noexcept
under a C++11 compliant compiler), and doesn't handle the exception either, which causes program termination by implicitly calling std::terminate
.
Change History (4)
comment:1 by , 5 years ago
comment:3 by , 5 years ago
The root cause of the problem is that copy(from, to)
calls detail::copy(from, to)
but the declaration of detail::copy
is:
void copy(const path& from, const path& to, system::error_code* ec=0);
That way ec
will be a null pointer. The next call in the chain in case of a regular file will be copy_file(from, to, fs::copy_option::fail_if_exists, *ec)
Looking at the declaration of copy_file
void copy_file(const path& from, const path& to, // See ticket #2925 BOOST_SCOPED_ENUM(copy_option) option, system::error_code& ec) BOOST_NOEXCEPT
we can see that ec
will be a null reference. The next call will be detail::copy_file(from, to, static_cast<detail::copy_option>(option), &ec)
which finally calls the function error
:
bool error(err_t error_num, error_code* ec, const char* message) { if (!error_num) { if (ec != 0) ec->clear(); } else { // error if (ec == 0) BOOST_FILESYSTEM_THROW(filesystem_error(message, error_code(error_num, system_category()))); else ec->assign(error_num, system_category()); } return error_num != 0; }
which will throw an exception because ec
is a null pointer. This exception will propagate up to
void copy_file(const path& from, const path& to, // See ticket #2925 BOOST_SCOPED_ENUM(copy_option) option, system::error_code& ec) BOOST_NOEXCEPT
which is a noexcept
function.
comment:4 by , 5 years ago
After running a few tests not just filesystem::copy_file
but filesystem::copy_symlink
and filesystem::copy_directory
functions are affected depending on what kind of file from
points to. All of these errors can easily be fixed by rewriting filesystem::detail::copy
to call functions defined in filesystem::detail
namespace instead of filesystem
namespace. Because I was unable to attach a patch file to the ticket I'm pasting the patched filesystem::detail::copy
function here:
BOOST_FILESYSTEM_DECL void copy(const path& from, const path& to, system::error_code* ec) { file_status s(symlink_status(from, *ec)); if (ec != 0 && *ec) return; if(is_symlink(s)) { copy_symlink(from, to, ec); } else if(is_directory(s)) { copy_directory(from, to, ec); } else if(is_regular_file(s)) { copy_file(from, to, fs::detail::copy_option::fail_if_exists, ec); } else { if (ec == 0) BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy", from, to, error_code(BOOST_ERROR_NOT_SUPPORTED, system_category()))); ec->assign(BOOST_ERROR_NOT_SUPPORTED, system_category()); } }
i want to work on this bug