mirror of
https://github.com/boostorg/container.git
synced 2025-07-30 20:47:17 +02:00
Avoid using transform iterator as null pointer dereferences might happen
This commit is contained in:
@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user