Re: [Boost-bugs] [Boost C++ Libraries] #12578: Crash with boost::filesystem's directory_iterator and recursive_directory_iterator

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #12578: Crash with boost::filesystem's directory_iterator and recursive_directory_iterator
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-11-21 22:32:39


#12578: Crash with boost::filesystem's directory_iterator and
recursive_directory_iterator
-------------------------------+------------------------
  Reporter: anonymous | Owner: bemandawes
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: filesystem
   Version: Boost 1.61.0 | Severity: Problem
Resolution: | Keywords:
-------------------------------+------------------------

Comment (by mlimber@…):

 Ah, but but but.....

 Your example still crashes if the folder you run in has one entry only, as
 here:

 {{{#!cpp
 #include <boost/filesystem.hpp>
 #include <boost/range/iterator_range.hpp>
 #include <iostream>

 namespace fs = boost::filesystem;

 void process_iter(fs::recursive_directory_iterator myIter)
 {
   std::cout << *(myIter++) << std::endl;
 }

 int main()
 {
   try
   {
     // Move to a folder with only one entry
     fs::create_directories( "dir/dir2" );
     fs::current_path( fs::current_path() / "dir" );

     auto iter = fs::recursive_directory_iterator{ "." };
     const auto end = fs::recursive_directory_iterator{};
     process_iter( iter );

     std::cout << (iter != end) << std::endl;

     for( const auto& entry : boost::make_iterator_range( iter, end ) )
     // OR for( const auto& entry : iter )
     {
       std::cout << entry << "\n";
     }

     // OR
     // while( iter != end )
     // {
     // std::cout << "Post: " << *iter << "\n";
     // ++iter;
     // }
   }
   catch( ... )
   {
     std::cerr << "Exception.\n";
   }
 }
 }}}

 See it fail: coliru.stacked-crooked.com/a/3c4e31bbef79cc6b

 Note that we are NOT dereferencing {{{iter}}} after the call to
 {{{process_iter()}}}. The problem is that {{{iter}}} is itself invalidated
 once the {{{myIter}}} copy is advanced to the end. But as far as I can
 tell, there is NO WAY to tell whether {{{iter}}} has been invalidated or
 can still be used. Adding a print statement as I did after the call to
 {{{process_iter()}}} indicates that the iterator is not equal to end and
 is therefore valid, but that is wrong!

 So at the very least, your suggested usage invokes undefined behavior.

 Compare how istream_iterator behaves: coliru.stacked-
 crooked.com/a/e5988c4626f2c339

 Is that lesson here that input iterators should be considered move-only,
 not copyable, because copies are too prone to error in untested
 circumstances (like having only one file, above)? Should that be codified
 in the standard or at least coding standards?

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/12578#comment:9>
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