Avoid using transform iterator as null pointer dereferences might happen

This commit is contained in:
Ion Gaztañaga
2024-05-23 22:53:14 +02:00
parent 8d17978748
commit c09c9b5804

View File

@ -25,15 +25,17 @@
#include <boost/container/container_fwd.hpp>
// container/detail
#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/transform_iterator.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/placement_new.hpp>
#include <boost/container/detail/iterator.hpp>
// intrusive
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/twin.hpp>
// move
#include <boost/move/utility_core.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
namespace boost {
namespace container {
@ -187,15 +189,100 @@ class basic_multiallocation_chain
}
};
template<class T>
struct cast_functor
template <class Iterator, class T>
class multialloc_iterator
: public boost::container::iterator
< typename Iterator::iterator_category
, T
, typename Iterator::difference_type
, T*
, T&
>
{
typedef typename dtl::add_reference<T>::type result_type;
template<class U>
result_type operator()(U &ptr) const
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
public:
inline explicit multialloc_iterator(const Iterator &it)
: m_it(it)
{}
inline explicit multialloc_iterator()
: m_it()
{}
//Constructors
inline multialloc_iterator& operator++()
{ increment(); return *this; }
inline multialloc_iterator operator++(int)
{
multialloc_iterator result (*this);
increment();
return result;
}
inline friend bool operator== (const multialloc_iterator& i, const multialloc_iterator& i2)
{ return i.equal(i2); }
inline friend bool operator!= (const multialloc_iterator& i, const multialloc_iterator& i2)
{ return !(i == i2); }
inline friend typename Iterator::difference_type operator- (const multialloc_iterator& i, const multialloc_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
inline multialloc_iterator& operator+=(typename Iterator::difference_type off)
{ this->advance(off); return *this; }
inline multialloc_iterator operator+(typename Iterator::difference_type off) const
{
multialloc_iterator other(*this);
other.advance(off);
return other;
}
inline friend multialloc_iterator operator+(typename Iterator::difference_type off, const multialloc_iterator& right)
{ return right + off; }
inline multialloc_iterator& operator-=(typename Iterator::difference_type off)
{ this->advance(-off); return *this; }
inline multialloc_iterator operator-(typename Iterator::difference_type off) const
{ return *this + (-off); }
inline T& operator*() const
{ return *this->operator->(); }
inline T* operator->() const
{ return static_cast<T*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(m_it))); }
inline Iterator & base()
{ return m_it; }
inline const Iterator & base() const
{ return m_it; }
private:
Iterator m_it;
inline void increment()
{ ++m_it; }
inline void decrement()
{ --m_it; }
inline bool equal(const multialloc_iterator &other) const
{ return m_it == other.m_it; }
inline bool less(const multialloc_iterator &other) const
{ return other.m_it < m_it; }
inline void advance(typename Iterator::difference_type n)
{ boost::container::iterator_advance(m_it, n); }
inline typename Iterator::difference_type distance_to(const multialloc_iterator &other)const
{ return boost::container::iterator_distance(other.m_it, m_it); }
};
template<class MultiallocationChain, class T>
class transform_multiallocation_chain
: public MultiallocationChain
@ -217,9 +304,8 @@ class transform_multiallocation_chain
{ return pointer_traits::static_cast_from(p); }
public:
typedef transform_iterator
< typename MultiallocationChain::iterator
, dtl::cast_functor <T> > iterator;
typedef multialloc_iterator
<typename MultiallocationChain::iterator, T> iterator;
typedef typename MultiallocationChain::size_type size_type;
typedef boost::intrusive::twin<pointer> pointer_pair;