diff --git a/doc/container.qbk b/doc/container.qbk index b02d1df..3c0ad5a 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1246,6 +1246,7 @@ use [*Boost.Container]? There are several reasons for that: * Removed support for already deprecated GCC < 4.3 and MSVC < 9.0 (Visual 2008) compilers. * Fixed bugs: * [@https://github.com/boostorg/container/pull/96 GitHub #96: ['"Workaround: Intel compilers do not offer CTAD yet"]]. + * [@https://github.com/boostorg/container/issues/97 GitHub #97: ['"buffer overflow in boost::container::flat_map on FreeBSD"]]. [endsect] diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp index 9cca9f6..f30ba42 100644 --- a/include/boost/container/detail/pair.hpp +++ b/include/boost/container/detail/pair.hpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -188,8 +189,36 @@ void get(T); //to enable ADL ///@endcond +#ifdef _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR +//Libc++, in some versions, has an ABI breakage that needs some +//padding in dtl::pair, as "std::pair::first" is not at offset zero. +//See: https://reviews.llvm.org/D56357 for more information. +// +template +struct pair_padding +{ + char padding[N]; +}; + +template +struct pair_padding +{ +}; + +template +struct simple_pair +{ + T1 first; + T2 second; +}; + +#endif + template struct pair +#ifdef _LIBCPP_VERSION + : pair_padding) - sizeof(simple_pair)> +#endif { private: BOOST_COPYABLE_AND_MOVABLE(pair) @@ -204,64 +233,88 @@ struct pair //Default constructor pair() : first(), second() - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } //pair copy assignment pair(const pair& x) : first(x.first), second(x.second) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } //pair move constructor pair(BOOST_RV_REF(pair) p) : first(::boost::move(p.first)), second(::boost::move(p.second)) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } template pair(const pair &p) : first(p.first), second(p.second) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } template pair(BOOST_RV_REF_BEG pair BOOST_RV_REF_END p) : first(::boost::move(p.first)), second(::boost::move(p.second)) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } //pair from two values pair(const T1 &t1, const T2 &t2) : first(t1) , second(t2) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } template pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v) : first(::boost::forward(u)) , second(::boost::forward(v)) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } //And now compatibility with std::pair pair(const std::pair& x) : first(x.first), second(x.second) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } template pair(const std::pair& p) : first(p.first), second(p.second) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } pair(BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END p) : first(::boost::move(p.first)), second(::boost::move(p.second)) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } template pair(BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END p) : first(::boost::move(p.first)), second(::boost::move(p.second)) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template< class KeyType, class ...Args> pair(try_emplace_t, BOOST_FWD_REF(KeyType) k, Args && ...args) : first(boost::forward(k)), second(::boost::forward(args)...)\ - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } #else //piecewise construction from boost::tuple @@ -269,7 +322,9 @@ struct pair template< class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ pair( try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\ : first(boost::forward(k)), second(BOOST_MOVE_FWD##N)\ - {}\ + {\ + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair)));\ + }\ // BOOST_MOVE_ITERATE_0TO9(BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE) #undef BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE @@ -289,7 +344,9 @@ struct pair >::type* = 0\ )\ : first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\ - { (void)p; (void)q; }\ + { (void)p; (void)q;\ + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair)));\ + }\ // BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE) #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE @@ -309,7 +366,9 @@ struct pair , class = typename pair_impl::disable_if_boost_tuple< Tuple >::type> pair(piecewise_construct_t, Tuple t1, Tuple t2) : pair(t1, t2, typename build_number_seq::type(), typename build_number_seq::type()) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } # else //piecewise construction from variadic tuple (suboptimal, without delegating constructors) private: @@ -327,7 +386,9 @@ struct pair pair(piecewise_construct_t, Tuple t1, Tuple t2) : first (build_from_args (::boost::move(t1))) , second (build_from_args(::boost::move(t2))) - {} + { + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair))); + } # endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520) //MSVC 2010 tuple implementation @@ -338,7 +399,9 @@ struct pair , StdTuple p\ , StdTuple q)\ : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\ - { (void)p; (void)q; }\ + { (void)p; (void)q;\ + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair)));\ + }\ // BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE) #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE @@ -357,7 +420,9 @@ struct pair , StdTuple p\ , StdTuple q)\ : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\ - { (void)p; (void)q; }\ + { (void)p; (void)q;\ + BOOST_STATIC_ASSERT((sizeof(std::pair) == sizeof(pair)));\ + }\ // BOOST_MOVE_ITER2D_0TOMAX(BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE) #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE