https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78346

            Bug ID: 78346
           Summary: std::search with binary comparison predicate uses
                    invalid reference
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: reagentoo at gmail dot com
  Target Milestone: ---

When using std::search with binary comparison predicate, reference obtained
from iterator outlives iterator itself
which violates part 24.2.1 [iterator.requirements.general] of C++ standard:

10. Destruction of an iterator may invalidate pointers and references
previously obtained from that iterator.


The iterator is being dereferenced when converting binary predicate to unary
for later use in std::find_if:

template<typename _ForwardIterator1, typename _ForwardIterator2,
   typename _BinaryPredicate>
  _ForwardIterator1
  __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
     _BinaryPredicate  __predicate)
  {
  ...
  __first1 =
  std::__find_if(__first1, __last1,
      __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));

In this expression __first2 is passed to a _Iter_equals_iter wrapper (from
bits/predefined_ops.h):

template<typename _Iterator1>
struct _Iter_equals_iter
{
  typename std::iterator_traits<_Iterator1>::reference _M_ref; <-- reference
obtained from iterator

  _Iter_equals_iter(_Iterator1 __it1)
    : _M_ref(*__it1)
  { }

  template<typename _Iterator2>
    bool
    operator()(_Iterator2 __it2)
    { return *__it2 == _M_ref; }
};

Since _Iterator1 __it1 is passed to constructor by value, _M_ref can become
invalid after iterator leaves the scope;

This behavior can be observed when using std::search with
boost::filesystem::path, since 
boost::filesystem::path::iterator::dereference returns reference to a local
member:

http://melpon.org/wandbox/permlink/58aIbfJWeGgMKMdF

As a proposed solution, _Iter_equals_iter might store copy of iterator rather
than dereferenced
value.

Reply via email to