diff --git a/compiler-rt/lib/asan/asan_poisoning.cpp b/compiler-rt/lib/asan/asan_poisoning.cpp --- a/compiler-rt/lib/asan/asan_poisoning.cpp +++ b/compiler-rt/lib/asan/asan_poisoning.cpp @@ -395,7 +395,7 @@ // Annotates front for a double ended contiguous container like std::deque // It allows detecting buggy accesses to allocated but not used begining or end -// items of such a container +// items of such a container. void __sanitizer_annotate_de_contiguous_container_front( const void *beg_p, const void *end_p, const void *new_con_beg_p, const void *old_con_beg_p, const void *con_end_p) { @@ -477,7 +477,8 @@ // Annotates back for a double ended contiguous container like std::deque // It allows detecting buggy accesses to allocated but not used begining or end -// items of such a container +// items of such a container. +// Look at __sanitizer_annotate_de_contiguous_container_front first. void __sanitizer_annotate_de_contiguous_container_back( const void *beg_p, const void *end_p, const void *old_con_end_p, const void *new_con_end_p, const void *con_beg_p) { diff --git a/deque b/deque new file mode 100644 diff --git a/libcxx/include/deque b/libcxx/include/deque --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -1280,6 +1280,9 @@ class _LIBCPP_TEMPLATE_VIS deque : private __deque_base<_Tp, _Allocator> { +private: + using __default_allocator_type = allocator<_Tp>; + public: // types: @@ -1310,10 +1313,8 @@ // construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY - deque() - _NOEXCEPT_(is_nothrow_default_constructible::value) - {} - _LIBCPP_INLINE_VISIBILITY explicit deque(const allocator_type& __a) : __base(__a) {} + deque() _NOEXCEPT_(is_nothrow_default_constructible::value) { __annotate_new(0); } + _LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a) : __base(__a) { __annotate_new(0); } explicit deque(size_type __n); #if _LIBCPP_STD_VER > 11 explicit deque(size_type __n, const _Allocator& __a); @@ -1323,8 +1324,9 @@ template ::value> > deque(size_type __n, const value_type& __v, const allocator_type& __a) : __base(__a) { - if (__n > 0) - __append(__n, __v); + __annotate_new(0); + if (__n > 0) + __append(__n, __v); } template @@ -1529,75 +1531,415 @@ } private: - _LIBCPP_INLINE_VISIBILITY - bool __maybe_remove_front_spare(bool __keep_one = true) { - if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { - __alloc_traits::deallocate(__base::__alloc(), __base::__map_.front(), - __base::__block_size); - __base::__map_.pop_front(); - __base::__start_ -= __base::__block_size; - return true; - } - return false; - } + // Implementation based on the one from std::vector. + // + // The following functions are no-ops outside of AddressSanitizer mode. + // We call annotatations only for the default Allocator because other allocators + // may not meet the AddressSanitizer alignment constraints. + // See the documentation for __sanitizer_annotate_contiguous_container for more details. +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_front( + const void* __beg, + const void* __end, + const void* __new_con_beg, + const void* __old_con_beg, + const void* __con_end) const { + // Same wrapper as in std::vector for annotating mid-to-end of a contiguous block. + if (__beg && is_same::value) + __sanitizer_annotate_de_contiguous_container_front(__beg, __end, __new_con_beg, __old_con_beg, __con_end); + } + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_back( + const void* __beg, + const void* __end, + const void* __old_con_end, + const void* __new_con_end, + const void* __con_beg) const { + // Same wrapper as in std::vector for annotating mid-to-end of a contiguous block + if (__beg && is_same::value) + __sanitizer_annotate_de_contiguous_container_back(__beg, __end, __old_con_end, __new_con_end, __con_beg); + } +#else + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_front( + const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI + void __annotate_contiguous_container_back( + const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} +#endif // _LIBCPP_HAS_NO_ASAN + + _LIBCPP_HIDE_FROM_ABI + // __b - index of first item in __map_ to annotate + // __e - index behind the last item in __map_ to annotate (so last item + 1) + void __annotate_poison_from_to_front(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + + // __mp - ponter to the first chunk which annotations we want to modify. + // __last_mp - pointer to the last chunk which annotations we want to modify. + // If ony one chunk if affected, __mp == __last_mp + // We use (__e - 1) in calculations, because if we poison to the very end of chunk, + // we still want to point at that chunk and not the next one. Using __e, would + // point at the memory for the next element, which may be in a next chunk. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); + + // We iterate over map pointers and fully poison all blocks between the first and the last. + // The first block is partialy poisoned here as well. + // The last one is poisoned after the while loop. + while (__mp != __last_mp) { + // Pointer to chunk's/block's beginning + const void* __p_t_b = std::__to_address(*__mp); + // Pointer to chunk's/block's end + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + // We are poisoning rest of the blocks memory, therefore end of block is last argument. + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_t_e, __p_b, __p_t_e); + // Poisoned memory: [__p, __p_t_e] + + __mp += 1; + __p_b = std::__to_address(*__mp); + } + + // If __last_block_index is zero, then we should point to the end of a chunk (one of its contiguous blocks). + size_type __last_block_index = __e % __base::__block_size; + + const void* __p_e = + std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + + // Poisoning happens after the container modification, so the size + // was already changed and may be 0 but we still have to poison the cleared blocks. + if (__last_block_index == 0 || size() == 0) + // Read comments in __annotate_contiguous_container_front for empty block argument requrements. + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_e); + else { + // Due to current limitations of ASan, it only matters if container is empty or not, + // therefore we do not have to calculate true end of the container in the block (better performance), + // but if poisoning prefixes are implemented in Asan, we will have to pass correct end of memory in use + // inside that chunk, instead of just end of the allocated memory. (Last argument.) + // + // Correct end of container is passed to __annotate_contiguous_container_front, but it + // may be changes to __p_t_e for better performance. + // __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p, __p_t_e); + if ((size() + __base::__start_) / __base::__block_size == (__e - 1) / __base::__block_size) { + // End of the container is in the block which we are poisoning. + const void* __p_c_e = std::__to_address(*__mp + ((size() + __base::__start_) % __base::__block_size)); + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_c_e); + } else + // End of the container is in a different chunk, rest of chunk is in use. + // Therefore last argument is end of chunk. + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_e, __p_b, __p_t_e); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_unpoison_from_to_front(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); + while (__mp != __last_mp) { + // Pointer to block's beginning + const void* __p_t_b = std::__to_address(*__mp); + // Pointer to block's end + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_t_e, __p_t_e); + + __mp += 1; + __p_b = std::__to_address(*__mp); + } + + size_type __last_block_index = __e % __base::__block_size; + + const void* __p_e = + std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + + // unpoison happens before the size is changed + // so we have to unpoison the block before its modified + if (__last_block_index == 0 || size() == 0) + __annotate_contiguous_container_front(__p_t_b, __p_e, __p_b, __p_e, __p_e); + else { + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + if ((size() + __base::__start_) / __base::__block_size == (__e - 1) / __base::__block_size) { + const void* __p_c_e = std::__to_address(*__mp + ((size() + __base::__start_) % __base::__block_size)); + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_e, __p_c_e); + } else + __annotate_contiguous_container_front(__p_t_b, __p_t_e, __p_b, __p_e, __p_t_e); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_poison_from_to_back(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = std::__to_address(*__mp + (__b % __base::__block_size)); + const void* __p_c_b; + // Poisoning happens after container modification and size updated. + if (size() == 0) + __p_c_b = __p_b; + else { + if (__base::__start_ / __base::__block_size == __b / __base::__block_size) + // Container starts in the block we are about to poison. + __p_c_b = std::__to_address(*__mp + (__base::__start_ % __base::__block_size)); + else + // Container starts in a different block. + __p_c_b = std::__to_address(*__mp); + } + while (__mp != __last_mp) { + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_t_e, __p_b, __p_c_b); + + __mp += 1; + __p_c_b = __p_b = std::__to_address(*__mp); + } + + size_type __last_block_index = __e % __base::__block_size; + const void* __p_e = + std::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = std::__to_address(*__mp); + const void* __p_t_e = std::__to_address(*__mp + __base::__block_size); + // Poisoning happens after elemests were removed. + if (size() == 0) + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_e, __p_b, __p_b); + else + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_e, __p_b, __p_c_b); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_unpoison_from_to_back(size_type __b, size_type __e) const _NOEXCEPT { + if (__b == __e) + return; + + // Check comment in __annotate_poison_from_to_front(size_type, size_type) for details. + typename __base::__map_traits::const_pointer __mp = __base::__map_.begin() + __b / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + const void* __p_b = _VSTD::__to_address(*__mp + (__b % __base::__block_size)); + const void* __p_c_b; + // Unpoisoning happens befor container modification and size updated. + if (size() == 0) + __p_c_b = __p_b; + else { + if (__base::__start_ / __base::__block_size == __b / __base::__block_size) + // Container starts in the block we are about to poison. + __p_c_b = std::__to_address(*__mp + (__base::__start_ % __base::__block_size)); + else + // Container starts in a different block. + __p_c_b = std::__to_address(*__mp); + } + + while (__mp != __last_mp) { + const void* __p_t_b = _VSTD::__to_address(*__mp); + const void* __p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_b, __p_t_e, __p_c_b); + + __mp += 1; + __p_c_b = __p_b = _VSTD::__to_address(*__mp); + } + + size_type __last_block_index = __e % __base::__block_size; + const void* __p_e = + _VSTD::__to_address(*__mp + (__last_block_index == 0 ? __base::__block_size : __last_block_index)); + const void* __p_t_b = _VSTD::__to_address(*__mp); + const void* __p_t_e = _VSTD::__to_address(*__mp + __base::__block_size); + __annotate_contiguous_container_back(__p_t_b, __p_t_e, __p_b, __p_e, __p_c_b); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_new(size_type __current_size) const _NOEXCEPT { + if (__current_size == 0) + __annotate_poison_from_to_back(0, __base::__map_.size() * __base::__block_size); + else { + // This branch is never reached in current implementation because + // __annotate_new is always called with 0, + // but let's leave it here in case anyone needs to use + // __annotate_new(n) in the future + __annotate_poison_from_to_front(0, __base::__start_); + __annotate_poison_from_to_back(__base::__start_ + __current_size, __base::__map_.size() * __base::__block_size); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_delete() const _NOEXCEPT { + if (!empty()) { + __annotate_unpoison_from_to_front(0, __base::__start_); + __annotate_unpoison_from_to_back( + __base::__start_ + __base::size(), __base::__map_.size() * __base::__block_size); + } else + __annotate_unpoison_from_to_back(0, __base::__map_.size() * __base::__block_size); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_increase_front(size_type __n) const _NOEXCEPT { + __annotate_unpoison_from_to_front(__base::__start_ - __n, __base::__start_); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_increase_back(size_type __n) const _NOEXCEPT { + __annotate_unpoison_from_to_back(__base::__start_ + __base::size(), __base::__start_ + __base::size() + __n); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_poison_from_to_front(__old_start, __old_start + (__old_size - size())); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_poison_from_to_back(__old_start + size(), __old_start + __old_size); + } + +// 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 - _LIBCPP_INLINE_VISIBILITY - bool __maybe_remove_back_spare(bool __keep_one = true) { - if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { - __alloc_traits::deallocate(__base::__alloc(), __base::__map_.back(), - __base::__block_size); - __base::__map_.pop_back(); - return true; +public: + bool __verify_asan_annotations() const _NOEXCEPT { + // This function tests deque object annotations. + // This test is simplified, it tests only if: + // - memory owned by deque (deque blocks) not containig alements is poisoned. + // - memory owned by deque elements is accessible. + // + // Therefore you cannot test, with that function, deque containing objects + // which memory may be partialy (or fully) poisoned, like std::string (SSO case). + // You can test std::vector or long std::string. + + if (empty()) { + for (typename __base::__map_traits::const_pointer __it = __base::__map_.begin(); __it != __base::__map_.end(); + ++__it) + if (!__sanitizer_verify_de_contiguous_container(*__it, *__it, *__it, *__it + __base::__block_size)) + return false; + + return true; + } + + size_type __e = __base::__start_ + __base::size(); + typename __base::__map_traits::const_pointer __first_mp = + __base::__map_.begin() + __base::__start_ / __base::__block_size; + typename __base::__map_traits::const_pointer __last_mp = __base::__map_.begin() + (__e - 1) / __base::__block_size; + + // Pointers to first and last elements + // They can be in *different deque blocks* + pointer __p_first = *__first_mp + (__base::__start_ % __base::__block_size); + pointer __p_last = + *__last_mp + ((__e % __base::__block_size == 0) ? __base::__block_size : __e % __base::__block_size); + + for (typename __base::__map_traits::const_pointer __it = __base::__map_.begin(); __it != __base::__map_.end(); + ++__it) { + // Go over all blocks, find the place we are in and verify its annotations + // Note that __p_last 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_de_contiguous_container(*__it, *__it, *__it, (*__it + __base::__block_size))) + return false; } - return false; - } - - template - void __append(_InpIter __f, _InpIter __l, - typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); - template - void __append(_ForIter __f, _ForIter __l, - typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); - void __append(size_type __n); - void __append(size_type __n, const value_type& __v); - void __erase_to_end(const_iterator __f); - void __add_front_capacity(); - void __add_front_capacity(size_type __n); - void __add_back_capacity(); - void __add_back_capacity(size_type __n); - iterator __move_and_check(iterator __f, iterator __l, iterator __r, - const_pointer& __vt); - iterator __move_backward_and_check(iterator __f, iterator __l, iterator __r, - const_pointer& __vt); - void __move_construct_and_check(iterator __f, iterator __l, - iterator __r, const_pointer& __vt); - void __move_construct_backward_and_check(iterator __f, iterator __l, - iterator __r, const_pointer& __vt); - _LIBCPP_INLINE_VISIBILITY - void __copy_assign_alloc(const deque& __c) - {__copy_assign_alloc(__c, integral_constant());} - - _LIBCPP_INLINE_VISIBILITY - void __copy_assign_alloc(const deque& __c, true_type) + else { + // Is the block the first block that contains elements? + pointer __con_beg = (__it == __first_mp) ? __p_first : *__it; + // Is it the last one? + pointer __con_end = (__it == __last_mp) ? __p_last : (*__it + __base::__block_size); { - if (__base::__alloc() != __c.__alloc()) - { - clear(); - shrink_to_fit(); - } - __base::__alloc() = __c.__alloc(); - __base::__map_.__alloc() = __c.__map_.__alloc(); + if (!__sanitizer_verify_de_contiguous_container(*__it, __con_beg, __con_end, (*__it + __base::__block_size))) + return false; } + } + } - _LIBCPP_INLINE_VISIBILITY - void __copy_assign_alloc(const deque&, false_type) - {} + return true; + } + +private: +#endif // _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS + + _LIBCPP_INLINE_VISIBILITY + bool __maybe_remove_front_spare(bool __keep_one = true) { + if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { + __annotate_unpoison_from_to_back(0, __base::__block_size); + __alloc_traits::deallocate(__base::__alloc(), __base::__map_.front(), __base::__block_size); + __base::__map_.pop_front(); + __base::__start_ -= __base::__block_size; + return true; + } + return false; + } + + _LIBCPP_INLINE_VISIBILITY + bool __maybe_remove_back_spare(bool __keep_one = true) { + if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { + __annotate_unpoison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); + __alloc_traits::deallocate(__base::__alloc(), __base::__map_.back(), __base::__block_size); + __base::__map_.pop_back(); + return true; + } + return false; + } + + template + void __append(_InpIter __f, + _InpIter __l, + typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); + template + void + __append(_ForIter __f, _ForIter __l, typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); + void __append(size_type __n); + void __append(size_type __n, const value_type& __v); + void __erase_to_end(const_iterator __f); + void __add_front_capacity(); + void __add_front_capacity(size_type __n); + void __add_back_capacity(); + void __add_back_capacity(size_type __n); + iterator __move_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + iterator __move_backward_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + void __move_construct_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + void __move_construct_backward_and_check(iterator __f, iterator __l, iterator __r, const_pointer& __vt); + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const deque& __c) { + __copy_assign_alloc(__c, integral_constant()); + } + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const deque& __c, true_type) { + if (__base::__alloc() != __c.__alloc()) { + clear(); + shrink_to_fit(); + } + __base::__alloc() = __c.__alloc(); + __base::__map_.__alloc() = __c.__map_.__alloc(); + } + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const deque&, false_type) {} + + void __move_assign(deque& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); + void __move_assign(deque& __c, false_type); - void __move_assign(deque& __c, true_type) - _NOEXCEPT_(is_nothrow_move_assignable::value); - void __move_assign(deque& __c, false_type); +public: + ~deque() { __annotate_delete(); } }; #if _LIBCPP_STD_VER >= 17 @@ -1621,8 +1963,9 @@ template deque<_Tp, _Allocator>::deque(size_type __n) { - if (__n > 0) - __append(__n); + __annotate_new(0); + if (__n > 0) + __append(__n); } #if _LIBCPP_STD_VER > 11 @@ -1630,16 +1973,18 @@ deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) : __base(__a) { - if (__n > 0) - __append(__n); + __annotate_new(0); + if (__n > 0) + __append(__n); } #endif template deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) { - if (__n > 0) - __append(__n, __v); + __annotate_new(0); + if (__n > 0) + __append(__n, __v); } template @@ -1647,7 +1992,8 @@ deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) { - __append(__f, __l); + __annotate_new(0); + __append(__f, __l); } template @@ -1656,21 +2002,24 @@ typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) : __base(__a) { - __append(__f, __l); + __annotate_new(0); + __append(__f, __l); } template deque<_Tp, _Allocator>::deque(const deque& __c) : __base(__alloc_traits::select_on_container_copy_construction(__c.__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) : __base(__a) { - __append(__c.begin(), __c.end()); + __annotate_new(0); + __append(__c.begin(), __c.end()); } template @@ -1690,14 +2039,16 @@ template deque<_Tp, _Allocator>::deque(initializer_list __il) { - __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) : __base(__a) { - __append(__il.begin(), __il.end()); + __annotate_new(0); + __append(__il.begin(), __il.end()); } template @@ -1839,12 +2190,13 @@ allocator_type& __a = __base::__alloc(); if (empty()) { - while (__base::__map_.size() > 0) - { - __alloc_traits::deallocate(__a, __base::__map_.back(), __base::__block_size); - __base::__map_.pop_back(); - } + __annotate_delete(); + while (__base::__map_.size() > 0) { + __alloc_traits::deallocate(__a, __base::__map_.back(), __base::__block_size); + __base::__map_.pop_back(); + } __base::__start_ = 0; + __annotate_new(0); } else { @@ -1938,6 +2290,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), __v); ++__base::size(); } @@ -1950,6 +2303,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v); --__base::__start_; ++__base::size(); @@ -1964,6 +2318,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), _VSTD::move(__v)); ++__base::size(); } @@ -1981,6 +2336,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), _VSTD::forward<_Args>(__args)...); ++__base::size(); @@ -1997,6 +2353,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::move(__v)); --__base::__start_; ++__base::size(); @@ -2016,6 +2373,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::forward<_Args>(__args)...); --__base::__start_; ++__base::size(); @@ -2036,6 +2394,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::move(__v)); @@ -2059,6 +2418,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = __base::size() - __pos; if (__de == 0) { @@ -2092,6 +2452,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), _VSTD::forward<_Args>(__args)...); @@ -2116,6 +2477,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = __base::size() - __pos; if (__de == 0) { @@ -2152,6 +2514,7 @@ if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v); @@ -2178,6 +2541,7 @@ if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = __base::size() - __pos; if (__de == 0) { @@ -2213,6 +2577,7 @@ if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = __base::begin(); iterator __i = __old_begin; if (__n > __pos) @@ -2237,6 +2602,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = __base::end(); iterator __i = __old_end; size_type __de = __base::size() - __pos; @@ -2299,6 +2665,7 @@ if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = __base::begin(); iterator __i = __old_begin; _BiIter __m = __f; @@ -2329,6 +2696,7 @@ if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = __base::end(); iterator __i = __old_end; _BiIter __m = __l; @@ -2379,6 +2747,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(__base::end(), __base::end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) { @@ -2396,6 +2765,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(__base::end(), __base::end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -2413,6 +2783,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(__base::end(), __base::end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -2454,6 +2825,7 @@ __base::__start_ = __base::__map_.size() == 1 ? __base::__block_size / 2 : __base::__start_ + __base::__block_size; + __annotate_poison_from_to_back(0, __base::__block_size); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -2479,6 +2851,7 @@ __base::__start_ = __base::__map_.size() == 1 ? __base::__block_size / 2 : __base::__start_ + __base::__block_size; + __annotate_poison_from_to_back(0, __base::__block_size); } } @@ -2515,6 +2888,7 @@ if (__base::__map_.__front_spare() == 0) break; __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); + __annotate_poison_from_to_back(0, __base::__block_size); } for (; __nb > 0; --__nb, ++__back_capacity) __base::__map_.push_back(__alloc_traits::allocate(__a, __base::__block_size)); @@ -2525,6 +2899,7 @@ pointer __pt = __base::__map_.back(); __base::__map_.pop_back(); __base::__map_.push_front(__pt); + __annotate_poison_from_to_back(0, __base::__block_size); } } // Else need to allocate __nb buffers, *and* we need to reallocate __map_. @@ -2539,16 +2914,24 @@ try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __nb > 0; --__nb) - __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + for (; __nb > 0; --__nb) { + __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + // ASan: this is empty container, we have to poison whole + __annotate_contiguous_container_back( + std::__to_address(__buf.back()), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back()), + std::__to_address(__buf.back())); + } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - for (typename __base::__map_pointer __i = __buf.begin(); - __i != __buf.end(); ++__i) - __alloc_traits::deallocate(__a, *__i, __base::__block_size); - throw; + __annotate_delete(); + for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) + __alloc_traits::deallocate(__a, *__i, __base::__block_size); + throw; } #endif // _LIBCPP_NO_EXCEPTIONS for (; __back_capacity > 0; --__back_capacity) @@ -2596,6 +2979,8 @@ __base::__map_.pop_front(); __base::__map_.push_back(__pt); } + __annotate_poison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -2619,6 +3004,8 @@ _VSTD::swap(__base::__map_.__begin_, __buf.__begin_); _VSTD::swap(__base::__map_.__end_, __buf.__end_); _VSTD::swap(__base::__map_.__end_cap(), __buf.__end_cap()); + __annotate_poison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); } } @@ -2655,10 +3042,14 @@ if (__base::__map_.__back_spare() == 0) break; __base::__map_.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + __annotate_poison_from_to_back( + (__base::__map_.size() - 1) * __base::__block_size, __base::__map_.size() * __base::__block_size); + } + for (; __nb > 0; + --__nb, ++__front_capacity, __base::__start_ += __base::__block_size - (__base::__map_.size() == 1)) { + __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); + __annotate_poison_from_to_back(0, __base::__block_size); } - for (; __nb > 0; --__nb, ++__front_capacity, __base::__start_ += - __base::__block_size - (__base::__map_.size() == 1)) - __base::__map_.push_front(__alloc_traits::allocate(__a, __base::__block_size)); // Done allocating, reorder capacity __base::__start_ -= __base::__block_size * __front_capacity; for (; __front_capacity > 0; --__front_capacity) @@ -2681,16 +3072,24 @@ try { #endif // _LIBCPP_NO_EXCEPTIONS - for (; __nb > 0; --__nb) - __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + for (; __nb > 0; --__nb) { + __buf.push_back(__alloc_traits::allocate(__a, __base::__block_size)); + // ASan: this is empty container, we have to poison whole + __annotate_contiguous_container_back( + std::__to_address(__buf.back()), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back() + __base::__block_size), + std::__to_address(__buf.back()), + std::__to_address(__buf.back())); + } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - for (typename __base::__map_pointer __i = __buf.begin(); - __i != __buf.end(); ++__i) - __alloc_traits::deallocate(__a, *__i, __base::__block_size); - throw; + __annotate_delete(); + for (typename __base::__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) + __alloc_traits::deallocate(__a, *__i, __base::__block_size); + throw; } #endif // _LIBCPP_NO_EXCEPTIONS for (; __front_capacity > 0; --__front_capacity) @@ -2713,13 +3112,16 @@ void deque<_Tp, _Allocator>::pop_front() { - allocator_type& __a = __base::__alloc(); - __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + - __base::__start_ / __base::__block_size) + - __base::__start_ % __base::__block_size)); - --__base::size(); - ++__base::__start_; - __maybe_remove_front_spare(); + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + allocator_type& __a = __base::__alloc(); + __alloc_traits::destroy(__a, + _VSTD::__to_address(*(__base::__map_.begin() + __base::__start_ / __base::__block_size) + + __base::__start_ % __base::__block_size)); + --__base::size(); + ++__base::__start_; + __annotate_shrink_front(__old_sz, __old_start); + __maybe_remove_front_spare(); } template @@ -2727,12 +3129,15 @@ deque<_Tp, _Allocator>::pop_back() { _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque"); + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; allocator_type& __a = __base::__alloc(); size_type __p = __base::size() + __base::__start_ - 1; __alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() + __p / __base::__block_size) + __p % __base::__block_size)); --__base::size(); + __annotate_shrink_back(__old_sz, __old_start); __maybe_remove_back_spare(); } @@ -2872,25 +3277,26 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f) { - iterator __b = __base::begin(); - difference_type __pos = __f - __b; - iterator __p = __b + __pos; - allocator_type& __a = __base::__alloc(); - if (static_cast(__pos) <= (__base::size() - 1) / 2) - { // erase from front - _VSTD::move_backward(__b, __p, _VSTD::next(__p)); - __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); - --__base::size(); - ++__base::__start_; - __maybe_remove_front_spare(); - } - else - { // erase from back - iterator __i = _VSTD::move(_VSTD::next(__p), __base::end(), __p); - __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); - --__base::size(); - __maybe_remove_back_spare(); - } + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + iterator __b = __base::begin(); + difference_type __pos = __f - __b; + iterator __p = __b + __pos; + allocator_type& __a = __base::__alloc(); + if (static_cast(__pos) <= (__base::size() - 1) / 2) { // erase from front + _VSTD::move_backward(__b, __p, _VSTD::next(__p)); + __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); + --__base::size(); + ++__base::__start_; + __annotate_shrink_front(__old_sz, __old_start); + __maybe_remove_front_spare(); + } else { // erase from back + iterator __i = _VSTD::move(_VSTD::next(__p), __base::end(), __p); + __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); + --__base::size(); + __annotate_shrink_back(__old_sz, __old_start); + __maybe_remove_back_spare(); + } return __base::begin() + __pos; } @@ -2898,33 +3304,33 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) { - difference_type __n = __l - __f; - iterator __b = __base::begin(); - difference_type __pos = __f - __b; - iterator __p = __b + __pos; - if (__n > 0) - { - allocator_type& __a = __base::__alloc(); - if (static_cast(__pos) <= (__base::size() - __n) / 2) - { // erase from front - iterator __i = _VSTD::move_backward(__b, __p, __p + __n); - for (; __b != __i; ++__b) - __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); - __base::size() -= __n; - __base::__start_ += __n; - while (__maybe_remove_front_spare()) { - } - } - else - { // erase from back - iterator __i = _VSTD::move(__p + __n, __base::end(), __p); - for (iterator __e = __base::end(); __i != __e; ++__i) - __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); - __base::size() -= __n; - while (__maybe_remove_back_spare()) { - } - } + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + difference_type __n = __l - __f; + iterator __b = __base::begin(); + difference_type __pos = __f - __b; + iterator __p = __b + __pos; + if (__n > 0) { + allocator_type& __a = __base::__alloc(); + if (static_cast(__pos) <= (__base::size() - __n) / 2) { // erase from front + iterator __i = _VSTD::move_backward(__b, __p, __p + __n); + for (; __b != __i; ++__b) + __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); + __base::size() -= __n; + __base::__start_ += __n; + __annotate_shrink_front(__old_sz, __old_start); + while (__maybe_remove_front_spare()) { + } + } else { // erase from back + iterator __i = _VSTD::move(__p + __n, __base::end(), __p); + for (iterator __e = __base::end(); __i != __e; ++__i) + __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); + __base::size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); + while (__maybe_remove_back_spare()) { + } } + } return __base::begin() + __pos; } @@ -2932,19 +3338,21 @@ void deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) { - iterator __e = __base::end(); - difference_type __n = __e - __f; - if (__n > 0) - { - allocator_type& __a = __base::__alloc(); - iterator __b = __base::begin(); - difference_type __pos = __f - __b; - for (iterator __p = __b + __pos; __p != __e; ++__p) - __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); - __base::size() -= __n; - while (__maybe_remove_back_spare()) { - } + size_type __old_sz = __base::size(); + size_type __old_start = __base::__start_; + iterator __e = __base::end(); + difference_type __n = __e - __f; + if (__n > 0) { + allocator_type& __a = __base::__alloc(); + iterator __b = __base::begin(); + difference_type __pos = __f - __b; + for (iterator __p = __b + __pos; __p != __e; ++__p) + __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); + __base::size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); + while (__maybe_remove_back_spare()) { } + } } template @@ -2966,7 +3374,9 @@ void deque<_Tp, _Allocator>::clear() _NOEXCEPT { - __base::clear(); + __annotate_delete(); + __base::clear(); + __annotate_new(0); } template diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/assign.pass.cpp @@ -0,0 +1,462 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +#if TEST_STD_VER >= 11 +template +void test_assign_d5(const size_t N) { + typedef std::deque D; + D empty_d5; + D short_d5a(1), short_d5b(N - 1); + D mid_d5(N + 1); + D long_d5(32 * N + 1); + + empty_d5.assign({T(), T()}); + short_d5a.assign({T(), T()}); + short_d5b.assign({T(), T()}); + mid_d5.assign({T(), T()}); + long_d5.assign({T(), T()}); + + assert(is_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_contiguous_container_asan_correct(long_d5)); + + empty_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d5a.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d5b.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + mid_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + long_d5.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + + assert(empty_d5.size() > 16); + assert(short_d5a.size() > 16); + assert(short_d5b.size() > 16); + assert(mid_d5.size() > 16); + assert(long_d5.size() > 16); + + assert(is_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_contiguous_container_asan_correct(long_d5)); +} + +template +void test_assign_d6(const size_t N) { + typedef std::deque D; + D empty_d6; + D short_d6a(1), short_d6b(N - 1); + D mid_d6(N + 1); + D long_d6(32 * N + 1); + + empty_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d6a.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + short_d6b.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + mid_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + long_d6.assign({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + + assert(empty_d6.size() > 16); + assert(short_d6a.size() > 16); + assert(short_d6b.size() > 16); + assert(mid_d6.size() > 16); + assert(long_d6.size() > 16); + + assert(is_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6)); + assert(is_de_contiguous_container_asan_correct(long_d6)); +} + +template +void test_assign_d7(const size_t N) { + typedef std::deque D; + const T val = T(); + D empty_d7; + D short_d7a(1), short_d7b(N - 1); + D mid_d7(N + 1); + D long_d7(32 * N + 1); + + empty_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + short_d7a.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + short_d7b.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + mid_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + long_d7.assign({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + + assert(empty_d7.size() > 16); + assert(short_d7a.size() > 16); + assert(short_d7b.size() > 16); + assert(mid_d7.size() > 16); + assert(long_d7.size() > 16); + + assert(is_de_contiguous_container_asan_correct(empty_d7)); + assert(is_de_contiguous_container_asan_correct(short_d7a)); + assert(is_de_contiguous_container_asan_correct(short_d7b)); + assert(is_de_contiguous_container_asan_correct(mid_d7)); + assert(is_de_contiguous_container_asan_correct(long_d7)); +} +#endif + +template +void test_assign() { + typedef std::deque D; + const size_t N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void assign( size_type count, const T& value ); + + D empty_d1; + D short_d1a(1), short_d1b(N - 1); + D mid_d1(N + 1); + D long_d1(32 * N + 1); + + empty_d1.assign(2, T()); + short_d1a.assign(2, T()); + short_d1b.assign(2, T()); + mid_d1.assign(2, T()); + long_d1.assign(2, T()); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + assert(is_de_contiguous_container_asan_correct(long_d1)); + + empty_d1.assign(2 * N, T()); + short_d1a.assign(2 * N, T()); + short_d1b.assign(2 * N, T()); + mid_d1.assign(2 * N, T()); + long_d1.assign(2 * N, T()); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + assert(is_de_contiguous_container_asan_correct(long_d1)); + + D empty_d2; + D short_d2a(1), short_d2b(N - 1); + D mid_d2(N + 1); + D long_d2(32 * N + 1); + + empty_d2.assign(42 * N, T()); + short_d2a.assign(42 * N, T()); + short_d2b.assign(42 * N, T()); + mid_d2.assign(42 * N, T()); + long_d2.assign(42 * N, T()); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2)); + assert(is_de_contiguous_container_asan_correct(long_d2)); + + // template< class InputIt > + // void assign( InputIt first, InputIt last ); + D source_d(50 * N); + + D empty_d3; + D short_d3a(1), short_d3b(N - 1); + D mid_d3(N + 1); + D long_d3(32 * N + 1); + + empty_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + short_d3a.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + short_d3b.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + mid_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + long_d3.assign(source_d.begin() + N - 1, source_d.begin() + N + 1); + + assert(is_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3)); + assert(is_de_contiguous_container_asan_correct(long_d3)); + assert(is_de_contiguous_container_asan_correct(source_d)); + + empty_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); + short_d3a.assign(source_d.begin() + N, source_d.begin() + 3 * N); + short_d3b.assign(source_d.begin() + N, source_d.begin() + 3 * N); + mid_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); + long_d3.assign(source_d.begin() + N, source_d.begin() + 3 * N); + + assert(is_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3)); + assert(is_de_contiguous_container_asan_correct(long_d3)); + assert(is_de_contiguous_container_asan_correct(source_d)); + + D empty_d4; + D short_d4a(1), short_d4b(N - 1); + D mid_d4(N + 1); + D long_d4(32 * N + 1); + + empty_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + short_d4a.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + short_d4b.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + mid_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + long_d4.assign(source_d.end() - 42 * N - 1, source_d.end() - 1); + + assert(is_de_contiguous_container_asan_correct(empty_d4)); + assert(is_de_contiguous_container_asan_correct(short_d4a)); + assert(is_de_contiguous_container_asan_correct(short_d4b)); + assert(is_de_contiguous_container_asan_correct(mid_d4)); + assert(is_de_contiguous_container_asan_correct(long_d4)); + assert(is_de_contiguous_container_asan_correct(source_d)); + +#if TEST_STD_VER >= 11 + // void assign( std::initializer_list ilist ); + test_assign_d5(N); + test_assign_d6(N); + test_assign_d7(N); +#endif +} + +template +void test_operator() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // deque& operator=( const deque& other ); + + D empty_d1, empty_d2; + D mid_d1(N), mid_d2(N); + D long_d1(32 * N), long_d2(32 * N); + + empty_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d2)); + empty_d1 = mid_d1; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + empty_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d2)); + empty_d1 = long_d1; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(long_d1)); + empty_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d2)); + + empty_d2 = long_d1; + assert(is_de_contiguous_container_asan_correct(empty_d2)); + + mid_d1 = long_d1; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + mid_d1 = empty_d2; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + mid_d1 = long_d1; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + mid_d1 = mid_d2; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + + long_d1 = long_d2; + assert(is_de_contiguous_container_asan_correct(long_d1)); + long_d1 = empty_d1; + assert(is_de_contiguous_container_asan_correct(long_d1)); + long_d1 = long_d2; + assert(is_de_contiguous_container_asan_correct(long_d1)); + + empty_d1 = D(); + assert(is_de_contiguous_container_asan_correct(empty_d1)); + mid_d1 = D(); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + long_d1 = D(); + assert(is_de_contiguous_container_asan_correct(long_d1)); + + mid_d1 = mid_d2; + assert(is_de_contiguous_container_asan_correct(mid_d1)); + long_d1 = long_d2; + assert(is_de_contiguous_container_asan_correct(long_d1)); + + // deque& operator=( deque&& other ) + +#if TEST_STD_VER >= 11 + mid_d1 = std::move(mid_d2); + assert(is_de_contiguous_container_asan_correct(mid_d1)); + assert(is_de_contiguous_container_asan_correct(mid_d2)); + long_d1 = std::move(long_d2); + assert(is_de_contiguous_container_asan_correct(long_d1)); + assert(is_de_contiguous_container_asan_correct(long_d2)); + + D mid_d3a(N), mid_d3b(N); + D long_d3a(32 * N), long_d3b(32 * N); + + mid_d3a = std::move(long_d3a); + long_d3b = std::move(mid_d3b); + assert(is_de_contiguous_container_asan_correct(mid_d3a)); + assert(is_de_contiguous_container_asan_correct(mid_d3b)); + assert(is_de_contiguous_container_asan_correct(long_d3a)); + assert(is_de_contiguous_container_asan_correct(long_d3b)); + + D empty_d4; + D long_d4a(32 * N), long_d4b(32 * N); + + long_d4a = std::move(empty_d4); + long_d4b = std::move(empty_d1); + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(empty_d4)); + assert(is_de_contiguous_container_asan_correct(long_d4a)); + assert(is_de_contiguous_container_asan_correct(long_d4b)); +#endif + + // void assign( std::initializer_list ilist ) + + D empty_d5; + D short_d5a(1), short_d5b(N - 1); + D mid_d5(N + 1); + D long_d5(32 * N + 1); + + empty_d5 = {T(), T()}; + short_d5a = {T(), T()}; + short_d5b = {T(), T()}; + mid_d5 = {T(), T()}; + long_d5 = {T(), T()}; + + assert(is_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_contiguous_container_asan_correct(long_d5)); + + empty_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d5a = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d5b = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + mid_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + long_d5 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + + assert(empty_d5.size() > 16); + assert(short_d5a.size() > 16); + assert(short_d5b.size() > 16); + assert(mid_d5.size() > 16); + assert(long_d5.size() > 16); + + assert(is_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5)); + assert(is_de_contiguous_container_asan_correct(long_d5)); + + D empty_d6; + D short_d6a(1), short_d6b(N - 1); + D mid_d6(N + 1); + D long_d6(32 * N + 1); + + empty_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d6a = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + short_d6b = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + mid_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + long_d6 = {T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}; + + assert(empty_d6.size() > 16); + assert(short_d6a.size() > 16); + assert(short_d6b.size() > 16); + assert(mid_d6.size() > 16); + assert(long_d6.size() > 16); + + assert(is_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6)); + assert(is_de_contiguous_container_asan_correct(long_d6)); + + empty_d6 = {}; + short_d6a = {}; + short_d6b = {}; + mid_d6 = {}; + long_d6 = {}; + + assert(is_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6)); + assert(is_de_contiguous_container_asan_correct(long_d6)); + + + D empty_d7; + D short_d7a(1), short_d7b(N - 1); + D mid_d7(N + 1); + D long_d7a(32 * N + 1), long_d7b(32 * N + 1); + + empty_d7 = {}; + short_d7a = {}; + short_d7b = {}; + mid_d7 = {}; + long_d7a = {}; + + long_d7b.pop_front(); + long_d7b = {}; + + assert(is_de_contiguous_container_asan_correct(empty_d7)); + assert(is_de_contiguous_container_asan_correct(short_d7a)); + assert(is_de_contiguous_container_asan_correct(short_d7b)); + assert(is_de_contiguous_container_asan_correct(mid_d7)); + assert(is_de_contiguous_container_asan_correct(long_d7a)); + assert(is_de_contiguous_container_asan_correct(long_d7b)); +} + +template +void test() { + test_assign(); + test_operator(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/clear.pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void clear() + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.clear(); + short_d1a.clear(); + short_d1b.clear(); + mid_d1a.clear(); + mid_d1b.clear(); + mid_d1c.clear(); + long_d1a.clear(); + long_d1b.clear(); + long_d1c.clear(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + typedef std::deque D; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/constructor.pass.cpp @@ -0,0 +1,313 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // Different constructors are called based on the used standard. + // Please, check https://en.cppreference.com/w/cpp/container/deque/deque + // for full list. + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + D empty_d2(empty_d1); + D short_d2a(short_d1a), short_d2b(short_d1b); + D mid_d2a(mid_d1a), mid_d2b(mid_d1b), mid_d2c(mid_d1c); + D long_d2a(long_d1a), long_d2b(long_d1b), long_d2c(long_d1c); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + D empty_d3(std::move(empty_d2)); + D short_d3a(std::move(short_d2a)), short_d3b(std::move(short_d2b)); + D mid_d3a(std::move(mid_d2a)), mid_d3b(std::move(mid_d2b)), mid_d3c(std::move(mid_d2c)); + D long_d3a(std::move(long_d2a)), long_d3b(std::move(long_d2b)), long_d3c(std::move(long_d2c)); + + assert(is_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3a)); + assert(is_de_contiguous_container_asan_correct(mid_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3c)); + assert(is_de_contiguous_container_asan_correct(long_d3a)); + assert(is_de_contiguous_container_asan_correct(long_d3b)); + assert(is_de_contiguous_container_asan_correct(long_d3c)); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); + +#if TEST_STD_VER >= 11 + D empty_d4(empty_d1.cbegin(), empty_d1.cend()); + D short_d4a(short_d1a.cbegin(), short_d1a.cend()), short_d4b(short_d1b.cbegin(), short_d1b.cend()); + D mid_d4a(mid_d1a.cbegin(), mid_d1a.cend()), mid_d4b(mid_d1b.cbegin(), mid_d1b.cend()), + mid_d4c(mid_d1c.cbegin(), mid_d1c.cend()); + D long_d4a(long_d1a.cbegin(), long_d1a.cend()), long_d4b(long_d1a.cbegin(), long_d1a.cend()), + long_d4c(long_d1a.cbegin(), long_d1a.cend()); +#else + D empty_d4(empty_d1.begin(), empty_d1.end()); + D short_d4a(short_d1a.begin(), short_d1a.end()), short_d4b(short_d1b.begin(), short_d1b.end()); + D mid_d4a(mid_d1a.begin(), mid_d1a.end()), mid_d4b(mid_d1b.begin(), mid_d1b.end()), + mid_d4c(mid_d1c.begin(), mid_d1c.end()); + D long_d4a(long_d1a.begin(), long_d1a.end()), long_d4b(long_d1a.begin(), long_d1a.end()), + long_d4c(long_d1a.begin(), long_d1a.end()); +#endif + + assert(is_de_contiguous_container_asan_correct(empty_d4)); + assert(is_de_contiguous_container_asan_correct(short_d4a)); + assert(is_de_contiguous_container_asan_correct(short_d4b)); + assert(is_de_contiguous_container_asan_correct(mid_d4a)); + assert(is_de_contiguous_container_asan_correct(mid_d4b)); + assert(is_de_contiguous_container_asan_correct(mid_d4c)); + assert(is_de_contiguous_container_asan_correct(long_d4a)); + assert(is_de_contiguous_container_asan_correct(long_d4b)); + assert(is_de_contiguous_container_asan_correct(long_d4c)); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + +#if TEST_STD_VER >= 11 + D empty_d5(empty_d1.crbegin(), empty_d1.crend()); + D short_d5a(short_d1a.crbegin(), short_d1a.crend()), short_d5b(short_d1b.crbegin(), short_d1b.crend()); + D mid_d5a(mid_d1a.crbegin(), mid_d1a.crend()), mid_d5b(mid_d1b.crbegin(), mid_d1b.crend()), + mid_d5c(mid_d1c.crbegin(), mid_d1c.crend()); + D long_d5a(long_d1a.crbegin(), long_d1a.crend()), long_d5b(long_d1a.crbegin(), long_d1a.crend()), + long_d5c(long_d1a.crbegin(), long_d1a.crend()); +#else + D empty_d5(empty_d1.rbegin(), empty_d1.rend()); + D short_d5a(short_d1a.rbegin(), short_d1a.rend()), short_d5b(short_d1b.rbegin(), short_d1b.rend()); + D mid_d5a(mid_d1a.rbegin(), mid_d1a.rend()), mid_d5b(mid_d1b.rbegin(), mid_d1b.rend()), + mid_d5c(mid_d1c.rbegin(), mid_d1c.rend()); + D long_d5a(long_d1a.rbegin(), long_d1a.rend()), long_d5b(long_d1a.rbegin(), long_d1a.rend()), + long_d5c(long_d1a.rbegin(), long_d1a.rend()); +#endif + + assert(is_de_contiguous_container_asan_correct(empty_d5)); + assert(is_de_contiguous_container_asan_correct(short_d5a)); + assert(is_de_contiguous_container_asan_correct(short_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5a)); + assert(is_de_contiguous_container_asan_correct(mid_d5b)); + assert(is_de_contiguous_container_asan_correct(mid_d5c)); + assert(is_de_contiguous_container_asan_correct(long_d5a)); + assert(is_de_contiguous_container_asan_correct(long_d5b)); + assert(is_de_contiguous_container_asan_correct(long_d5c)); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + D empty_d6(0, T()); + D short_d6a(1, T()), short_d6b(2, T()); + D mid_d6a(N - 1, T()), mid_d6b(N, T()), mid_d6c(N + 1, T()); + D long_d6a(17 * N - 1, T()), long_d6b(8 * N, T()), long_d6c(11 * N + 1, T()); + + assert(is_de_contiguous_container_asan_correct(empty_d6)); + assert(is_de_contiguous_container_asan_correct(short_d6a)); + assert(is_de_contiguous_container_asan_correct(short_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6a)); + assert(is_de_contiguous_container_asan_correct(mid_d6b)); + assert(is_de_contiguous_container_asan_correct(mid_d6c)); + assert(is_de_contiguous_container_asan_correct(long_d6a)); + assert(is_de_contiguous_container_asan_correct(long_d6b)); + assert(is_de_contiguous_container_asan_correct(long_d6c)); + +#if TEST_STD_VER >= 11 + D empty_d7({}); + D short_d7a({T()}), short_d7b({T(), T()}); + D mid_d7a({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + D mid_d7b({T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T(), T()}); + + assert(is_de_contiguous_container_asan_correct(empty_d7)); + assert(is_de_contiguous_container_asan_correct(short_d7a)); + assert(is_de_contiguous_container_asan_correct(short_d7b)); + assert(mid_d7a.size() == 16); + assert(is_de_contiguous_container_asan_correct(mid_d7a)); + assert(mid_d7b.size() == 17); + assert(is_de_contiguous_container_asan_correct(mid_d7b)); + + const T val = T(); + D empty_d8({}); + D short_d8a({val}), short_d8b({val, val}); + D mid_d8a({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + D mid_d8b({val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}); + + assert(is_de_contiguous_container_asan_correct(empty_d8)); + assert(is_de_contiguous_container_asan_correct(short_d8a)); + assert(is_de_contiguous_container_asan_correct(short_d8b)); + assert(mid_d8a.size() == 16); + assert(is_de_contiguous_container_asan_correct(mid_d8a)); + assert(mid_d8b.size() == 17); + assert(is_de_contiguous_container_asan_correct(mid_d8b)); +#endif + + D empty_d9a((std::allocator())), empty_d9b(empty_d8.get_allocator()); + assert(is_de_contiguous_container_asan_correct(empty_d9a)); + assert(is_de_contiguous_container_asan_correct(empty_d9b)); + +#if TEST_STD_VER >= 11 + D empty_d10(empty_d3, std::allocator()); + D short_d10a(short_d3a, std::allocator()), short_d10b(short_d3b, std::allocator()); + D mid_d10a(mid_d3a, std::allocator()), mid_d10b(mid_d3b, std::allocator()), + mid_d10c(mid_d3c, std::allocator()); + D long_d10a(long_d3a, std::allocator()), long_d10b(long_d3b, std::allocator()), + long_d10c(long_d3c, std::allocator()); + + assert(is_de_contiguous_container_asan_correct(empty_d10)); + assert(is_de_contiguous_container_asan_correct(short_d10a)); + assert(is_de_contiguous_container_asan_correct(short_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10a)); + assert(is_de_contiguous_container_asan_correct(mid_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10c)); + assert(is_de_contiguous_container_asan_correct(long_d10a)); + assert(is_de_contiguous_container_asan_correct(long_d10b)); + assert(is_de_contiguous_container_asan_correct(long_d10c)); + + assert(is_de_contiguous_container_asan_correct(empty_d3)); + assert(is_de_contiguous_container_asan_correct(short_d3a)); + assert(is_de_contiguous_container_asan_correct(short_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3a)); + assert(is_de_contiguous_container_asan_correct(mid_d3b)); + assert(is_de_contiguous_container_asan_correct(mid_d3c)); + assert(is_de_contiguous_container_asan_correct(long_d3a)); + assert(is_de_contiguous_container_asan_correct(long_d3b)); + assert(is_de_contiguous_container_asan_correct(long_d3c)); + + D empty_d11(std::move(empty_d10), std::allocator()); + D short_d11a(std::move(short_d10a), std::allocator()), short_d11b(std::move(short_d10b), std::allocator()); + D mid_d11a(std::move(mid_d10a), std::allocator()), mid_d11b(std::move(mid_d10b), std::allocator()), + mid_d11c(std::move(mid_d10c), std::allocator()); + D long_d11a(std::move(long_d10a), std::allocator()), long_d11b(std::move(long_d10b), std::allocator()), + long_d11c(std::move(long_d10c), std::allocator()); + + assert(is_de_contiguous_container_asan_correct(empty_d11)); + assert(is_de_contiguous_container_asan_correct(short_d11a)); + assert(is_de_contiguous_container_asan_correct(short_d11b)); + assert(is_de_contiguous_container_asan_correct(mid_d11a)); + assert(is_de_contiguous_container_asan_correct(mid_d11b)); + assert(is_de_contiguous_container_asan_correct(mid_d11c)); + assert(is_de_contiguous_container_asan_correct(long_d11a)); + assert(is_de_contiguous_container_asan_correct(long_d11b)); + assert(is_de_contiguous_container_asan_correct(long_d11c)); + + assert(is_de_contiguous_container_asan_correct(empty_d10)); + assert(is_de_contiguous_container_asan_correct(short_d10a)); + assert(is_de_contiguous_container_asan_correct(short_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10a)); + assert(is_de_contiguous_container_asan_correct(mid_d10b)); + assert(is_de_contiguous_container_asan_correct(mid_d10c)); + assert(is_de_contiguous_container_asan_correct(long_d10a)); + assert(is_de_contiguous_container_asan_correct(long_d10b)); + assert(is_de_contiguous_container_asan_correct(long_d10c)); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/emplace_constructible.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// The test helped us find issues with llvm12 implementation, +// but it's a problematic one now. +// We may want to delete it. + +// UNSUPPORTED: c++03 + +#include +#include +#include "emplace_constructible.h" +#include "asan_testing.h" // includes deque - don't do it before +#include "test_iterators.h" + +template +void test_constructible() { + T arr1[] = {T()}; + using T2 = EmplaceConstructibleMoveableAndAssignable; + using It = cpp17_input_iterator; + typedef std::deque D; + + D d; + d.assign(It(arr1), It(std::end(arr1))); + assert(is_de_contiguous_container_asan_correct(d)); +} + +template +void test() { + test_constructible(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/erase.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // iterator erase( iterator first, iterator last ); + // iterator erase( const_iterator first, const_iterator last ); + + D d1a(N), d1b(N), d1c(N); +#if TEST_STD_VER >= 11 + d1a.erase(d1a.cbegin(), d1a.cend()); + d1b.erase(d1b.cbegin() + 1); + d1c.erase(d1c.cend() - 1); +#else + d1a.erase(d1a.begin(), d1a.end()); + d1b.erase(d1b.begin() + 1); + d1c.erase(d1c.end() - 1); +#endif + + assert(is_de_contiguous_container_asan_correct(d1a)); + assert(is_de_contiguous_container_asan_correct(d1b)); + assert(is_de_contiguous_container_asan_correct(d1c)); + + D d2a(N + 1), d2b(N + 1), d2c(N + 1), d2d(N + 1); + + d2a.erase(d2a.begin(), d2a.end() - 2); + d2b.erase(d2b.begin() + 1, d2b.end()); + // iterator erase( iterator pos ); + // iterator erase( const_iterator pos ); + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2c.erase(d2c.begin() + 2); + d2d.erase(d2d.end() - 3); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + D d3a(32 * N + 1), d3b(32 * N + 1), d3c(32 * N + 1), d3d(32 * N + 1); + + d3a.erase(d3a.begin() + N + 1, d3a.end() - N - 2); + d3b.erase(d3b.begin() + N - 1, d3b.end()); + + assert(is_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + while (d3c.size() > 3) { + d3c.erase(d3c.begin() + 2); + assert(is_de_contiguous_container_asan_correct(d3c)); + } + while (d3d.size() > 4) { + d3d.erase(d3d.end() - 3); + assert(is_de_contiguous_container_asan_correct(d3d)); + } + + D d4a(32 * N + 3), d4b(32 * N + 3); + while (d4a.size() > 5) { + d4a.erase(d4a.begin() + 2, d4a.begin() + 4); + assert(is_de_contiguous_container_asan_correct(d4a)); + } + + while (d4b.size() > 5) { + d4b.erase(d4b.end() - 4, d4b.end() - 2); + assert(is_de_contiguous_container_asan_correct(d4b)); + } +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/insert.pass.cpp @@ -0,0 +1,278 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_insert() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + T t = T(); + D d1a(2), d1b(2), d1c(2); + +#if TEST_STD_VER >= 11 + d1a.insert(d1a.cbegin(), t); + d1b.insert(d1b.cend(), t); + d1c.insert(d1c.cbegin() + 1, t); +#else + d1a.insert(d1a.begin(), t); + d1b.insert(d1b.end(), t); + d1c.insert(d1c.begin() + 1, t); +#endif + + assert(is_de_contiguous_container_asan_correct(d1a)); + assert(is_de_contiguous_container_asan_correct(d1b)); + assert(is_de_contiguous_container_asan_correct(d1c)); + + D d2a(3 * N), d2b(3 * N), d2c(3 * N), d2d(3 * N); + + d2a.insert(d2a.begin(), t); + d2b.insert(d2b.end(), t); + d2c.insert(d2c.begin() + 1, t); + d2d.insert(d2d.end() - 1, t); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), 2 * N + 1, t); + d2b.insert(d2b.end(), 2 * N + 1, t); + d2c.insert(d2c.begin() + 1, 2 * N + 1, t); + d2d.insert(d2d.end() - 1, 2 * N + 1, t); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2c.insert(d2c.begin() + N + 1, 2 * N + 1, t); + d2d.insert(d2d.end() - N - 1, 2 * N + 1, t); + + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + D source(3 * N); + + d2a.insert(d2a.begin(), source.begin() + 1, source.end() - 1); + d2b.insert(d2b.end(), source.begin() + 1, source.end() - 1); + d2c.insert(d2c.begin() + 1, source.begin() + 1, source.end() - 1); + d2d.insert(d2d.end() - 1, source.begin() + 1, source.end() - 1); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2c.insert(d2c.begin() + N + 1, source.begin() + 1, source.end() - 1); + d2d.insert(d2d.end() - N - 1, source.begin() + 1, source.end() - 1); + + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), T()); + d2b.insert(d2b.end(), T()); + d2c.insert(d2c.begin() + 1, T()); + d2d.insert(d2d.end() - 1, T()); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + T a = T(), b = T(), c = T(), d = T(); + d2a.insert(d2a.begin(), a); + d2b.insert(d2b.end(), b); + d2c.insert(d2c.begin() + 1, c); + d2d.insert(d2d.end() - 1, d); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), 3, a); + d2b.insert(d2b.end(), 3, b); + d2c.insert(d2c.begin() + 1, 3, c); + d2d.insert(d2d.end() - 1, 3, d); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), 3 * N, a); + d2b.insert(d2b.end(), 3 * N, b); + d2c.insert(d2c.begin() + 1, 3 * N, c); + d2d.insert(d2d.end() - 1, 3 * N, d); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2a.insert(d2a.begin(), std::move(a)); + d2b.insert(d2b.end(), std::move(b)); + d2c.insert(d2c.begin() + 1, std::move(c)); + d2d.insert(d2d.end() - 1, std::move(d)); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + +#if TEST_STD_VER >= 11 + D d3a(2), d3b(2), d3c(2); + + d3a.insert(d3a.cbegin(), {t}); + d3b.insert(d3b.cend(), {t}); + d3c.insert(d3c.cbegin() + 1, {t}); + + assert(is_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + assert(is_de_contiguous_container_asan_correct(d3c)); + + d3a.insert(d3a.cbegin(), {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3b.insert(d3b.cend(), {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3c.insert(d3c.cbegin() + 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + + assert(d3a.size() > 16); + assert(d3b.size() > 16); + assert(d3c.size() > 16); + + assert(is_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + assert(is_de_contiguous_container_asan_correct(d3c)); + + d3a.insert(d3a.cbegin() + 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3b.insert(d3b.cend() - 1, {t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + d3c.resize(N - 1); + d3c.insert(d3c.cbegin() + N - 2, {t, t, t, t, t, t, t, T(), t, t, t, t, T(), t, t, t, t, t, t}); + + assert(is_de_contiguous_container_asan_correct(d3a)); + assert(is_de_contiguous_container_asan_correct(d3b)); + assert(is_de_contiguous_container_asan_correct(d3c)); +#endif +} + +#if TEST_STD_VER >= 11 +template +void test_emplace() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + T t = T(); + D d1a(2), d1b(2), d1c(2); + + d1a.emplace(d1a.cbegin(), t); + d1b.emplace(d1b.cend(), t); + d1c.emplace(d1c.cbegin() + 1, t); + + assert(is_de_contiguous_container_asan_correct(d1a)); + assert(is_de_contiguous_container_asan_correct(d1b)); + assert(is_de_contiguous_container_asan_correct(d1c)); + + D d2a(3 * N), d2b(3 * N), d2c(3 * N), d2d(3 * N); + + d2a.emplace(d2a.cbegin(), t); + d2b.emplace(d2b.cend(), t); + d2c.emplace(d2c.cbegin() + 1, t); + d2d.emplace(d2d.cend() - 1, t); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + d2a.emplace(d2a.cbegin(), T()); + d2b.emplace(d2b.cend(), T()); + d2c.emplace(d2c.cbegin() + 1, T()); + d2d.emplace(d2d.cend() - 1, T()); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); + + T a = T(), b = T(), c = T(), d = T(); + d2a.emplace(d2a.cbegin(), std::move(a)); + d2b.emplace(d2b.cend(), std::move(b)); + d2c.emplace(d2c.cbegin() + 1, std::move(c)); + d2d.emplace(d2d.cend() - 1, std::move(d)); + + assert(is_de_contiguous_container_asan_correct(d2a)); + assert(is_de_contiguous_container_asan_correct(d2b)); + assert(is_de_contiguous_container_asan_correct(d2c)); + assert(is_de_contiguous_container_asan_correct(d2d)); +} +#endif + +template +void test() { + test_insert(); +#if TEST_STD_VER >= 11 + test_emplace(); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_back.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_aligned() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void pop_back() + + D single_d(1); + single_d.pop_back(); + assert(is_de_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + while (!d1.empty()) { + d1.pop_back(); + assert(is_de_contiguous_container_asan_correct(d1)); + } +} + +template +void test_not_aligned() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void pop_back() + + D single_d(1); + single_d.pop_back(); + assert(is_de_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + d1.pop_front(); + + while (!d1.empty()) { + d1.pop_back(); + assert(is_de_contiguous_container_asan_correct(d1)); + } +} + +template +void test() { + test_aligned(); + test_not_aligned(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + typedef std::deque D; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/pop_front.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void pop_front() + + D single_d(1); + single_d.pop_front(); + assert(is_de_contiguous_container_asan_correct(single_d)); + + D d1(34 * N); + while (!d1.empty()) { + d1.pop_front(); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + D d2(34 * N + 1); + while (!d2.empty()) { + d2.pop_front(); + assert(is_de_contiguous_container_asan_correct(d2)); + } +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + typedef std::deque D; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/push_back.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_push() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D d1; + + // void push_back( const T& value ); + + for (size_t i = 0; i < 32 * N; ++i) { + T b = T(); + d1.push_back(b); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T b = T(); + d1.push_back(b); + assert(is_de_contiguous_container_asan_correct(d1)); + } + +#if TEST_STD_VER >= 11 + // void push_back( T&& value ); + + D d2; + + for (size_t i = 0; i < 34 * N; ++i) { + T b = T(); + d2.push_back(std::move(b)); + assert(is_de_contiguous_container_asan_correct(d2)); + d2.push_back(T()); + assert(is_de_contiguous_container_asan_correct(d2)); + } +#endif +} + +#if TEST_STD_VER >= 11 +template +void test_emplace() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // template< class... Args > + // reference emplace_back( Args&&... args ); + D d1; + + for (size_t i = 0; i < 32 * N; ++i) { + T b = T(); + d1.emplace_back(b); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T b = T(); + d1.emplace_back(b); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + D d2; + + for (size_t i = 0; i < 32 * N; ++i) { + T b = T(); + d2.emplace_back(std::move(b)); + assert(is_de_contiguous_container_asan_correct(d2)); + d2.emplace_back(T()); + assert(is_de_contiguous_container_asan_correct(d2)); + } +} +#endif + +template +void test() { + test_push(); +#if TEST_STD_VER >= 11 + test_emplace(); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/push_front.pass.cpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_push() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // void push_front( const T& value ); + + D d1; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d1.push_front(f); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T f = T(); + d1.push_front(f); + assert(is_de_contiguous_container_asan_correct(d1)); + } + +#if TEST_STD_VER >= 11 + // void push_front( T&& value ); + + D d2; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d2.push_front(std::move(f)); + assert(is_de_contiguous_container_asan_correct(d2)); + d2.push_front(T()); + assert(is_de_contiguous_container_asan_correct(d2)); + } +#endif +} + +#if TEST_STD_VER >= 11 +template +void test_emplace() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + // template< class... Args > + // reference emplace_front( Args&&... args ); + + D d1; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d1.emplace_front(f); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + d1.clear(); + + for (size_t i = 0; i < 34 * N; ++i) { + T f = T(); + d1.emplace_front(f); + assert(is_de_contiguous_container_asan_correct(d1)); + } + + D d2; + + for (size_t i = 0; i < 32 * N; ++i) { + T f = T(); + d2.emplace_front(std::move(f)); + assert(is_de_contiguous_container_asan_correct(d2)); + d2.emplace_front(T()); + assert(is_de_contiguous_container_asan_correct(d2)); + } +} +#endif + +template +void test() { + test_push(); +#if TEST_STD_VER >= 11 + test_emplace(); +#endif +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/resize.pass.cpp @@ -0,0 +1,501 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_count() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(1); + short_d1a.resize(1); + short_d1b.resize(1); + mid_d1a.resize(1); + mid_d1b.resize(1); + mid_d1c.resize(1); + long_d1a.resize(1); + long_d1b.resize(1); + long_d1c.resize(1); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(2); + short_d1a.resize(2); + short_d1b.resize(2); + mid_d1a.resize(2); + mid_d1b.resize(2); + mid_d1c.resize(2); + long_d1a.resize(2); + long_d1b.resize(2); + long_d1c.resize(2); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N - 1); + short_d1a.resize(N - 1); + short_d1b.resize(N - 1); + mid_d1a.resize(N - 1); + mid_d1b.resize(N - 1); + mid_d1c.resize(N - 1); + long_d1a.resize(N - 1); + long_d1b.resize(N - 1); + long_d1c.resize(N - 1); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N + 1); + short_d1a.resize(N + 1); + short_d1b.resize(N + 1); + mid_d1a.resize(N + 1); + mid_d1b.resize(N + 1); + mid_d1c.resize(N + 1); + long_d1a.resize(N + 1); + long_d1b.resize(N + 1); + long_d1c.resize(N + 1); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(20 * N); + short_d1a.resize(20 * N); + short_d1b.resize(20 * N); + mid_d1a.resize(20 * N); + mid_d1b.resize(20 * N); + mid_d1c.resize(20 * N); + long_d1a.resize(20 * N); + long_d1b.resize(20 * N); + long_d1c.resize(20 * N); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + D empty_d2; + D short_d2a(1), short_d2b(2); + D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); + D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); + + empty_d2.resize(20 * N); + short_d2a.resize(20 * N); + short_d2b.resize(20 * N); + mid_d2a.resize(20 * N); + mid_d2b.resize(20 * N); + mid_d2c.resize(20 * N); + long_d2a.resize(20 * N); + long_d2b.resize(20 * N); + long_d2c.resize(20 * N); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); +} + +template +void test_value() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + const T val = T(); + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.resize(0, val); + short_d1a.resize(1, val); + short_d1b.resize(2, val); + mid_d1a.resize(N - 1, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N + 1, val); + long_d1a.resize(17 * N - 1, val); + long_d1b.resize(8 * N, val); + long_d1c.resize(11 * N + 1, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(1, val); + short_d1a.resize(1, val); + short_d1b.resize(1, val); + mid_d1a.resize(1, val); + mid_d1b.resize(1, val); + mid_d1c.resize(1, val); + long_d1a.resize(1, val); + long_d1b.resize(1, val); + long_d1c.resize(1, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(2, val); + short_d1a.resize(2, val); + short_d1b.resize(2, val); + mid_d1a.resize(2, val); + mid_d1b.resize(2, val); + mid_d1c.resize(2, val); + long_d1a.resize(2, val); + long_d1b.resize(2, val); + long_d1c.resize(2, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N - 1, val); + short_d1a.resize(N - 1, val); + short_d1b.resize(N - 1, val); + mid_d1a.resize(N - 1, val); + mid_d1b.resize(N - 1, val); + mid_d1c.resize(N - 1, val); + long_d1a.resize(N - 1, val); + long_d1b.resize(N - 1, val); + long_d1c.resize(N - 1, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N, val); + short_d1a.resize(N, val); + short_d1b.resize(N, val); + mid_d1a.resize(N, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N, val); + long_d1a.resize(N, val); + long_d1b.resize(N, val); + long_d1c.resize(N, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N + 1, val); + short_d1a.resize(N + 1, val); + short_d1b.resize(N + 1, val); + mid_d1a.resize(N + 1, val); + mid_d1b.resize(N + 1, val); + mid_d1c.resize(N + 1, val); + long_d1a.resize(N + 1, val); + long_d1b.resize(N + 1, val); + long_d1c.resize(N + 1, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(N, val); + short_d1a.resize(N, val); + short_d1b.resize(N, val); + mid_d1a.resize(N, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N, val); + long_d1a.resize(N, val); + long_d1b.resize(N, val); + long_d1c.resize(N, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(20 * N, val); + short_d1a.resize(20 * N, val); + short_d1b.resize(20 * N, val); + mid_d1a.resize(20 * N, val); + mid_d1b.resize(20 * N, val); + mid_d1c.resize(20 * N, val); + long_d1a.resize(20 * N, val); + long_d1b.resize(20 * N, val); + long_d1c.resize(20 * N, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0, val); + short_d1a.resize(1, val); + short_d1b.resize(2, val); + mid_d1a.resize(N - 1, val); + mid_d1b.resize(N, val); + mid_d1c.resize(N + 1, val); + long_d1a.resize(17 * N - 1, val); + long_d1b.resize(8 * N, val); + long_d1c.resize(11 * N + 1, val); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + D empty_d2; + D short_d2a(1), short_d2b(2); + D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); + D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); + + empty_d2.resize(20 * N, val); + short_d2a.resize(20 * N, val); + short_d2b.resize(20 * N, val); + mid_d2a.resize(20 * N, val); + mid_d2b.resize(20 * N, val); + mid_d2c.resize(20 * N, val); + long_d2a.resize(20 * N, val); + long_d2b.resize(20 * N, val); + long_d2c.resize(20 * N, val); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); +} + +template +void test() { + test_count(); + test_value(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/shrink_to_fit.pass.cpp @@ -0,0 +1,500 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// UNSUPPORTED: c++03 + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1; + D short_d1a(1), short_d1b(2); + D mid_d1a(N - 1), mid_d1b(N), mid_d1c(N + 1); + D long_d1a(17 * N - 1), long_d1b(8 * N), long_d1c(11 * N + 1); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(1); + short_d1a.resize(1); + short_d1b.resize(1); + mid_d1a.resize(1); + mid_d1b.resize(1); + mid_d1c.resize(1); + long_d1a.resize(1); + long_d1b.resize(1); + long_d1c.resize(1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(2); + short_d1a.resize(2); + short_d1b.resize(2); + mid_d1a.resize(2); + mid_d1b.resize(2); + mid_d1c.resize(2); + long_d1a.resize(2); + long_d1b.resize(2); + long_d1c.resize(2); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N - 1); + short_d1a.resize(N - 1); + short_d1b.resize(N - 1); + mid_d1a.resize(N - 1); + mid_d1b.resize(N - 1); + mid_d1c.resize(N - 1); + long_d1a.resize(N - 1); + long_d1b.resize(N - 1); + long_d1c.resize(N - 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N + 1); + short_d1a.resize(N + 1); + short_d1b.resize(N + 1); + mid_d1a.resize(N + 1); + mid_d1b.resize(N + 1); + mid_d1c.resize(N + 1); + long_d1a.resize(N + 1); + long_d1b.resize(N + 1); + long_d1c.resize(N + 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(N); + short_d1a.resize(N); + short_d1b.resize(N); + mid_d1a.resize(N); + mid_d1b.resize(N); + mid_d1c.resize(N); + long_d1a.resize(N); + long_d1b.resize(N); + long_d1c.resize(N); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.resize(20 * N); + short_d1a.resize(20 * N); + short_d1b.resize(20 * N); + mid_d1a.resize(20 * N); + mid_d1b.resize(20 * N); + mid_d1c.resize(20 * N); + long_d1a.resize(20 * N); + long_d1b.resize(20 * N); + long_d1c.resize(20 * N); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.resize(0); + short_d1a.resize(1); + short_d1b.resize(2); + mid_d1a.resize(N - 1); + mid_d1b.resize(N); + mid_d1c.resize(N + 1); + long_d1a.resize(17 * N - 1); + long_d1b.resize(8 * N); + long_d1c.resize(11 * N + 1); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + empty_d1.clear(); + short_d1a.clear(); + short_d1b.clear(); + mid_d1a.clear(); + mid_d1b.clear(); + mid_d1c.clear(); + long_d1a.clear(); + long_d1b.clear(); + long_d1c.clear(); + + empty_d1.shrink_to_fit(); + short_d1a.shrink_to_fit(); + short_d1b.shrink_to_fit(); + mid_d1a.shrink_to_fit(); + mid_d1b.shrink_to_fit(); + mid_d1c.shrink_to_fit(); + long_d1a.shrink_to_fit(); + long_d1b.shrink_to_fit(); + long_d1c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d1)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + assert(is_de_contiguous_container_asan_correct(mid_d1c)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + assert(is_de_contiguous_container_asan_correct(long_d1c)); + + D empty_d2; + D short_d2a(1), short_d2b(2); + D mid_d2a(N - 1), mid_d2b(N), mid_d2c(N + 1); + D long_d2a(17 * N - 1), long_d2b(8 * N), long_d2c(11 * N + 1); + + empty_d2.resize(20 * N); + short_d2a.resize(20 * N); + short_d2b.resize(20 * N); + mid_d2a.resize(20 * N); + mid_d2b.resize(20 * N); + mid_d2c.resize(20 * N); + long_d2a.resize(20 * N); + long_d2b.resize(20 * N); + long_d2c.resize(20 * N); + + empty_d2.shrink_to_fit(); + short_d2a.shrink_to_fit(); + short_d2b.shrink_to_fit(); + mid_d2a.shrink_to_fit(); + mid_d2b.shrink_to_fit(); + mid_d2c.shrink_to_fit(); + long_d2a.shrink_to_fit(); + long_d2b.shrink_to_fit(); + long_d2c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); + + empty_d2.resize(0); + short_d2a.resize(0); + short_d2b.resize(0); + mid_d2a.resize(0); + mid_d2b.resize(0); + mid_d2c.resize(0); + long_d2a.resize(0); + long_d2b.resize(0); + long_d2c.resize(0); + + empty_d2.shrink_to_fit(); + short_d2a.shrink_to_fit(); + short_d2b.shrink_to_fit(); + mid_d2a.shrink_to_fit(); + mid_d2b.shrink_to_fit(); + mid_d2c.shrink_to_fit(); + long_d2a.shrink_to_fit(); + long_d2b.shrink_to_fit(); + long_d2c.shrink_to_fit(); + + assert(is_de_contiguous_container_asan_correct(empty_d2)); + assert(is_de_contiguous_container_asan_correct(short_d2a)); + assert(is_de_contiguous_container_asan_correct(short_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2a)); + assert(is_de_contiguous_container_asan_correct(mid_d2b)); + assert(is_de_contiguous_container_asan_correct(mid_d2c)); + assert(is_de_contiguous_container_asan_correct(long_d2a)); + assert(is_de_contiguous_container_asan_correct(long_d2b)); + assert(is_de_contiguous_container_asan_correct(long_d2c)); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} diff --git a/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/deque.asan/swap.pass.cpp @@ -0,0 +1,280 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +#include +#include +#include "test_macros.h" +#include "asan_testing.h" // includes deque - don't do it before + +template +void test_external() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1a, empty_d1b; + D short_d1a(1), short_d1b; + D mid_d1a(N), mid_d1b(N + 1); + D long_d1a(8 * N), long_d1b(11 * N + 1); + + std::swap(empty_d1a, empty_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + std::swap(empty_d1a, empty_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + + std::swap(empty_d1a, short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + std::swap(empty_d1a, short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + + std::swap(empty_d1a, mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + std::swap(empty_d1a, mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + + std::swap(empty_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + std::swap(empty_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + std::swap(empty_d1a, long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + std::swap(empty_d1a, long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + + std::swap(empty_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(empty_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(short_d1a, short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + std::swap(short_d1a, short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + std::swap(short_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + std::swap(short_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + std::swap(short_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(short_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(mid_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + std::swap(mid_d1a, mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + std::swap(mid_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(mid_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(long_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + std::swap(long_d1a, long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + std::swap(empty_d1a, empty_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + + std::swap(short_d1a, short_d1a); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + std::swap(short_d1b, short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + std::swap(long_d1a, long_d1a); + assert(is_de_contiguous_container_asan_correct(long_d1a)); +} + +template +void test_member() { + typedef std::deque D; + size_t const N = sizeof(T) < 256 ? (4096 / sizeof(T)) : 16; + + D empty_d1a, empty_d1b; + D short_d1a(1), short_d1b; + D mid_d1a(N), mid_d1b(N + 1); + D long_d1a(8 * N), long_d1b(11 * N + 1); + + empty_d1a.swap(empty_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + empty_d1a.swap(empty_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(empty_d1b)); + + empty_d1a.swap(short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + empty_d1a.swap(short_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + + empty_d1a.swap(mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + empty_d1a.swap(mid_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + + empty_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + empty_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + empty_d1a.swap(long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + empty_d1a.swap(long_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + + empty_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + empty_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + short_d1a.swap(short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + short_d1a.swap(short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + short_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + short_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + short_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + short_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + mid_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + mid_d1a.swap(mid_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(mid_d1b)); + + mid_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + mid_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(mid_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + long_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + long_d1a.swap(long_d1b); + assert(is_de_contiguous_container_asan_correct(long_d1a)); + assert(is_de_contiguous_container_asan_correct(long_d1b)); + + empty_d1a.swap(empty_d1a); + assert(is_de_contiguous_container_asan_correct(empty_d1a)); + + short_d1a.swap(short_d1a); + assert(is_de_contiguous_container_asan_correct(short_d1a)); + short_d1b.swap(short_d1b); + assert(is_de_contiguous_container_asan_correct(short_d1b)); + + long_d1a.swap(long_d1a); + assert(is_de_contiguous_container_asan_correct(long_d1a)); +} + +template +void test() { + test_external(); + test_member(); +} + +int main(int, char**) { + { + typedef char T; + test(); + } + { + typedef short T; + test(); + } + { + typedef int T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array T; + test(); + } + { + typedef std::array, 8000> T; + test(); + } + /* + // Testing interface does not support situations, + // when object memory may be poisoned (SSO case). + { + typedef std::string T; + test(); + } +*/ + return 0; +} 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,11 +9,23 @@ #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" #if TEST_HAS_FEATURE(address_sanitizer) extern "C" int __sanitizer_verify_contiguous_container ( const void *beg, const void *mid, const void *end ); +extern "C" int +__sanitizer_verify_de_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 +# include template TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &c ) @@ -26,13 +38,23 @@ return true; } +template +TEST_CONSTEXPR bool is_de_contiguous_container_asan_correct(const std::deque<_Tp, _Allocator>& c) { + return c.__verify_asan_annotations(); +} #else +# include +# include template TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector &) { return true; } -#endif +template +TEST_CONSTEXPR bool is_de_contiguous_container_asan_correct(const std::deque<_Tp, _Allocator>&) { + return true; +} +#endif #endif // ASAN_TESTING_H