diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -903,6 +903,12 @@ # ifndef _LIBCPP_HAS_NO_ASAN extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); +# if _LIBCPP_CLANG_VER >= 1600 +extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_double_ended_contiguous_container( + const void*, const void*, const void*, const void*, const void*, const void*); +extern "C" _LIBCPP_FUNC_VIS int +__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); +# endif # endif // Try to find out if RTTI is disabled. diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -219,6 +219,13 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> +#if !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600 + extern "C" int __sanitizer_annotate_double_ended_contiguous_container( + const void *storage_beg, const void *storage_end, + const void *old_container_beg, const void *old_container_end, + const void *new_container_beg, const void *new_container_end); +#endif + _LIBCPP_BEGIN_NAMESPACE_STD @@ -435,6 +442,9 @@ template */> class _LIBCPP_TEMPLATE_VIS deque { +private: + using __default_allocator_type = allocator<_Tp>; + public: // types: @@ -557,10 +567,11 @@ // construct/copy/destroy: _LIBCPP_HIDE_FROM_ABI deque() _NOEXCEPT_(is_nothrow_default_constructible::value) - : __start_(0), __size_(0, __default_init_tag()) {} + : __start_(0), __size_(0, __default_init_tag()) {__annotate_new(0);} _LIBCPP_HIDE_FROM_ABI ~deque() { clear(); + __annotate_delete(); typename __map::iterator __i = __map_.begin(); typename __map::iterator __e = __map_.end(); for (; __i != __e; ++__i) @@ -568,7 +579,7 @@ } _LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a) - : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {} + : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {__annotate_new(0);} explicit _LIBCPP_HIDE_FROM_ABI deque(size_type __n); #if _LIBCPP_STD_VER >= 14 @@ -580,8 +591,9 @@ _LIBCPP_HIDE_FROM_ABI deque(size_type __n, const value_type& __v, const allocator_type& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { - if (__n > 0) - __append(__n, __v); + __annotate_new(0); + if (__n > 0) + __append(__n, __v); } template @@ -858,27 +870,240 @@ } private: +// The following functions are no-ops outside of AddressSanitizer mode. +// We call annotatations only for the default Allocator. +#if !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600 +_LIBCPP_HIDE_FROM_ABI + void __annotate_double_ended_contiguous_container( + const void* __beg, + const void* __end, + const void* __old_con_beg, + const void* __old_con_end, + const void* __new_con_beg, + const void* __new_con_end) const { + if (__beg && is_same::value) + __sanitizer_annotate_double_ended_contiguous_container( + __beg, __end, __old_con_beg, __old_con_end, __new_con_beg, __new_con_end); +} +#else +_LIBCPP_HIDE_FROM_ABI + void __annotate_double_ended_contiguous_container( + const void*, const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} +#endif // !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600 + _LIBCPP_HIDE_FROM_ABI - bool __maybe_remove_front_spare(bool __keep_one = true) { - if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { - __alloc_traits::deallocate(__alloc(), __map_.front(), - __block_size); - __map_.pop_front(); - __start_ -= __block_size; - return true; + void __annotate_from_to(size_type __b, size_type __e, bool __poisoning, bool __front) const _NOEXCEPT { + // __b - index of the first item to annotate + // __e - index behind the last item to annotate (so last item + 1) + // __poisoning - true if poisoning, false if unpoisoning + // __front - true if front was moved, __false if end was moved + // Alle indexes in __map_ + if (__b == __e) + // Nothing to do here. + return; + // __annotations_beg_mp - first chunk which annotations we want to modify + // __annotations_end_mp - last chunk which annotations we want to modify + // NOTE: if __e % __block_size == 0, __annotations_end_mp points at the next block, which may not exist + typename __map::const_iterator __annotations_beg_mp = __map_.begin() + __b / __block_size; + typename __map::const_iterator __annotations_end_mp = __map_.begin() + __e / __block_size; + + // __old_c_beg_index - index of the first element in old container + // __old_c_end_index - index of the end of old container (last + 1) + // NOTE: may be outside the area we are annotating + size_t __old_c_beg_index = (__poisoning && __front) ? __b : __start_; + size_t __old_c_end_index = (__poisoning && !__front) ? __e : __start_ + size(); + if(__poisoning && empty()) { + // Special case: we shouldn't trust __start_ + __old_c_beg_index = __b; + __old_c_end_index = __e; + } + // __old_c_beg_mp - memory block (chunk) with first element + // __old_c_end_mp - memory block (chunk) with end of old container + // NOTE: if __old_c_end_index % __block_size == 0, __old_c_end_mp points at the next block, + // which may not exist + typename __map::const_iterator __old_c_beg_mp = __map_.begin() + __old_c_beg_index / __block_size; + typename __map::const_iterator __old_c_end_mp = __map_.begin() + __old_c_end_index / __block_size; + + // One edge (front/end) of the container was moved and one was not modified. + // __new_edge_index - index of new edge + // __new_edge_mp - memory block (chunk) with new edge, it always equals to + // __annotations_beg_mp or __annotations_end_mp + // __old_edge_mp - memory block (chunk) with old edge, it always equals to + // __old_c_beg_mp or __old_c_end_mp + size_t __new_edge_index = (__poisoning ^ __front) ? __b : __e; + typename __map::const_iterator __new_edge_mp = __map_.begin() + __new_edge_index / __block_size; + typename __map::const_iterator __old_edge_mp = __front ? __old_c_end_mp : __old_c_beg_mp; + + // We iterate over map pointers (chunks) and fully poison all memory blocks between the first and the last. + // First and last chunk may be partially poisoned. + // __annotate_end_mp may point at not existing chunk, therefore we have to have a check for it. + for (typename __map::const_iterator __mp = __annotations_beg_mp; __mp <= __annotations_end_mp; ++__mp) { + if(__mp == __annotations_end_mp && __e % __block_size == 0) + // Nothing to do here, chunk may not exist + break; + // The beginning and the end of the current memory block + const void* __mem_b = _VSTD::__to_address(*__mp); + const void* __mem_e = _VSTD::__to_address(*__mp + __block_size); + + // The beginning of memory-in-use in the memory block before container modification + const void* __old_b = (__mp == __old_c_beg_mp) ? + _VSTD::__to_address(*__mp + (__old_c_beg_index % __block_size)) : __mem_b; + + // The end of memory-in-use in the memory block before container modification + const void* __old_e; + if(__mp < __old_c_beg_mp || __mp > __old_c_end_mp || (!__poisoning && empty())) + __old_e = __old_b; + else + __old_e = (__mp == __old_c_end_mp) ? + _VSTD::__to_address(*__mp + (__old_c_end_index % __block_size)) : __mem_e; + + // New edge of the container in current memory block + // If the edge is in a different chunk it points on corresponding end of the memory block + const void* __new_edge; + if(__mp == __new_edge_mp) + __new_edge = _VSTD::__to_address(*__mp + (__new_edge_index % __block_size)); + else + __new_edge = (__poisoning ^ __front) ? __mem_b : __mem_e; + + // Not modified edge of the container + // If the edge is in a different chunk it points on corresponding end of the memory block + const void* __old_edge; + if(__mp == __old_edge_mp) + __old_edge = __front ? __old_e : __old_b; + else + __old_edge = __front ? __mem_e : __mem_b; + // __new_b - the beginning of memory-in-use in the memory block after container modification + // __new_e - the end of memory-in-use in the memory block after container modification + const void* __new_b = __front ? __new_edge : __old_edge; + const void* __new_e = __front ? __old_edge : __new_edge; + + __annotate_double_ended_contiguous_container(__mem_b, __mem_e, __old_b, __old_e, __new_b, __new_e); } - return false; } +_LIBCPP_HIDE_FROM_ABI + void __annotate_new(size_type __current_size) const _NOEXCEPT { + if (__current_size == 0) + __annotate_from_to(0, __map_.size() * __block_size, true, false); + else { + __annotate_from_to(0, __start_, true, true); + __annotate_from_to(__start_ + __current_size, __map_.size() * __block_size, true, false); + } +} + +_LIBCPP_HIDE_FROM_ABI + void __annotate_delete() const _NOEXCEPT { + if (!empty()) { + __annotate_from_to(0, __start_, false, true); + __annotate_from_to(__start_ + size(), __map_.size() * __block_size, false, false); + } else + __annotate_from_to(0, __map_.size() * __block_size, false, false); +} + +_LIBCPP_HIDE_FROM_ABI + void __annotate_increase_front(size_type __n) const _NOEXCEPT { + __annotate_from_to(__start_ - __n, __start_, false, true); +} + +_LIBCPP_HIDE_FROM_ABI + void __annotate_increase_back(size_type __n) const _NOEXCEPT { + __annotate_from_to(__start_ + size(), __start_ + size() + __n, false, false); +} + +_LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_from_to(__old_start, __old_start + (__old_size - size()), true, true); +} + +_LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_from_to(__old_start + size(), __old_start + __old_size, true, false); +} + +// This macro should be defined only during testing ASAN. +// Include the "asan_testing.h" file which defines it +// to be able to use it in ASan tests. +#ifdef _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS + public: + bool __verify_asan_annotations() const _NOEXCEPT { + // This function tests deque object annotations. + if (empty()) { + for (typename __map::const_iterator __it = __map_.begin(); + __it != __map_.end(); + ++__it) + if (!__sanitizer_verify_double_ended_contiguous_container( + *__it, *__it, *__it, *__it + __block_size)) + return false; + + return true; + } + + size_type __e = __start_ + size(); + typename __map_::const_iterator __first_mp = + __map_.begin() + __start_ / __block_size; + typename __map::const_iterator __map_const_pointer __last_mp = + __map_.begin() + (__e - 1) / __block_size; + + // Pointers to first and after last elements + // Those can be in different deque blocks + pointer __p_beg = *__first_mp + (__start_ % __block_size); + pointer __p_end = + *__last_mp + ((__e % __block_size == 0) ? __block_size : __e % __block_size); + + for (typename __map::const_iterator __it = __map_.begin(); + __it != __map_.end(); + ++__it) { + // Go over all blocks, find the place we are in and verify its annotations + // Note that __p_end points *behind* the last item. + + // - blocks before the first block with container elements + // - first block with items + // - last block with items + // - blocks after last block with ciontainer elements + + // Is the block before or after deque blocks that contain elements? + if (__it < __first_mp || __it > __last_mp) { + if (!__sanitizer_verify_double_ended_contiguous_container( + *__it, *__it, *__it, (*__it + __block_size))) + return false; + } else { + pointer __p_b = (__it == __first_mp) ? __p_beg : *it; + pointer __p_e = (__it == __last_mp) ? __p_end : *it + __block_size; + if (!__sanitizer_verify_double_ended_contiguous_container( + *__it, __p_b, __p_e, (*__it + __block_size))) + return false; + } + return false; + } + return true; + } + + private: +#endif // _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS _LIBCPP_HIDE_FROM_ABI - bool __maybe_remove_back_spare(bool __keep_one = true) { - if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { - __alloc_traits::deallocate(__alloc(), __map_.back(), - __block_size); - __map_.pop_back(); - return true; - } - return false; + bool __maybe_remove_front_spare(bool __keep_one = true) { + __annotate_from_to(0, __block_size, false, false); + if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { + __alloc_traits::deallocate(__alloc(), __map_.front(), + __block_size); + __map_.pop_front(); + __start_ -= __block_size; + return true; + } + return false; + } + + _LIBCPP_HIDE_FROM_ABI + bool __maybe_remove_back_spare(bool __keep_one = true) { + if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { + __annotate_from_to( + (__map_.size() - 1) * __block_size, __map_.size() * __block_size, false, false); + __alloc_traits::deallocate(__alloc(), __map_.back(), + __block_size); + __map_.pop_back(); + return true; + } + return false; } template @@ -955,8 +1180,9 @@ deque<_Tp, _Allocator>::deque(size_type __n) : __start_(0), __size_(0, __default_init_tag()) { - if (__n > 0) - __append(__n); + __annotate_new(0); + if (__n > 0) + __append(__n); } #if _LIBCPP_STD_VER >= 14 @@ -964,8 +1190,9 @@ deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { - if (__n > 0) - __append(__n); + __annotate_new(0); + if (__n > 0) + __append(__n); } #endif @@ -973,8 +1200,9 @@ deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) : __start_(0), __size_(0, __default_init_tag()) { - if (__n > 0) - __append(__n, __v); + __annotate_new(0); + if (__n > 0) + __append(__n, __v); } template @@ -983,7 +1211,8 @@ typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) : __start_(0), __size_(0, __default_init_tag()) { - __append(__f, __l); + __annotate_new(0); + __append(__f, __l); } template @@ -992,7 +1221,8 @@ typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { - __append(__f, __l); + __annotate_new(0); + __append(__f, __l); } template @@ -1001,14 +1231,16 @@ __start_(0), __size_(0, __map_.__alloc()) { - __append(__c.begin(), __c.end()); + __annotate_new(0); + __append(__c.begin(), __c.end()); } template deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { - __append(__c.begin(), __c.end()); + __annotate_new(0); + __append(__c.begin(), __c.end()); } template @@ -1029,14 +1261,16 @@ deque<_Tp, _Allocator>::deque(initializer_list __il) : __start_(0), __size_(0, __default_init_tag()) { - __append(__il.begin(), __il.end()); + __annotate_new(0); + __append(__il.begin(), __il.end()); } template deque<_Tp, _Allocator>::deque(initializer_list __il, const allocator_type& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { - __append(__il.begin(), __il.end()); + __annotate_new(0); + __append(__il.begin(), __il.end()); } template @@ -1190,6 +1424,7 @@ allocator_type& __a = __alloc(); if (empty()) { + __annotate_delete(); while (__map_.size() > 0) { __alloc_traits::deallocate(__a, __map_.back(), __block_size); @@ -1289,6 +1524,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*end()), __v); ++__size(); } @@ -1301,6 +1537,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), __v); --__start_; ++__size(); @@ -1315,6 +1552,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*end()), _VSTD::move(__v)); ++__size(); } @@ -1332,6 +1570,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*end()), _VSTD::forward<_Args>(__args)...); ++__size(); @@ -1348,6 +1587,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::move(__v)); --__start_; ++__size(); @@ -1367,6 +1607,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::forward<_Args>(__args)...); --__start_; ++__size(); @@ -1387,6 +1628,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::move(__v)); @@ -1410,6 +1652,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = size() - __pos; if (__de == 0) { @@ -1443,6 +1686,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::forward<_Args>(__args)...); @@ -1467,6 +1711,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = size() - __pos; if (__de == 0) { @@ -1503,6 +1748,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), __v); @@ -1529,6 +1775,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = size() - __pos; if (__de == 0) { @@ -1564,6 +1811,7 @@ if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = begin(); iterator __i = __old_begin; if (__n > __pos) @@ -1588,6 +1836,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = end(); iterator __i = __old_end; size_type __de = size() - __pos; @@ -1650,6 +1899,7 @@ if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = begin(); iterator __i = __old_begin; _BiIter __m = __f; @@ -1680,6 +1930,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = end(); iterator __i = __old_end; _BiIter __m = __l; @@ -1730,6 +1981,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(end(), end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) { @@ -1747,6 +1999,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(end(), end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -1764,6 +2017,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(end(), end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -1786,14 +2040,17 @@ pointer __pt = __map_.back(); __map_.pop_back(); __map_.push_front(__pt); + __annotate_from_to(0, __block_size, true, false); } // Else if __map_.size() < __map_.capacity() then we need to allocate 1 buffer else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around // until all buffers are allocated. If we throw, we don't need to fix // anything up (any added buffers are undetectible) - if (__map_.__front_spare() > 0) - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + if (__map_.__front_spare() > 0) { + __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __annotate_from_to(0, __block_size, true, false); + } else { __map_.push_back(__alloc_traits::allocate(__a, __block_size)); @@ -1801,10 +2058,12 @@ pointer __pt = __map_.back(); __map_.pop_back(); __map_.push_front(__pt); + __annotate_from_to(0, __block_size, true, false); } __start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size; + __annotate_from_to(0, __block_size, true, false); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -1830,6 +2089,7 @@ __start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size; + __annotate_from_to(0, __block_size, true, false); } } @@ -1866,6 +2126,7 @@ if (__map_.__front_spare() == 0) break; __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __annotate_from_to(0, __block_size, true, false); } for (; __nb > 0; --__nb, ++__back_capacity) __map_.push_back(__alloc_traits::allocate(__a, __block_size)); @@ -1876,6 +2137,7 @@ pointer __pt = __map_.back(); __map_.pop_back(); __map_.push_front(__pt); + __annotate_from_to(0, __block_size, true, false); } } // Else need to allocate __nb buffers, *and* we need to reallocate __map_. @@ -1890,12 +2152,22 @@ try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS - for (; __nb > 0; --__nb) + for (; __nb > 0; --__nb) { __buf.push_back(__alloc_traits::allocate(__a, __block_size)); + // ASan: this is empty container, we have to poison whole + __annotate_double_ended_contiguous_container( + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back() + __block_size), + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back() + __block_size), + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back())); + } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { + __annotate_delete(); for (__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) __alloc_traits::deallocate(__a, *__i, __block_size); @@ -1942,11 +2214,14 @@ else { __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __annotate_from_to(0, __block_size, true, false); // Done allocating, reorder capacity pointer __pt = __map_.front(); __map_.pop_front(); __map_.push_back(__pt); } + __annotate_from_to( + (__map_.size() - 1) * __block_size, __map_.size() * __block_size, true, false); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -1970,6 +2245,8 @@ _VSTD::swap(__map_.__begin_, __buf.__begin_); _VSTD::swap(__map_.__end_, __buf.__end_); _VSTD::swap(__map_.__end_cap(), __buf.__end_cap()); + __annotate_from_to( + (__map_.size() - 1) * __block_size, __map_.size() * __block_size, true, false); } } @@ -2006,10 +2283,14 @@ if (__map_.__back_spare() == 0) break; __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __annotate_from_to( + (__map_.size() - 1) * __block_size, __map_.size() * __block_size, true, false); } for (; __nb > 0; --__nb, ++__front_capacity, __start_ += - __block_size - (__map_.size() == 1)) + __block_size - (__map_.size() == 1)) { __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __annotate_from_to(0, __block_size, true, false); + } // Done allocating, reorder capacity __start_ -= __block_size * __front_capacity; for (; __front_capacity > 0; --__front_capacity) @@ -2032,12 +2313,22 @@ try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS - for (; __nb > 0; --__nb) + for (; __nb > 0; --__nb) { __buf.push_back(__alloc_traits::allocate(__a, __block_size)); + // ASan: this is empty container, we have to poison whole + __annotate_double_ended_contiguous_container( + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back() + __block_size), + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back() + __block_size), + _VSTD::__to_address(__buf.back()), + _VSTD::__to_address(__buf.back())); + } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { + __annotate_delete(); for (__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) __alloc_traits::deallocate(__a, *__i, __block_size); @@ -2064,12 +2355,15 @@ void deque<_Tp, _Allocator>::pop_front() { + size_type __old_sz = size(); + size_type __old_start = __start_; allocator_type& __a = __alloc(); __alloc_traits::destroy(__a, _VSTD::__to_address(*(__map_.begin() + __start_ / __block_size) + __start_ % __block_size)); --__size(); ++__start_; + __annotate_shrink_front(__old_sz, __old_start); __maybe_remove_front_spare(); } @@ -2078,12 +2372,15 @@ deque<_Tp, _Allocator>::pop_back() { _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque"); + size_type __old_sz = size(); + size_type __old_start = __start_; allocator_type& __a = __alloc(); size_type __p = size() + __start_ - 1; __alloc_traits::destroy(__a, _VSTD::__to_address(*(__map_.begin() + __p / __block_size) + __p % __block_size)); --__size(); + __annotate_shrink_back(__old_sz, __old_start); __maybe_remove_back_spare(); } @@ -2223,6 +2520,8 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f) { + size_type __old_sz = size(); + size_type __old_start = __start_; iterator __b = begin(); difference_type __pos = __f - __b; iterator __p = __b + __pos; @@ -2233,6 +2532,7 @@ __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); --__size(); ++__start_; + __annotate_shrink_front(__old_sz, __old_start); __maybe_remove_front_spare(); } else @@ -2240,6 +2540,7 @@ iterator __i = _VSTD::move(_VSTD::next(__p), end(), __p); __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); --__size(); + __annotate_shrink_back(__old_sz, __old_start); __maybe_remove_back_spare(); } return begin() + __pos; @@ -2249,6 +2550,8 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) { + size_type __old_sz = size(); + size_type __old_start = __start_; difference_type __n = __l - __f; iterator __b = begin(); difference_type __pos = __f - __b; @@ -2263,6 +2566,7 @@ __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); __size() -= __n; __start_ += __n; + __annotate_shrink_front(__old_sz, __old_start); while (__maybe_remove_front_spare()) { } } @@ -2272,6 +2576,7 @@ for (iterator __e = end(); __i != __e; ++__i) __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); __size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); while (__maybe_remove_back_spare()) { } } @@ -2283,6 +2588,8 @@ void deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) { + size_type __old_sz = size(); + size_type __old_start = __start_; iterator __e = end(); difference_type __n = __e - __f; if (__n > 0) @@ -2293,6 +2600,7 @@ for (iterator __p = __b + __pos; __p != __e; ++__p) __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); __size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); while (__maybe_remove_back_spare()) { } } @@ -2320,6 +2628,7 @@ void deque<_Tp, _Allocator>::clear() _NOEXCEPT { + __annotate_delete(); allocator_type& __a = __alloc(); for (iterator __i = begin(), __e = end(); __i != __e; ++__i) __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); @@ -2338,6 +2647,7 @@ __start_ = __block_size; break; } + __annotate_new(0); } template diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp @@ -21,6 +21,7 @@ // const_reference back() const; // libc++ marks these as 'noexcept' +#include "asan_testing.h" #include #include @@ -66,6 +67,7 @@ assert(c.at(i) == i); assert(c.front() == 0); assert(c.back() == 9); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } { typedef std::deque C; @@ -82,6 +84,7 @@ assert(c.at(i) == i); assert(c.front() == 0); assert(c.back() == 9); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #if TEST_STD_VER >= 11 { @@ -99,6 +102,7 @@ assert(c.at(i) == i); assert(c.front() == 0); assert(c.back() == 9); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } { typedef std::deque> C; @@ -115,6 +119,7 @@ assert(c.at(i) == i); assert(c.front() == 0); assert(c.back() == 9); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp @@ -12,6 +12,7 @@ // bool empty() const noexcept; +#include "asan_testing.h" #include #include @@ -27,8 +28,10 @@ assert(c.empty()); c.push_back(C::value_type(1)); assert(!c.empty()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.clear(); assert(c.empty()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #if TEST_STD_VER >= 11 { @@ -38,8 +41,10 @@ assert(c.empty()); c.push_back(C::value_type(1)); assert(!c.empty()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.clear(); assert(c.empty()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp @@ -10,6 +10,7 @@ // size_type max_size() const; +#include "asan_testing.h" #include #include #include @@ -25,6 +26,7 @@ C c; assert(c.max_size() <= 10); LIBCPP_ASSERT(c.max_size() == 10); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } { typedef limited_allocator A; @@ -34,6 +36,7 @@ C c; assert(c.max_size() <= max_dist); LIBCPP_ASSERT(c.max_size() == max_dist); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } { typedef std::deque C; @@ -42,6 +45,7 @@ C c; assert(c.max_size() <= max_dist); assert(c.max_size() <= alloc_max_size(c.get_allocator())); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp @@ -10,6 +10,7 @@ // void resize(size_type n); +#include "asan_testing.h" #include #include #include @@ -34,10 +35,13 @@ C c(init, 0); for (int i = 0; i < init-start; ++i) c.pop_back(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); for (int i = 0; i < size; ++i) c.push_back(i); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); for (int i = 0; i < start; ++i) c.pop_front(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); return c; } @@ -50,6 +54,7 @@ c1.resize(size); assert(c1.size() == static_cast(size)); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); CI i = c1.begin(); for (int j = 0; static_cast(j) < std::min(c1_osize, c1.size()); ++j, ++i) assert(*i == j); @@ -84,6 +89,14 @@ for (int k = 0; k < N; ++k) testN>>(rng[i], rng[j], rng[k]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + for (int k = 0; k < N; ++k) + testN>>(rng[i], rng[j], rng[k]); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp @@ -10,6 +10,7 @@ // void resize(size_type n, const value_type& v); +#include "asan_testing.h" #include #include #include @@ -34,10 +35,13 @@ C c(init, 0); for (int i = 0; i < init-start; ++i) c.pop_back(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); for (int i = 0; i < size; ++i) c.push_back(i); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); for (int i = 0; i < start; ++i) c.pop_front(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); return c; } @@ -50,6 +54,7 @@ c1.resize(size, x); assert(c1.size() == static_cast(size)); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); CI i = c1.begin(); for (int j = 0; static_cast(j) < std::min(c1_osize, c1.size()); ++j, ++i) assert(*i == j); @@ -84,6 +89,14 @@ for (int k = 0; k < N; ++k) testN>>(rng[i], rng[j], rng[k]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + for (int k = 0; k < N; ++k) + testN>>(rng[i], rng[j], rng[k]); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp @@ -10,6 +10,7 @@ // void shrink_to_fit(); +#include "asan_testing.h" #include #include @@ -45,6 +46,7 @@ C s = c1; c1.shrink_to_fit(); assert(c1 == s); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); } template @@ -72,6 +74,13 @@ for (int j = 0; j < N; ++j) testN> >(rng[i], rng[j]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + testN> >(rng[i], rng[j]); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp @@ -12,6 +12,7 @@ // size_type size() const noexcept; +#include "asan_testing.h" #include #include @@ -25,18 +26,25 @@ C c; ASSERT_NOEXCEPT(c.size()); assert(c.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.push_back(C::value_type(2)); assert(c.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.push_back(C::value_type(1)); assert(c.size() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.push_back(C::value_type(3)); assert(c.size() == 3); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.erase(c.begin()); assert(c.size() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.erase(c.begin()); assert(c.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.erase(c.begin()); assert(c.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #if TEST_STD_VER >= 11 { @@ -44,18 +52,25 @@ C c; ASSERT_NOEXCEPT(c.size()); assert(c.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.push_back(C::value_type(2)); assert(c.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.push_back(C::value_type(1)); assert(c.size() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.push_back(C::value_type(3)); assert(c.size() == 3); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.erase(c.begin()); assert(c.size() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.erase(c.begin()); assert(c.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.erase(c.begin()); assert(c.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp @@ -10,6 +10,7 @@ // explicit deque(const allocator_type& a); +#include "asan_testing.h" #include #include @@ -25,6 +26,7 @@ std::deque d(a); assert(d.size() == 0); assert(d.get_allocator() == a); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } int main(int, char**) @@ -33,7 +35,9 @@ test(test_allocator(3)); #if TEST_STD_VER >= 11 test(min_allocator()); + test(safe_allocator()); test(min_allocator{}); + test(safe_allocator{}); test(explicit_allocator()); test(explicit_allocator{}); #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp @@ -12,6 +12,7 @@ // void assign(initializer_list il); +#include "asan_testing.h" #include #include @@ -28,6 +29,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } { std::deque> d; @@ -37,6 +39,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp @@ -11,6 +11,7 @@ // template // void assign(InputIterator f, InputIterator l); +#include "asan_testing.h" #include #include #include @@ -51,6 +52,8 @@ c1.assign(c2.begin(), c2.end()); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } template @@ -71,6 +74,8 @@ c1.assign(ICI(c2.begin()), ICI(c2.end())); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } template @@ -103,6 +108,15 @@ testN> >(rng[i], rng[j], rng[k]); testNI> >(1500, 2000, 1000); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + for (int k = 0; k < N; ++k) + testN> >(rng[i], rng[j], rng[k]); + testNI> >(1500, 2000, 1000); + } #endif } diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp @@ -10,6 +10,7 @@ // void assign(size_type n, const value_type& v); +#include "asan_testing.h" #include #include #include @@ -48,6 +49,7 @@ c1.assign(size, v); assert(c1.size() == static_cast(size)); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); for (CI i = c1.begin(); i != c1.end(); ++i) assert(*i == v); } diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp @@ -10,6 +10,7 @@ // deque(const deque&); +#include "asan_testing.h" #include #include @@ -23,6 +24,8 @@ { C c(x); assert(c == x); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(x)); } int main(int, char**) @@ -37,6 +40,8 @@ std::deque > v2 = v; assert(v2 == v); assert(v2.get_allocator() == v.get_allocator()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v2)); } #if TEST_STD_VER >= 11 { @@ -44,6 +49,8 @@ std::deque > v2 = v; assert(v2 == v); assert(v2.get_allocator() == other_allocator(-2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v2)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -55,6 +62,8 @@ std::deque > v2 = v; assert(v2 == v); assert(v2.get_allocator() == v.get_allocator()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v2)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp @@ -10,6 +10,7 @@ // deque(const deque& c, const allocator_type& a); +#include "asan_testing.h" #include #include @@ -24,6 +25,7 @@ C c(x, a); assert(c == x); assert(c.get_allocator() == a); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } int main(int, char**) @@ -47,6 +49,12 @@ test(std::deque >(ab, an, min_allocator()), min_allocator()); } + { + int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; + int* an = ab + sizeof(ab)/sizeof(ab[0]); + test(std::deque >(ab, an, safe_allocator()), + safe_allocator()); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp @@ -14,6 +14,7 @@ // -> deque::value_type, Allocator>; // +#include "asan_testing.h" #include #include #include @@ -37,6 +38,7 @@ static_assert(std::is_same_v>, ""); assert(std::equal(deq.begin(), deq.end(), std::begin(arr), std::end(arr))); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } { @@ -47,6 +49,7 @@ assert(deq[0] == INT_MAX); assert(deq[1] == 1L); assert(deq[2] == 2L); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } // Test the implicit deduction guides @@ -61,6 +64,7 @@ static_assert(std::is_same_v, ""); static_assert(std::is_same_v>, ""); assert(deq.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } { @@ -68,6 +72,7 @@ static_assert(std::is_same_v, ""); static_assert(std::is_same_v>, ""); assert(deq.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } { @@ -75,6 +80,7 @@ static_assert(std::is_same_v, ""); assert(deq.size() == 5); assert(deq[2] == 3U); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } { @@ -83,6 +89,7 @@ static_assert(std::is_same_v>, ""); assert(deq.size() == 4); assert(deq[3] == 4.0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } { @@ -91,6 +98,7 @@ static_assert(std::is_same_v, ""); static_assert(std::is_same_v>, ""); assert(deq.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); } { @@ -101,24 +109,32 @@ std::deque source; std::deque deq(source, Alloc(2)); static_assert(std::is_same_v); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source)); } { std::deque source; std::deque deq(source, ConvertibleToAlloc(2)); static_assert(std::is_same_v); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source)); } { std::deque source; std::deque deq(std::move(source), Alloc(2)); static_assert(std::is_same_v); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source)); } { std::deque source; std::deque deq(std::move(source), ConvertibleToAlloc(2)); static_assert(std::is_same_v); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(deq)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(source)); } } diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp @@ -10,6 +10,7 @@ // deque() +#include "asan_testing.h" #include #include @@ -24,9 +25,11 @@ { std::deque d; assert(d.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); #if TEST_STD_VER >= 11 std::deque d1 = {}; assert(d1.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d1)); #endif } diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp @@ -12,6 +12,7 @@ // deque(initializer_list il); +#include "asan_testing.h" #include #include @@ -27,6 +28,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } { std::deque> d = {3, 4, 5, 6}; @@ -35,6 +37,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp @@ -12,6 +12,7 @@ // deque(initializer_list il, const Allocator& a = allocator_type()); +#include "asan_testing.h" #include #include @@ -29,6 +30,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } { std::deque> d({3, 4, 5, 6}, min_allocator()); @@ -38,6 +40,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp @@ -10,6 +10,7 @@ // template deque(InputIterator f, InputIterator l); +#include "asan_testing.h" #include #include #include @@ -33,6 +34,7 @@ C d(f, l); assert(d.size() == static_cast(std::distance(f, l))); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f) assert(*i == *f); } @@ -47,6 +49,7 @@ C d(f, l); assert(d.size() == static_cast(std::distance(f, l))); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f) assert(*i == *f); } diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp @@ -11,6 +11,7 @@ // template // deque(InputIterator f, InputIterator l, const allocator_type& a); +#include "asan_testing.h" #include #include #include @@ -34,6 +35,7 @@ assert(d.get_allocator() == a); assert(d.size() == static_cast(std::distance(f, l))); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); for (const_iterator i = d.begin(), e = d.end(); i != e; ++i, ++f) assert(*i == *f); } @@ -66,12 +68,14 @@ { std::deque v(It(arr1), It(std::end(arr1)), a); assert(v[0].value == 42); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); } { std::deque v(It(arr2), It(std::end(arr2)), a); assert(v[0].value == 1); assert(v[1].value == 101); assert(v[2].value == 42); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); } } { @@ -82,6 +86,7 @@ std::deque v(It(arr1), It(std::end(arr1)), a); assert(v[0].copied == 0); assert(v[0].value == 42); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); } { std::deque v(It(arr2), It(std::end(arr2)), a); @@ -91,6 +96,7 @@ assert(v[1].value == 101); assert(v[2].copied == 0); assert(v[2].value == 42); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); } } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp @@ -12,6 +12,7 @@ // deque(deque&&); +#include "asan_testing.h" #include #include @@ -38,6 +39,9 @@ assert(c1.size() == 0); assert(c3.get_allocator() == old_a); assert(c1.get_allocator() == A(test_alloc_base::moved_value)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -53,6 +57,9 @@ assert(c2 == c3); assert(c1.size() == 0); assert(c3.get_allocator() == c1.get_allocator()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -68,6 +75,9 @@ assert(c2 == c3); assert(c1.size() == 0); assert(c3.get_allocator() == c1.get_allocator()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp @@ -12,6 +12,7 @@ // deque(deque&& c, const allocator_type& a); +#include "asan_testing.h" #include #include @@ -36,6 +37,9 @@ assert(c2 == c3); assert(c3.get_allocator() == A(3)); LIBCPP_ASSERT(c1.size() != 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -51,6 +55,9 @@ assert(c2 == c3); assert(c3.get_allocator() == A(1)); LIBCPP_ASSERT(c1.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -66,6 +73,9 @@ assert(c2 == c3); assert(c3.get_allocator() == A(3)); LIBCPP_ASSERT(c1.size() != 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -81,6 +91,9 @@ assert(c2 == c3); assert(c3.get_allocator() == A()); LIBCPP_ASSERT(c1.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp @@ -12,6 +12,7 @@ // deque& operator=(deque&& c); +#include "asan_testing.h" #include #include @@ -37,6 +38,9 @@ assert(c2 == c3); assert(c1.size() == 0); assert(c3.get_allocator() == A(5)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -53,6 +57,9 @@ assert(c2 == c3); assert(c1.size() != 0); assert(c3.get_allocator() == A(6)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -69,6 +76,9 @@ assert(c2 == c3); assert(c1.size() == 0); assert(c3.get_allocator() == A(5)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } { int ab[] = {3, 4, 2, 8, 0, 1, 44, 34, 45, 96, 80, 1, 13, 31, 45}; @@ -85,6 +95,9 @@ assert(c2 == c3); assert(c1.size() == 0); assert(c3.get_allocator() == A()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c3)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp @@ -10,6 +10,7 @@ // deque& operator=(const deque& c); +#include "asan_testing.h" #include #include #include "test_macros.h" @@ -23,6 +24,8 @@ C c; c = x; assert(c == x); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(x)); } int main(int, char**) @@ -38,6 +41,8 @@ l2 = l; assert(l2 == l); assert(l2.get_allocator() == test_allocator(3)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l2)); } { std::deque > l(3, 2, other_allocator(5)); @@ -45,6 +50,8 @@ l2 = l; assert(l2 == l); assert(l2.get_allocator() == other_allocator(5)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l2)); } #if TEST_STD_VER >= 11 { @@ -58,6 +65,8 @@ l2 = l; assert(l2 == l); assert(l2.get_allocator() == min_allocator()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(l2)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp @@ -12,6 +12,7 @@ // deque& operator=(initializer_list il); +#include "asan_testing.h" #include #include @@ -28,6 +29,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } { std::deque> d; @@ -37,6 +39,7 @@ assert(d[1] == 4); assert(d[2] == 5); assert(d[3] == 6); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp @@ -10,6 +10,7 @@ // explicit deque(size_type n); +#include "asan_testing.h" #include #include #include @@ -32,6 +33,7 @@ assert(static_cast(DefaultOnly::count) == n); assert(d.size() == n); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); for (const_iterator i = d.begin(), e = d.end(); i != e; ++i) assert(*i == T()); } @@ -53,6 +55,7 @@ assert(static_cast(DefaultOnly::count) == n); assert(d.size() == n); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); #if TEST_STD_VER >= 11 for (const_iterator i = d.begin(), e = d.end(); i != e; ++i) assert(*i == T()); @@ -71,6 +74,7 @@ C d(n, alloc); assert(d.size() == n); assert(d.get_allocator() == alloc); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } #else ((void)n); diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp @@ -10,6 +10,7 @@ // deque(size_type n, const value_type& v); +#include "asan_testing.h" #include #include #include @@ -27,6 +28,7 @@ C d(n, x); assert(d.size() == n); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); for (const_iterator i = d.begin(), e = d.end(); i != e; ++i) assert(*i == x); } diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp @@ -10,6 +10,7 @@ // deque(size_type n, const value_type& v, const allocator_type& a); +#include "asan_testing.h" #include #include #include @@ -27,6 +28,7 @@ assert(d.get_allocator() == a); assert(d.size() == n); assert(static_cast(std::distance(d.begin(), d.end())) == d.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); for (const_iterator i = d.begin(), e = d.end(); i != e; ++i) assert(*i == x); } diff --git a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp @@ -13,6 +13,7 @@ // typename deque::size_type // erase(deque& c, const U& value); +#include "asan_testing.h" #include #include @@ -25,6 +26,7 @@ ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase(s, val))); assert(expected_erased_count == std::erase(s, val)); assert(s == expected); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(s)); } template @@ -67,6 +69,7 @@ { test>(); test>> (); + test>> (); test>> (); test>(); diff --git a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp @@ -13,6 +13,7 @@ // typename deque::size_type // erase_if(deque& c, Predicate pred); +#include "asan_testing.h" #include #include "test_macros.h" @@ -24,6 +25,7 @@ ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase_if(s, p))); assert(expected_erased_count == std::erase_if(s, p)); assert(s == expected); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(s)); } template @@ -69,6 +71,7 @@ { test>(); test>> (); + test>> (); test>> (); test>(); diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp @@ -10,6 +10,7 @@ // void clear() noexcept; +#include "asan_testing.h" #include #include @@ -26,6 +27,7 @@ ASSERT_NOEXCEPT(c.clear()); c.clear(); assert(std::distance(c.begin(), c.end()) == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } { typedef int T; @@ -36,9 +38,11 @@ ASSERT_NOEXCEPT(c.clear()); c.clear(); assert(std::distance(c.begin(), c.end()) == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.clear(); assert(std::distance(c.begin(), c.end()) == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #if TEST_STD_VER >= 11 { @@ -48,6 +52,7 @@ ASSERT_NOEXCEPT(c.clear()); c.clear(); assert(std::distance(c.begin(), c.end()) == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } { typedef int T; @@ -58,9 +63,11 @@ ASSERT_NOEXCEPT(c.clear()); c.clear(); assert(std::distance(c.begin(), c.end()) == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.clear(); assert(std::distance(c.begin(), c.end()) == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp @@ -12,6 +12,7 @@ // UNSUPPORTED: c++03 +#include "asan_testing.h" #include #include #include @@ -54,6 +55,7 @@ assert(c1.size() == c1_osize + 1); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); assert(*i == Emplaceable(1, 2.5)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); } template @@ -103,6 +105,13 @@ for (int j = 0; j < N; ++j) testN> >(rng[i], rng[j]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + testN> >(rng[i], rng[j]); + } return 0; } diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp @@ -13,6 +13,7 @@ // template reference emplace_back(Args&&... args); // return type is 'reference' in C++17; 'void' before +#include "asan_testing.h" #include #include #include @@ -61,6 +62,7 @@ == static_cast(c1.size())); I i = c1.end(); assert(*--i == Emplaceable(1, 2.5)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); #if TEST_STD_VER > 14 assert(&(*i) == &ref); #endif @@ -94,12 +96,16 @@ std::deque> c; c.emplace_back(); assert(c.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.emplace_back(1, 2, 3); assert(c.size() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.emplace_front(); assert(c.size() == 3); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.emplace_front(1, 2, 3); assert(c.size() == 4); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp @@ -13,6 +13,7 @@ // template reference emplace_front(Args&&... args); // return type is 'reference' in C++17; 'void' before +#include "asan_testing.h" #include #include #include @@ -61,6 +62,7 @@ == static_cast(c1.size())); I i = c1.begin(); assert(*i == Emplaceable(1, 2.5)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); #if TEST_STD_VER > 14 assert(&res_ref == &(*i)); #endif @@ -95,12 +97,16 @@ std::deque> c; c.emplace_front(); assert(c.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.emplace_front(1, 2, 3); assert(c.size() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.emplace_front(); assert(c.size() == 3); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); c.emplace_front(1, 2, 3); assert(c.size() == 4); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp @@ -13,6 +13,7 @@ // Erasing items from the beginning or the end of a deque shall not invalidate iterators // to items that were not erased. +#include "asan_testing.h" #include #include @@ -54,6 +55,7 @@ assert( it2 == it4); assert( *it2 == *it4); assert(&*it2 == &*it4); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp @@ -10,6 +10,7 @@ // iterator erase(const_iterator p) +#include "asan_testing.h" #include #include #include @@ -119,6 +120,7 @@ v.erase(--v.end()); v.erase(v.begin()); assert(v.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp @@ -14,6 +14,7 @@ // to items that were not erased. +#include "asan_testing.h" #include #include #include @@ -38,6 +39,7 @@ assert( it2 == it4); assert( *it2 == *it4); assert(&*it2 == &*it4); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } template @@ -58,6 +60,7 @@ assert( it2 == it4); assert( *it2 == *it4); assert(&*it2 == &*it4); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp @@ -12,6 +12,7 @@ // iterator erase(const_iterator f, const_iterator l) +#include "asan_testing.h" #include #include #include @@ -71,6 +72,7 @@ assert(i == c1.begin() + P); assert(c1.size() == c1_osize - size); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); i = c1.begin(); int j = 0; for (; j < P; ++j, ++i) @@ -123,8 +125,10 @@ Throws::sThrows = true; v.erase(v.begin(), --v.end()); assert(v.size() == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); v.erase(v.begin(), v.end()); assert(v.size() == 0); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(v)); } #endif diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp @@ -12,6 +12,7 @@ // iterator insert(const_iterator p, initializer_list il); +#include "asan_testing.h" #include #include @@ -39,6 +40,7 @@ assert(d[11] == 1); assert(d[12] == 1); assert(d[13] == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } { std::deque> d(10, 1); @@ -59,6 +61,7 @@ assert(d[11] == 1); assert(d[12] == 1); assert(d[13] == 1); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(d)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp @@ -13,6 +13,7 @@ // template // iterator insert (const_iterator p, InputIterator f, InputIterator l); +#include "asan_testing.h" #include #include #include @@ -58,6 +59,8 @@ assert(i == c1.begin() + P); assert(c1.size() == c1_osize + c2.size()); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); i = c1.begin(); for (int j = 0; j < P; ++j, ++i) assert(*i == j); @@ -173,6 +176,8 @@ assert(i == c1.begin() + P); assert(c1.size() == c1_osize + c2.size()); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); i = c1.begin(); for (int j = 0; j < P; ++j, ++i) assert(*i == j); @@ -284,6 +289,16 @@ testNI >(1500, 2000, 1000); test_move > >(); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + for (int k = 0; k < N; ++k) + testN> >(rng[i], rng[j], rng[k]); + testNI >(1500, 2000, 1000); + test_move > >(); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp @@ -12,6 +12,7 @@ // UNSUPPORTED: c++03 +#include "asan_testing.h" #include #include #include @@ -53,6 +54,7 @@ assert(i == c1.begin() + P); assert(c1.size() == c1_osize + 1); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); i = c1.begin(); for (int j = 0; j < P; ++j, (void) ++i) assert(*i == MoveOnly(j)); @@ -108,6 +110,13 @@ for (int j = 0; j < N; ++j) testN> >(rng[i], rng[j]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + testN> >(rng[i], rng[j]); + } return 0; } diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp @@ -12,6 +12,7 @@ // iterator insert (const_iterator p, size_type n, const value_type& v); +#include "asan_testing.h" #include #include #include @@ -51,6 +52,7 @@ assert(i == c1.begin() + P); assert(c1.size() == c1_osize + size); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); i = c1.begin(); for (int j = 0; j < P; ++j, ++i) assert(*i == j); @@ -153,6 +155,15 @@ testN> >(rng[i], rng[j], rng[k]); self_reference_test> >(); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + for (int k = 0; k < N; ++k) + testN> >(rng[i], rng[j], rng[k]); + self_reference_test> >(); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp @@ -10,6 +10,7 @@ // iterator insert (const_iterator p, const value_type& v); +#include "asan_testing.h" #include #include #include @@ -49,6 +50,7 @@ assert(i == c1.begin() + P); assert(c1.size() == c1_osize + 1); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); i = c1.begin(); for (int j = 0; j < P; ++j, ++i) assert(*i == j); @@ -133,6 +135,14 @@ testN> >(rng[i], rng[j]); self_reference_test> >(); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + testN> >(rng[i], rng[j]); + self_reference_test> >(); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp @@ -13,6 +13,7 @@ // Erasing items from the beginning or the end of a deque shall not invalidate iterators // to items that were not erased. +#include "asan_testing.h" #include #include @@ -34,18 +35,20 @@ assert( it2 == it4); assert( *it2 == *it4); assert(&*it2 == &*it4); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); } int main(int, char**) { std::deque queue; - for (int i = 0; i < 20; ++i) + for (int i = 0; i < 4098; ++i) queue.push_back(i); while (queue.size() > 1) { test(queue); queue.pop_back(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(queue)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp @@ -10,6 +10,7 @@ // void pop_back() +#include "asan_testing.h" #include #include #include @@ -48,6 +49,7 @@ c1.pop_back(); assert(c1.size() == c1_osize - 1); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); I i = c1.begin(); for (int j = 0; static_cast(j) < c1.size(); ++j, ++i) assert(*i == j); @@ -81,6 +83,13 @@ for (int j = 0; j < N; ++j) testN> >(rng[i], rng[j]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + testN> >(rng[i], rng[j]); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp @@ -13,6 +13,7 @@ // Erasing items from the beginning or the end of a deque shall not invalidate iterators // to items that were not erased. +#include "asan_testing.h" #include #include @@ -39,13 +40,14 @@ int main(int, char**) { std::deque queue; - for (int i = 0; i < 20; ++i) + for (int i = 0; i < 4098; ++i) queue.push_back(i); while (queue.size() > 1) { test(queue); queue.pop_back(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(queue)); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp @@ -10,6 +10,7 @@ // void pop_front() +#include "asan_testing.h" #include #include #include @@ -48,6 +49,7 @@ c1.pop_front(); assert(c1.size() == c1_osize - 1); assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); I i = c1.begin(); for (int j = 1; static_cast(j) < c1.size(); ++j, ++i) assert(*i == j); diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp @@ -12,6 +12,7 @@ // void pop_back(); // void pop_front(); +#include "asan_testing.h" #include #include @@ -49,6 +50,7 @@ { C c = make(size, rng[j]); typename C::const_iterator it = c.begin(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); for (int i = 0; i < size; ++i, ++it) assert(*it == i); } diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp @@ -14,6 +14,7 @@ // void pop_back(); // void pop_front(); +#include "asan_testing.h" #include #include @@ -53,6 +54,7 @@ { C c = make(size, rng[j]); typename C::const_iterator it = c.begin(); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c)); for (int i = 0; i < size; ++i, (void) ++it) assert(*it == MoveOnly(i)); } @@ -73,6 +75,12 @@ for (int j = 0; j < N; ++j) test> >(rng[j]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2046, 2047, 2048, 2049, 4094, 4095, 4096}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int j = 0; j < N; ++j) + test> >(rng[j]); + } return 0; } diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp @@ -10,6 +10,7 @@ // void push_front(const value_type& v); +#include "asan_testing.h" #include #include #include @@ -50,6 +51,7 @@ assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); I i = c1.begin(); assert(*i == x); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); ++i; for (int j = 0; static_cast(j) < c1_osize; ++j, ++i) assert(*i == j); @@ -80,6 +82,13 @@ for (int j = 0; j < N; ++j) testN> >(rng[i], rng[j]); } + { + int rng[] = {0, 1, 2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; + const int N = sizeof(rng)/sizeof(rng[0]); + for (int i = 0; i < N; ++i) + for (int j = 0; j < N; ++j) + testN> >(rng[i], rng[j]); + } #endif return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp @@ -12,6 +12,7 @@ // void push_front(value_type&& v); +#include "asan_testing.h" #include #include #include @@ -54,6 +55,7 @@ assert(static_cast(std::distance(c1.begin(), c1.end())) == c1.size()); I i = c1.begin(); assert(*i == MoveOnly(x)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); ++i; for (int j = 0; static_cast(j) < c1_osize; ++j, (void) ++i) assert(*i == MoveOnly(j)); @@ -82,7 +84,7 @@ const int N = sizeof(rng)/sizeof(rng[0]); for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) - testN> >(rng[i], rng[j]); + testN> >(rng[i], rng[j]); } return 0; diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp @@ -14,6 +14,7 @@ // OutputIterator // copy(InputIterator first, InputIterator last, OutputIterator result); +#include "asan_testing.h" #include #include @@ -55,16 +56,28 @@ C c2 = make(N); assert(std::copy(c1.cbegin(), c1.cend(), c2.begin()) == c2.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy(c2.cbegin(), c2.cend(), c1.begin()) == c1.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy(c1.cbegin(), c1.cend(), RAI(c2.begin())) == RAI(c2.end())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy(c2.cbegin(), c2.cend(), RAI(c1.begin())) == RAI(c1.end())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy(RACI(c1.cbegin()), RACI(c1.cend()), c2.begin()) == c2.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy(ICI(c2.cbegin()), ICI(c2.cend()), c1.begin()) == c1.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp @@ -14,6 +14,7 @@ // OutputIterator // copy_backward(InputIterator first, InputIterator last, OutputIterator result); +#include "asan_testing.h" #include #include @@ -54,16 +55,28 @@ C c2 = make(N); assert(std::copy_backward(c1.cbegin(), c1.cend(), c2.end()) == c2.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy_backward(c2.cbegin(), c2.cend(), c1.end()) == c1.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy_backward(c1.cbegin(), c1.cend(), RAI(c2.end())) == RAI(c2.begin())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy_backward(c2.cbegin(), c2.cend(), RAI(c1.end())) == RAI(c1.begin())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy_backward(RACI(c1.cbegin()), RACI(c1.cend()), c2.end()) == c2.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::copy_backward(RACI(c2.cbegin()), RACI(c2.cend()), c1.end()) == c1.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp @@ -14,6 +14,7 @@ // OutputIterator // move(InputIterator first, InputIterator last, OutputIterator result); +#include "asan_testing.h" #include #include @@ -54,16 +55,28 @@ C c2 = make(N); assert(std::move(c1.cbegin(), c1.cend(), c2.begin()) == c2.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move(c2.cbegin(), c2.cend(), c1.begin()) == c1.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move(c1.cbegin(), c1.cend(), RAI(c2.begin())) == RAI(c2.end())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move(c2.cbegin(), c2.cend(), RAI(c1.begin())) == RAI(c1.end())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move(RACI(c1.cbegin()), RACI(c1.cend()), c2.begin()) == c2.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move(RACI(c2.cbegin()), RACI(c2.cend()), c1.begin()) == c1.end()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp @@ -14,6 +14,7 @@ // OutputIterator // move_backward(InputIterator first, InputIterator last, OutputIterator result); +#include "asan_testing.h" #include #include @@ -54,16 +55,28 @@ C c2 = make(N); assert(std::move_backward(c1.cbegin(), c1.cend(), c2.end()) == c2.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move_backward(c2.cbegin(), c2.cend(), c1.end()) == c1.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move_backward(c1.cbegin(), c1.cend(), RAI(c2.end())) == RAI(c2.begin())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move_backward(c2.cbegin(), c2.cend(), RAI(c1.end())) == RAI(c1.begin())); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move_backward(RACI(c1.cbegin()), RACI(c1.cend()), c2.end()) == c2.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); assert(std::move_backward(RACI(c2.cbegin()), RACI(c2.cend()), c1.end()) == c1.begin()); assert(c1 == c2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } int main(int, char**) diff --git a/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp --- a/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp @@ -11,6 +11,7 @@ // template // void swap(deque& x, deque& y); +#include "asan_testing.h" #include #include #include "test_macros.h" @@ -49,6 +50,10 @@ swap(c1, c2); assert(c1 == c2_save); assert(c2 == c1_save); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1_save)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2_save)); } int main(int, char**) @@ -72,6 +77,8 @@ assert(c1.get_allocator().get_id() == 1); assert((c2 == std::deque(a1, a1+sizeof(a1)/sizeof(a1[0])))); assert(c2.get_allocator().get_id() == 2); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } { int a1[] = {1, 3, 7, 9, 10}; @@ -84,6 +91,8 @@ assert(c1.get_allocator() == A(2)); assert((c2 == std::deque(a1, a1+sizeof(a1)/sizeof(a1[0])))); assert(c2.get_allocator() == A(1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } #if TEST_STD_VER >= 11 { @@ -105,6 +114,8 @@ assert(c1.get_allocator() == A()); assert((c2 == std::deque(a1, a1+sizeof(a1)/sizeof(a1[0])))); assert(c2.get_allocator() == A()); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c1)); + LIBCPP_ASSERT(is_double_ended_contiguous_container_asan_correct(c2)); } #endif diff --git a/libcxx/test/support/asan_testing.h b/libcxx/test/support/asan_testing.h --- a/libcxx/test/support/asan_testing.h +++ b/libcxx/test/support/asan_testing.h @@ -9,7 +9,14 @@ #ifndef ASAN_TESTING_H #define ASAN_TESTING_H +#ifdef _LIBCPP_DEQUE +// We need to define _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS first +// prior to including deque, so we error out if its already included +# error deque included before asan_testing.h +#endif + #include "test_macros.h" +#include #if TEST_HAS_FEATURE(address_sanitizer) extern "C" int __sanitizer_verify_contiguous_container @@ -25,14 +32,35 @@ c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0; return true; } - #else template TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) { return true; } -#endif +#endif // TEST_HAS_FEATURE(address_sanitizer) + +#if TEST_HAS_FEATURE(address_sanitizer) && _LIBCPP_CLANG_VER >= 1600 +extern "C" int __sanitizer_verify_double_ended_contiguous_container( + const void* beg, const void* con_beg, const void* con_end, const void* end); +extern "C" bool __sanitizer_is_annotable(const void* address, const unsigned long size); +# define _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS +# include +template +TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque& c) { + if (TEST_IS_CONSTANT_EVALUATED) + return true; + if (std::is_same >::value) + return c.__verify_asan_annotations(); + return true; +} +#else +# include +template +TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std::deque&) { + return true; +} +#endif #endif // ASAN_TESTING_H