Remove UB in flat_map implementation when the implementation has a movable std::pair

This commit is contained in:
Ion Gaztañaga committed 2024-04-28 23:29:59 +02:00
1 parent 429024ca4e
commit 20ad12f20e
4 files changed
+241 -134

No files matched your search

+52 -15
View File
@@ -48,6 +48,11 @@
#include <initializer_list>
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
#endif
namespace boost {
namespace container {
@@ -58,21 +63,37 @@ class flat_multimap;
namespace dtl{
#if defined(BOOST_CONTAINER_STD_PAIR_IS_MOVABLE)
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
{ return *move_detail::force_ptr<D*>(&s); }
{ return s; }
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
{ return *move_detail::force_ptr<const D*>(&s); }
{ return s; }
template<class D>
BOOST_CONTAINER_FORCEINLINE static D force_copy(D s)
{ return s; }
#else //!BOOST_CONTAINER_DOXYGEN_INVOKED
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
{ return *move_detail::launder_cast<D*>(&s); }
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
{ return *move_detail::launder_cast<const D*>(&s); }
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
{
const D *const vp = move_detail::force_ptr<const D *>(&s);
const D *const vp = move_detail::launder_cast<const D *>(&s);
D ret_val(*vp);
return ret_val;
}
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace dtl{
@@ -118,18 +139,27 @@ class flat_map
private:
BOOST_COPYABLE_AND_MOVABLE(flat_map)
//This is the tree that we should store if pair was movable
typedef std::pair<Key, T> std_pair_t;
typedef dtl::flat_tree<
std::pair<Key, T>,
std_pair_t,
dtl::select1st<Key>,
Compare,
AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef dtl::pair<Key, T> dtl_pair_t;
#ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
typedef std_pair_t impl_pair_t;
#else
typedef dtl_pair_t impl_pair_t;
#endif
typedef dtl::flat_tree<
dtl::pair<Key, T>,
impl_pair_t,
dtl::select1st<Key>,
Compare,
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -851,7 +881,7 @@ class flat_map
//! @copydoc ::boost::container::flat_set::nth(size_type) const
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
{ return dtl::force_copy<const_iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
@@ -1099,7 +1129,7 @@ class flat_map
template <class Pair>
inline BOOST_CONTAINER_DOC1ST
( std::pair<iterator BOOST_MOVE_I bool>
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
insert(BOOST_FWD_REF(Pair) x)
{
@@ -1153,7 +1183,7 @@ class flat_map
template <class Pair>
inline BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{
@@ -1777,17 +1807,24 @@ class flat_multimap
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef std::pair<Key, T> std_pair_t;
typedef dtl::flat_tree<
std::pair<Key, T>,
std_pair_t,
dtl::select1st<Key>,
Compare,
AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef dtl::pair<Key, T> dtl_pair_t;
#ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
typedef std_pair_t impl_pair_t;
#else
typedef dtl_pair_t impl_pair_t;
#endif
typedef dtl::flat_tree<
dtl::pair<Key, T>,
impl_pair_t,
dtl::select1st<Key>,
Compare,
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -2388,7 +2425,7 @@ class flat_multimap
//! @copydoc ::boost::container::flat_set::nth(size_type) const
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
{ return dtl::force_copy<const_iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
@@ -2477,7 +2514,7 @@ class flat_multimap
template<class Pair>
inline BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I iterator >::type)
insert(BOOST_FWD_REF(Pair) x)
{ return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Pair>(x))); }
@@ -2514,7 +2551,7 @@ class flat_multimap
template<class Pair>
inline BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{