From 1582b2086dc255ed2b65152a873654fa71998023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 13 Sep 2012 18:54:58 +0000 Subject: [PATCH] Corrected strict aliasing error in multiallocation_chain [SVN r80514] --- .../detail/adaptive_node_pool_impl.hpp | 3 +- .../detail/multiallocation_chain.hpp | 53 ++++++++++++------- .../container/detail/node_alloc_holder.hpp | 3 +- include/boost/container/stable_vector.hpp | 7 +-- include/boost/container/vector.hpp | 21 ++++---- 5 files changed, 50 insertions(+), 37 deletions(-) diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp index afba6b5..39b9942 100644 --- a/include/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp @@ -348,8 +348,7 @@ class private_adaptive_node_pool_impl { block_iterator block_it(m_block_multiset.end()); while(n--){ - void *pElem = container_detail::to_raw_pointer(chain.front()); - chain.pop_front(); + void *pElem = container_detail::to_raw_pointer(chain.pop_front()); priv_invariants(); block_info_t *block_info = this->priv_block_from_node(pElem); BOOST_ASSERT(block_info->free_nodes.size() < m_real_num_node); diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp index 155e9bc..98d0924 100644 --- a/include/boost/container/detail/multiallocation_chain.hpp +++ b/include/boost/container/detail/multiallocation_chain.hpp @@ -45,14 +45,30 @@ class basic_multiallocation_chain > slist_impl_t; slist_impl_t slist_impl_; - static node & to_node(VoidPointer p) - { return *static_cast(static_cast(container_detail::to_raw_pointer(p))); } + typedef typename boost::intrusive::pointer_traits + ::template rebind_pointer::type node_ptr; + typedef typename boost::intrusive:: + pointer_traits node_ptr_traits; + + static node & build_node(const VoidPointer &p) + { + return *::new (static_cast(static_cast(container_detail::to_raw_pointer(p)))) node; + } + + static VoidPointer destroy_node(node &n) + { + VoidPointer retptr = node_ptr_traits::pointer_to(n); + n.~node(); + return retptr; + } + + static node_ptr to_node_ptr(VoidPointer p) + { return node_ptr_traits::static_cast_from(p); } BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) public: - typedef VoidPointer void_pointer; typedef typename slist_impl_t::iterator iterator; typedef typename slist_impl_t::size_type size_type; @@ -94,19 +110,21 @@ class basic_multiallocation_chain { slist_impl_.clear(); } iterator insert_after(iterator it, void_pointer m) - { return slist_impl_.insert_after(it, to_node(m)); } + { return slist_impl_.insert_after(it, build_node(m)); } void push_front(void_pointer m) - { return slist_impl_.push_front(to_node(m)); } + { return slist_impl_.push_front(build_node(m)); } void push_back(void_pointer m) - { return slist_impl_.push_back(to_node(m)); } + { return slist_impl_.push_back(build_node(m)); } - void pop_front() - { return slist_impl_.pop_front(); } - - void *front() - { return &*slist_impl_.begin(); } + void_pointer pop_front() + { + node & n = slist_impl_.front(); + void_pointer ret = destroy_node(n); + slist_impl_.pop_front(); + return ret; + } void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_begin, iterator before_end) { slist_impl_.splice_after(after_this, x.slist_impl_, before_begin, before_end); } @@ -118,10 +136,12 @@ class basic_multiallocation_chain { slist_impl_.splice_after(after_this, x.slist_impl_); } void incorporate_after(iterator after_this, void_pointer begin , iterator before_end) - { slist_impl_.incorporate_after(after_this, &to_node(begin), &to_node(before_end)); } + { + slist_impl_.incorporate_after(after_this, to_node_ptr(begin), to_node_ptr(before_end)); + } void incorporate_after(iterator after_this, void_pointer begin, void_pointer before_end, size_type n) - { slist_impl_.incorporate_after(after_this, &to_node(begin), &to_node(before_end), n); } + { slist_impl_.incorporate_after(after_this, to_node_ptr(begin), to_node_ptr(before_end), n); } void swap(basic_multiallocation_chain &x) { slist_impl_.swap(x.slist_impl_); } @@ -203,11 +223,8 @@ class transform_multiallocation_chain void incorporate_after(iterator after_this, pointer begin, pointer before_end, size_type n) { holder_.incorporate_after(after_this.base(), begin, before_end, n); } - void pop_front() - { holder_.pop_front(); } - - pointer front() - { return cast(holder_.front()); } + pointer pop_front() + { return cast(holder_.pop_front()); } bool empty() const { return holder_.empty(); } diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 8b0f8ba..68048bc 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -247,8 +247,7 @@ struct node_alloc_holder Node *p = 0; BOOST_TRY{ for(difference_type i = 0; i < n; ++i, ++beg, --constructed){ - p = container_detail::to_raw_pointer(mem.front()); - mem.pop_front(); + p = container_detail::to_raw_pointer(mem.pop_front()); //This can throw constructed = 0; boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), beg); diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index be0416c..f6c55c9 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -589,9 +589,7 @@ class stable_vector ::value>::type * = 0) { while(!holder.empty()){ - const node_ptr n = holder.front(); - holder.pop_front(); - this->deallocate_one(n); + this->deallocate_one(holder.pop_front()); } } @@ -1697,8 +1695,7 @@ class stable_vector , node_ptr_traits::static_cast_from(pool_first_ref) , node_ptr_traits::static_cast_from(pool_last_ref) , internal_data.pool_size); - node_ptr ret = holder.front(); - holder.pop_front(); + node_ptr ret = holder.pop_front(); --this->internal_data.pool_size; if(!internal_data.pool_size){ pool_first_ref = pool_last_ref = node_ptr(); diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index fd00705..87a09bc 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1723,7 +1723,7 @@ class vector : private container_detail::vector_alloc_holder //New situation in Case A (hole_size == 0): // range is moved through move assignments // - // first_pos last_pos old_limit + // first_pos last_pos limit_pos // | | | // ____________V_______V__________________V_____________ //| prefix' | | | range |suffix'|raw_mem ~ @@ -1735,7 +1735,7 @@ class vector : private container_detail::vector_alloc_holder //New situation in Case B (hole_size > 0): // range is moved through uninitialized moves // - // first_pos last_pos old_limit + // first_pos last_pos limit_pos // | | | // ____________V_______V__________________V________________ //| prefix' | | | [hole] | range | @@ -1746,31 +1746,33 @@ class vector : private container_detail::vector_alloc_holder //New situation in Case C (hole_size == 0): // range is moved through move assignments and uninitialized moves // - // first_pos last_pos old_limit + // first_pos last_pos limit_pos // | | | // ____________V_______V__________________V___ //| prefix' | | | range | //|___________________________________|___^___| // | | // |_>_>_>_>_>_>_>_>_>_>_>^ - size_type priv_insert_ordered_at_shift_range(size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count) + size_type priv_insert_ordered_at_shift_range + (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count) { BOOST_ASSERT(first_pos <= last_pos); BOOST_ASSERT(last_pos <= limit_pos); // T* const begin_ptr = container_detail::to_raw_pointer(this->members_.m_start); + T* const first_ptr = begin_ptr + first_pos; + T* const last_ptr = begin_ptr + last_pos; size_type hole_size = 0; //Case A: if((last_pos + shift_count) <= limit_pos){ //All move assigned - boost::move_backward(begin_ptr + first_pos, begin_ptr + last_pos, begin_ptr + last_pos + shift_count); + boost::move_backward(first_ptr, last_ptr, last_ptr + shift_count); } //Case B: else if((first_pos + shift_count) >= limit_pos){ //All uninitialized_moved - ::boost::container::uninitialized_move_alloc - (this->alloc(), begin_ptr + first_pos, begin_ptr + last_pos, begin_ptr + first_pos + shift_count); + ::boost::container::uninitialized_move_alloc(this->alloc(), first_ptr, last_ptr, first_ptr + shift_count); hole_size = last_pos + shift_count - limit_pos; } //Case C: @@ -1778,10 +1780,9 @@ class vector : private container_detail::vector_alloc_holder //Some uninitialized_moved T* const limit_ptr = begin_ptr + limit_pos; T* const boundary_ptr = limit_ptr - shift_count; - ::boost::container::uninitialized_move_alloc - (this->alloc(), boundary_ptr, begin_ptr + last_pos, limit_ptr); + ::boost::container::uninitialized_move_alloc(this->alloc(), boundary_ptr, last_ptr, limit_ptr); //The rest is move assigned - boost::move_backward(begin_ptr + first_pos, boundary_ptr, limit_ptr); + boost::move_backward(first_ptr, boundary_ptr, limit_ptr); } return hole_size; }