[Boost-bugs] [Boost C++ Libraries] #12254: NULL reference to error_code passing to noexcept functions caused std::terminate

Subject: [Boost-bugs] [Boost C++ Libraries] #12254: NULL reference to error_code passing to noexcept functions caused std::terminate
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-06-07 08:27:29


#12254: NULL reference to error_code passing to noexcept functions caused
std::terminate
------------------------------+-------------------------
 Reporter: aerisnju@… | Owner: bemandawes
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: filesystem
  Version: Boost 1.61.0 | Severity: Showstopper
 Keywords: noexcept |
------------------------------+-------------------------
 With compilers that support noexcept, the following simple code may end up
 in std::terminate():

 {{{
 #include <boost/filesystem.hpp>

 int main(int argc, char *argv[]) {
     try {
         boost::filesystem::path p(argv[0]);

         copy(p, p); // EEXIST, then std::terminate
     } catch (...) {}

     return 0;
 }
 }}}

 This is because the noexcept function copy_file() has received a NULL
 reference, which causes one of its subroutines throws an exception. Since
 copy_file() is noexcept and it throws exceptions, the std::terminate() is
 called.

 The call stack is (functions are called from bottom to top):

 {{{
 noexcept? function
 -----------------------------------------------------
 false error(unsigned long error_num, const
 boost::filesystem::path & p1, const boost::filesystem::path & p2,
 boost::system::error_code * ec, const char * message)
 false detail::copy_file(const boost::filesystem::path & from,
 const boost::filesystem::path & to, boost::filesystem::detail::copy_option
 option, boost::system::error_code * ec)
 true copy_file(const boost::filesystem::path & from, const
 boost::filesystem::path & to, boost::filesystem::copy_option option,
 boost::system::error_code & ec)
 false detail::copy(const boost::filesystem::path & from, const
 boost::filesystem::path & to, boost::system::error_code * ec)
 false copy(const boost::filesystem::path & from, const
 boost::filesystem::path & to)
 false main(int argc, char * * argv)
 }}}

 The function copy() calls detail::copy() without providing the ec
 parameter, so ec in detail::copy() is using the default value 0.
 detail::copy() then calls copy_file(), passing *ec as its parameter. Since
 ec in detail:copy() is NULL, copy_file() will receive a NULL reference. It
 then use &ec(that is NULL) to call detail::copy_file(). Since the target
 file exists, detail::copy_file() will generates EEXIST. Then an exception
 will be thrown from error(). The exception will be passed through the call
 stack until it reaches copy_file(). copy_file() is noexcept so it cannot
 throw exceptions. Then std::terminate() is called.

 There may be other similar situations apart from this case in
 Boost.Filesystem. I think the current workaround is removing the
 BOOST_NOEXCEPT from these functions. For a complete solution, the
 functions may need careful reviews.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/12254>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:20 UTC