mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-07 02:43:57 +00:00
[ASan][libc++] std::basic_string annotations (#72677)
This commit introduces basic annotations for `std::basic_string`,
mirroring the approach used in `std::vector` and `std::deque`.
Initially, only long strings with the default allocator will be
annotated. Short strings (_SSO - short string optimization_) and strings
with non-default allocators will be annotated in the near future, with
separate commits dedicated to enabling them. The process will be similar
to the workflow employed for enabling annotations in `std::deque`.
**Please note**: these annotations function effectively only when libc++
and libc++abi dylibs are instrumented (with ASan). This aligns with the
prevailing behavior of Memory Sanitizer.
To avoid breaking everything, this commit also appends
`_LIBCPP_INSTRUMENTED_WITH_ASAN` to `__config_site` whenever libc++ is
compiled with ASan. If this macro is not defined, string annotations are
not enabled. However, linking a binary that does **not** annotate
strings with a dynamic library that annotates strings, is not permitted.
Originally proposed here: https://reviews.llvm.org/D132769
Related patches on Phabricator:
- Turning on annotations for short strings:
https://reviews.llvm.org/D147680
- Turning on annotations for all allocators:
https://reviews.llvm.org/D146214
This PR is a part of a series of patches extending AddressSanitizer C++
container overflow detection capabilities by adding annotations, similar
to those existing in `std::vector` and `std::deque` collections. These
enhancements empower ASan to effectively detect instances where the
instrumented program attempts to access memory within a collection's
internal allocation that remains unused. This includes cases where
access occurs before or after the stored elements in `std::deque`, or
between the `std::basic_string`'s size (including the null terminator)
and capacity bounds.
The introduction of these annotations was spurred by a real-world
software bug discovered by Trail of Bits, involving an out-of-bounds
memory access during the comparison of two strings using the
`std::equals` function. This function was taking iterators
(`iter1_begin`, `iter1_end`, `iter2_begin`) to perform the comparison,
using a custom comparison function. When the `iter1` object exceeded the
length of `iter2`, an out-of-bounds read could occur on the `iter2`
object. Container sanitization, upon enabling these annotations, would
effectively identify and flag this potential vulnerability.
This Pull Request introduces basic annotations for `std::basic_string`.
Long strings exhibit structural similarities to `std::vector` and will
be annotated accordingly. Short strings are already implemented, but
will be turned on separately in a forthcoming commit. Look at [a
comment](https://github.com/llvm/llvm-project/pull/72677#issuecomment-1850554465)
below to read about SSO issues at current moment.
Due to the functionality introduced in
[D132522](dd1b7b797a
),
the `__sanitizer_annotate_contiguous_container` function now offers
compatibility with all allocators. However, enabling this support will
be done in a subsequent commit. For the time being, only strings with
the default allocator will be annotated.
If you have any questions, please email:
- advenam.tacet@trailofbits.com
- disconnect3d@trailofbits.com
This commit is contained in:
parent
e1e5f35409
commit
9ed20568e7
@ -651,6 +651,19 @@ get_sanitizer_flags(SANITIZER_FLAGS "${LLVM_USE_SANITIZER}")
|
||||
add_library(cxx-sanitizer-flags INTERFACE)
|
||||
target_compile_options(cxx-sanitizer-flags INTERFACE ${SANITIZER_FLAGS})
|
||||
|
||||
# _LIBCPP_INSTRUMENTED_WITH_ASAN informs that library was built with ASan.
|
||||
# Defining _LIBCPP_INSTRUMENTED_WITH_ASAN while building the library with ASan is required.
|
||||
# Normally, the _LIBCPP_INSTRUMENTED_WITH_ASAN flag is used to keep information whether
|
||||
# dylibs are built with AddressSanitizer. However, when building libc++,
|
||||
# this flag needs to be defined so that the resulting dylib has all ASan functionalities guarded by this flag.
|
||||
# If the _LIBCPP_INSTRUMENTED_WITH_ASAN flag is not defined, then parts of the ASan instrumentation code in libc++
|
||||
# will not be compiled into it, resulting in false positives.
|
||||
# For context, read: https://github.com/llvm/llvm-project/pull/72677#pullrequestreview-1765402800
|
||||
string(FIND "${LLVM_USE_SANITIZER}" "Address" building_with_asan)
|
||||
if (NOT "${building_with_asan}" STREQUAL "-1")
|
||||
config_define(ON _LIBCPP_INSTRUMENTED_WITH_ASAN)
|
||||
endif()
|
||||
|
||||
# Link system libraries =======================================================
|
||||
function(cxx_link_system_libraries target)
|
||||
if (NOT MSVC)
|
||||
|
@ -29,6 +29,7 @@
|
||||
#cmakedefine _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
#cmakedefine _LIBCPP_HAS_NO_STD_MODULES
|
||||
#cmakedefine _LIBCPP_HAS_NO_TIME_ZONE_DATABASE
|
||||
#cmakedefine _LIBCPP_INSTRUMENTED_WITH_ASAN
|
||||
|
||||
// PSTL backends
|
||||
#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_SERIAL
|
||||
|
@ -649,6 +649,17 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
|
||||
# define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS __attribute__((__no_sanitize__("address")))
|
||||
// This macro disables AddressSanitizer (ASan) instrumentation for a specific function,
|
||||
// allowing memory accesses that would normally trigger ASan errors to proceed without crashing.
|
||||
// This is useful for accessing parts of objects memory, which should not be accessed,
|
||||
// such as unused bytes in short strings, that should never be accessed
|
||||
// by other parts of the program.
|
||||
#else
|
||||
# define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
#endif
|
||||
#define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
@ -706,6 +717,9 @@ struct __init_with_sentinel_tag {};
|
||||
template<class _CharT, class _Traits, class _Allocator>
|
||||
class basic_string
|
||||
{
|
||||
private:
|
||||
using __default_allocator_type = allocator<_CharT>;
|
||||
|
||||
public:
|
||||
typedef basic_string __self;
|
||||
typedef basic_string_view<_CharT, _Traits> __self_view;
|
||||
@ -860,6 +874,7 @@ private:
|
||||
__set_long_pointer(__allocation);
|
||||
__set_long_size(__size);
|
||||
}
|
||||
__annotate_new(__size);
|
||||
}
|
||||
|
||||
template <class _Iter, class _Sent>
|
||||
@ -882,7 +897,9 @@ public:
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string()
|
||||
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
|
||||
: __r_(__value_init_tag(), __default_init_tag()) {}
|
||||
: __r_(__value_init_tag(), __default_init_tag()) {
|
||||
__annotate_new(0);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a)
|
||||
#if _LIBCPP_STD_VER <= 14
|
||||
@ -890,44 +907,65 @@ public:
|
||||
#else
|
||||
_NOEXCEPT
|
||||
#endif
|
||||
: __r_(__value_init_tag(), __a) {}
|
||||
: __r_(__value_init_tag(), __a) {
|
||||
__annotate_new(0);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str)
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str)
|
||||
: __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) {
|
||||
if (!__str.__is_long())
|
||||
{
|
||||
__r_.first() = __str.__r_.first();
|
||||
__annotate_new(__get_short_size());
|
||||
}
|
||||
else
|
||||
__init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, const allocator_type& __a)
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str, const allocator_type& __a)
|
||||
: __r_(__default_init_tag(), __a) {
|
||||
if (!__str.__is_long())
|
||||
{
|
||||
__r_.first() = __str.__r_.first();
|
||||
__annotate_new(__get_short_size());
|
||||
}
|
||||
else
|
||||
__init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string(basic_string&& __str)
|
||||
# if _LIBCPP_STD_VER <= 14
|
||||
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
||||
# else
|
||||
_NOEXCEPT
|
||||
# endif
|
||||
: __r_(std::move(__str.__r_)) {
|
||||
// Turning off ASan instrumentation for variable initialization with _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
// does not work consistently during initialization of __r_, so we instead unpoison __str's memory manually first.
|
||||
// __str's memory needs to be unpoisoned only in the case where it's a short string.
|
||||
: __r_( ( (__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_)) ) {
|
||||
__str.__r_.first() = __rep();
|
||||
__str.__annotate_new(0);
|
||||
if(!__is_long())
|
||||
__annotate_new(size());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str, const allocator_type& __a)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string(basic_string&& __str, const allocator_type& __a)
|
||||
: __r_(__default_init_tag(), __a) {
|
||||
if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
|
||||
__init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size());
|
||||
else {
|
||||
if (__libcpp_is_constant_evaluated())
|
||||
__r_.first() = __rep();
|
||||
if (!__str.__is_long())
|
||||
__str.__annotate_delete();
|
||||
__r_.first() = __str.__r_.first();
|
||||
__str.__r_.first() = __rep();
|
||||
__str.__annotate_new(0);
|
||||
if(!__is_long() && this != &__str)
|
||||
__annotate_new(size());
|
||||
}
|
||||
}
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
@ -1085,6 +1123,7 @@ public:
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() {
|
||||
__annotate_delete();
|
||||
if (__is_long())
|
||||
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
|
||||
}
|
||||
@ -1092,7 +1131,7 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); }
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const basic_string& __str);
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(const basic_string& __str);
|
||||
|
||||
template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
|
||||
!__is_same_uncvref<_Tp, basic_string>::value, int> = 0>
|
||||
@ -1102,8 +1141,8 @@ public:
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(basic_string&& __str)
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string&
|
||||
operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) {
|
||||
__move_assign(__str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
|
||||
return *this;
|
||||
}
|
||||
@ -1116,7 +1155,7 @@ public:
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
basic_string& operator=(nullptr_t) = delete;
|
||||
#endif
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(value_type __c);
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(value_type __c);
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
iterator begin() _NOEXCEPT
|
||||
@ -1339,12 +1378,22 @@ public:
|
||||
void __move_assign(basic_string&& __str, size_type __pos, size_type __len) {
|
||||
// Pilfer the allocation from __str.
|
||||
_LIBCPP_ASSERT_INTERNAL(__alloc() == __str.__alloc(), "__move_assign called with wrong allocator");
|
||||
size_type __old_sz = __str.size();
|
||||
if (!__str.__is_long())
|
||||
__str.__annotate_delete();
|
||||
__r_.first() = __str.__r_.first();
|
||||
__str.__r_.first() = __rep();
|
||||
__str.__annotate_new(0);
|
||||
|
||||
_Traits::move(data(), data() + __pos, __len);
|
||||
__set_size(__len);
|
||||
_Traits::assign(data()[__len], value_type());
|
||||
|
||||
if (!__is_long()) {
|
||||
__annotate_new(__len);
|
||||
} else if(__old_sz > __len) {
|
||||
__annotate_shrink(__old_sz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1742,7 +1791,7 @@ private:
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __shrink_or_extend(size_type __target_capacity);
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
bool __is_long() const _NOEXCEPT {
|
||||
if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__r_.first().__l.__is_long_)) {
|
||||
return __r_.first().__l.__is_long_;
|
||||
@ -1782,6 +1831,7 @@ private:
|
||||
value_type* __p;
|
||||
if (__cap - __sz >= __n)
|
||||
{
|
||||
__annotate_increase(__n);
|
||||
__p = std::__to_address(__get_pointer());
|
||||
size_type __n_move = __sz - __ip;
|
||||
if (__n_move != 0)
|
||||
@ -1808,7 +1858,7 @@ private:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
void __set_short_size(size_type __s) _NOEXCEPT {
|
||||
_LIBCPP_ASSERT_INTERNAL(
|
||||
__s < __min_cap, "__s should never be greater than or equal to the short string capacity");
|
||||
@ -1816,7 +1866,7 @@ private:
|
||||
__r_.first().__s.__is_long_ = false;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
size_type __get_short_size() const _NOEXCEPT {
|
||||
_LIBCPP_ASSERT_INTERNAL(
|
||||
!__r_.first().__s.__is_long_, "String has to be short when trying to get the short size");
|
||||
@ -1866,6 +1916,42 @@ private:
|
||||
const_pointer __get_pointer() const _NOEXCEPT
|
||||
{return __is_long() ? __get_long_pointer() : __get_short_pointer();}
|
||||
|
||||
// The following functions are no-ops outside of AddressSanitizer mode.
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_contiguous_container(
|
||||
[[__maybe_unused__]] const void* __old_mid, [[__maybe_unused__]] const void* __new_mid) const {
|
||||
#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
|
||||
const void* __begin = data();
|
||||
const void* __end = data() + capacity() + 1;
|
||||
if (!__libcpp_is_constant_evaluated() && __begin != nullptr && is_same<allocator_type, __default_allocator_type>::value)
|
||||
__sanitizer_annotate_contiguous_container(__begin, __end, __old_mid, __new_mid);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ASan: short string is poisoned if and only if this function returns true.
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __asan_short_string_is_annotated() const _NOEXCEPT {
|
||||
return _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED && !__libcpp_is_constant_evaluated();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_new(size_type __current_size) const _NOEXCEPT {
|
||||
if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
|
||||
__annotate_contiguous_container(data() + capacity() + 1, data() + __current_size + 1);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
|
||||
if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
|
||||
__annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_increase(size_type __n) const _NOEXCEPT {
|
||||
if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
|
||||
__annotate_contiguous_container(data() + size() + 1, data() + size() + 1 + __n);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_shrink(size_type __old_size) const _NOEXCEPT {
|
||||
if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
|
||||
__annotate_contiguous_container(data() + __old_size + 1, data() + size() + 1);
|
||||
}
|
||||
|
||||
template <size_type __a> static
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
size_type __align_it(size_type __s) _NOEXCEPT
|
||||
@ -1968,6 +2054,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
__annotate_delete();
|
||||
allocator_type __a = __str.__alloc();
|
||||
auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
|
||||
__begin_lifetime(__allocation.ptr, __allocation.count);
|
||||
@ -1977,6 +2064,7 @@ private:
|
||||
__set_long_pointer(__allocation.ptr);
|
||||
__set_long_cap(__allocation.count);
|
||||
__set_long_size(__str.size());
|
||||
__annotate_new(__get_long_size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1989,7 +2077,7 @@ private:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void __move_assign(basic_string& __str, false_type)
|
||||
_NOEXCEPT_(__alloc_traits::is_always_equal::value);
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
void __move_assign(basic_string& __str, true_type)
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
_NOEXCEPT;
|
||||
@ -2024,18 +2112,28 @@ private:
|
||||
|
||||
// Assigns the value in __s, guaranteed to be __n < __min_cap in length.
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_short(const value_type* __s, size_type __n) {
|
||||
size_type __old_size = size();
|
||||
if (__n > __old_size)
|
||||
__annotate_increase(__n - __old_size);
|
||||
pointer __p = __is_long()
|
||||
? (__set_long_size(__n), __get_long_pointer())
|
||||
: (__set_short_size(__n), __get_short_pointer());
|
||||
traits_type::move(std::__to_address(__p), __s, __n);
|
||||
traits_type::assign(__p[__n], value_type());
|
||||
if (__old_size > __n)
|
||||
__annotate_shrink(__old_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string& __null_terminate_at(value_type* __p, size_type __newsz) {
|
||||
size_type __old_size = size();
|
||||
if (__newsz > __old_size)
|
||||
__annotate_increase(__newsz - __old_size);
|
||||
__set_size(__newsz);
|
||||
traits_type::assign(__p[__newsz], value_type());
|
||||
if (__old_size > __newsz)
|
||||
__annotate_shrink(__old_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2142,6 +2240,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s,
|
||||
}
|
||||
traits_type::copy(std::__to_address(__p), __s, __sz);
|
||||
traits_type::assign(__p[__sz], value_type());
|
||||
__annotate_new(__sz);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -2170,6 +2269,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty
|
||||
}
|
||||
traits_type::copy(std::__to_address(__p), __s, __sz);
|
||||
traits_type::assign(__p[__sz], value_type());
|
||||
__annotate_new(__sz);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -2194,6 +2294,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(
|
||||
__set_long_size(__sz);
|
||||
}
|
||||
traits_type::copy(std::__to_address(__p), __s, __sz + 1);
|
||||
__annotate_new(__sz);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -2223,6 +2324,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
|
||||
}
|
||||
traits_type::assign(std::__to_address(__p), __n, __c);
|
||||
traits_type::assign(__p[__n], value_type());
|
||||
__annotate_new(__n);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -2238,6 +2340,7 @@ template <class _InputIterator, class _Sentinel>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) {
|
||||
__r_.first() = __rep();
|
||||
__annotate_new(0);
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
@ -2249,6 +2352,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputItera
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
__annotate_delete();
|
||||
if (__is_long())
|
||||
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
|
||||
throw;
|
||||
@ -2309,6 +2413,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init_with_size(
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
__annotate_new(__sz);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -2325,6 +2430,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
|
||||
size_type __cap = __old_cap < __ms / 2 - __alignment ?
|
||||
__recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) :
|
||||
__ms - 1;
|
||||
__annotate_delete();
|
||||
auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
|
||||
pointer __p = __allocation.ptr;
|
||||
__begin_lifetime(__p, __allocation.count);
|
||||
@ -2344,6 +2450,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
|
||||
__old_sz = __n_copy + __n_add + __sec_cp_sz;
|
||||
__set_long_size(__old_sz);
|
||||
traits_type::assign(__p[__old_sz], value_type());
|
||||
__annotate_new(__old_cap + __delta_cap);
|
||||
}
|
||||
|
||||
// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it
|
||||
@ -2366,6 +2473,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t
|
||||
size_type __cap = __old_cap < __ms / 2 - __alignment ?
|
||||
__recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) :
|
||||
__ms - 1;
|
||||
__annotate_delete();
|
||||
auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
|
||||
pointer __p = __allocation.ptr;
|
||||
__begin_lifetime(__p, __allocation.count);
|
||||
@ -2396,6 +2504,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
|
||||
__grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add);
|
||||
_LIBCPP_SUPPRESS_DEPRECATED_POP
|
||||
__set_long_size(__old_sz - __n_del + __n_add);
|
||||
__annotate_new(__old_sz - __n_del + __n_add);
|
||||
}
|
||||
|
||||
// assign
|
||||
@ -2408,10 +2517,15 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(
|
||||
const value_type* __s, size_type __n) {
|
||||
size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
|
||||
if (__n < __cap) {
|
||||
size_type __old_size = __is_short ? __get_short_size() : __get_long_size();
|
||||
if (__n > __old_size)
|
||||
__annotate_increase(__n - __old_size);
|
||||
pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
|
||||
__is_short ? __set_short_size(__n) : __set_long_size(__n);
|
||||
traits_type::copy(std::__to_address(__p), __s, __n);
|
||||
traits_type::assign(__p[__n], value_type());
|
||||
if (__old_size > __n)
|
||||
__annotate_shrink(__old_size);
|
||||
} else {
|
||||
size_type __sz = __is_short ? __get_short_size() : __get_long_size();
|
||||
__grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
|
||||
@ -2426,6 +2540,9 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_external(
|
||||
const value_type* __s, size_type __n) {
|
||||
size_type __cap = capacity();
|
||||
if (__cap >= __n) {
|
||||
size_type __old_size = size();
|
||||
if (__n > __old_size)
|
||||
__annotate_increase(__n - __old_size);
|
||||
value_type* __p = std::__to_address(__get_pointer());
|
||||
traits_type::move(__p, __s, __n);
|
||||
return __null_terminate_at(__p, __n);
|
||||
@ -2453,11 +2570,15 @@ basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c)
|
||||
{
|
||||
size_type __cap = capacity();
|
||||
size_type __old_size = size();
|
||||
if (__cap < __n)
|
||||
{
|
||||
size_type __sz = size();
|
||||
__grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz);
|
||||
__annotate_increase(__n);
|
||||
}
|
||||
else if(__n > __old_size)
|
||||
__annotate_increase(__n - __old_size);
|
||||
value_type* __p = std::__to_address(__get_pointer());
|
||||
traits_type::assign(__p, __n, __c);
|
||||
return __null_terminate_at(__p, __n);
|
||||
@ -2468,24 +2589,26 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c)
|
||||
{
|
||||
pointer __p;
|
||||
if (__is_long())
|
||||
{
|
||||
__p = __get_long_pointer();
|
||||
__set_long_size(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
__p = __get_short_pointer();
|
||||
__set_short_size(1);
|
||||
}
|
||||
traits_type::assign(*__p, __c);
|
||||
traits_type::assign(*++__p, value_type());
|
||||
return *this;
|
||||
pointer __p;
|
||||
size_type __old_size = size();
|
||||
if (__old_size == 0)
|
||||
__annotate_increase(1);
|
||||
if (__is_long()) {
|
||||
__p = __get_long_pointer();
|
||||
__set_long_size(1);
|
||||
} else {
|
||||
__p = __get_short_pointer();
|
||||
__set_short_size(1);
|
||||
}
|
||||
traits_type::assign(*__p, __c);
|
||||
traits_type::assign(*++__p, value_type());
|
||||
if (__old_size > 1)
|
||||
__annotate_shrink(__old_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
|
||||
{
|
||||
@ -2493,7 +2616,12 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
|
||||
__copy_assign_alloc(__str);
|
||||
if (!__is_long()) {
|
||||
if (!__str.__is_long()) {
|
||||
size_type __old_size = __get_short_size();
|
||||
if (__get_short_size() < __str.__get_short_size())
|
||||
__annotate_increase(__str.__get_short_size() - __get_short_size());
|
||||
__r_.first() = __str.__r_.first();
|
||||
if (__old_size > __get_short_size())
|
||||
__annotate_shrink(__old_size);
|
||||
} else {
|
||||
return __assign_no_alias<true>(__str.data(), __str.size());
|
||||
}
|
||||
@ -2519,7 +2647,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, fa
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
@ -2528,6 +2656,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
|
||||
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
__annotate_delete();
|
||||
if (__is_long()) {
|
||||
__alloc_traits::deallocate(__alloc(), __get_long_pointer(),
|
||||
__get_long_cap());
|
||||
@ -2535,13 +2664,35 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
|
||||
if (!is_nothrow_move_assignable<allocator_type>::value) {
|
||||
__set_short_size(0);
|
||||
traits_type::assign(__get_short_pointer()[0], value_type());
|
||||
__annotate_new(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
size_type __str_old_size = __str.size();
|
||||
bool __str_was_short = !__str.__is_long();
|
||||
|
||||
__move_assign_alloc(__str);
|
||||
__r_.first() = __str.__r_.first();
|
||||
__str.__set_short_size(0);
|
||||
traits_type::assign(__str.__get_short_pointer()[0], value_type());
|
||||
|
||||
if (__str_was_short && this != &__str)
|
||||
__str.__annotate_shrink(__str_old_size);
|
||||
else
|
||||
// ASan annotations: was long, so object memory is unpoisoned as new.
|
||||
// Or is same as *this, and __annotate_delete() was called.
|
||||
__str.__annotate_new(0);
|
||||
|
||||
// ASan annotations: Guard against `std::string s; s = std::move(s);`
|
||||
// You can find more here: https://en.cppreference.com/w/cpp/utility/move
|
||||
// Quote: "Unless otherwise specified, all standard library objects that have been moved
|
||||
// from are placed in a "valid but unspecified state", meaning the object's class
|
||||
// invariants hold (so functions without preconditions, such as the assignment operator,
|
||||
// can be safely used on the object after it was moved from):"
|
||||
// Quote: "v = std::move(v); // the value of v is unspecified"
|
||||
if (!__is_long() && &__str != this)
|
||||
// If it is long string, delete was never called on original __str's buffer.
|
||||
__annotate_new(__get_short_size());
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -2587,6 +2738,7 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _
|
||||
_LIBCPP_ASSERT_INTERNAL(
|
||||
__string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial");
|
||||
|
||||
size_type __old_size = size();
|
||||
size_type __cap = capacity();
|
||||
if (__cap < __n) {
|
||||
// Unlike `append` functions, if the input range points into the string itself, there is no case that the input
|
||||
@ -2597,12 +2749,17 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _
|
||||
// object itself stays valid even if reallocation happens.
|
||||
size_type __sz = size();
|
||||
__grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz);
|
||||
__annotate_increase(__n);
|
||||
}
|
||||
else if (__n > __old_size)
|
||||
__annotate_increase(__n - __old_size);
|
||||
pointer __p = __get_pointer();
|
||||
for (; __first != __last; ++__p, (void) ++__first)
|
||||
traits_type::assign(*__p, *__first);
|
||||
traits_type::assign(*__p, value_type());
|
||||
__set_size(__n);
|
||||
if (__n < __old_size)
|
||||
__annotate_shrink(__old_size);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -2663,6 +2820,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_ty
|
||||
{
|
||||
if (__n)
|
||||
{
|
||||
__annotate_increase(__n);
|
||||
value_type* __p = std::__to_address(__get_pointer());
|
||||
traits_type::copy(__p + __sz, __s, __n);
|
||||
__sz += __n;
|
||||
@ -2686,6 +2844,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c)
|
||||
size_type __sz = size();
|
||||
if (__cap - __sz < __n)
|
||||
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
|
||||
__annotate_increase(__n);
|
||||
pointer __p = __get_pointer();
|
||||
traits_type::assign(std::__to_address(__p) + __sz, __n, __c);
|
||||
__sz += __n;
|
||||
@ -2705,6 +2864,7 @@ basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n)
|
||||
size_type __sz = size();
|
||||
if (__cap - __sz < __n)
|
||||
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
|
||||
__annotate_increase(__n);
|
||||
pointer __p = __get_pointer();
|
||||
__sz += __n;
|
||||
__set_size(__sz);
|
||||
@ -2733,8 +2893,10 @@ basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c)
|
||||
if (__sz == __cap)
|
||||
{
|
||||
__grow_by_without_replace(__cap, 1, __sz, __sz, 0);
|
||||
__annotate_increase(1);
|
||||
__is_short = false; // the string is always long after __grow_by
|
||||
}
|
||||
} else
|
||||
__annotate_increase(1);
|
||||
pointer __p = __get_pointer();
|
||||
if (__is_short)
|
||||
{
|
||||
@ -2766,6 +2928,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(
|
||||
{
|
||||
if (__cap - __sz < __n)
|
||||
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
|
||||
__annotate_increase(__n);
|
||||
pointer __p = __get_pointer() + __sz;
|
||||
for (; __first != __last; ++__p, (void) ++__first)
|
||||
traits_type::assign(*__p, *__first);
|
||||
@ -2831,6 +2994,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_t
|
||||
{
|
||||
if (__n)
|
||||
{
|
||||
__annotate_increase(__n);
|
||||
value_type* __p = std::__to_address(__get_pointer());
|
||||
size_type __n_move = __sz - __pos;
|
||||
if (__n_move != 0)
|
||||
@ -2864,6 +3028,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n
|
||||
value_type* __p;
|
||||
if (__cap - __sz >= __n)
|
||||
{
|
||||
__annotate_increase(__n);
|
||||
__p = std::__to_address(__get_pointer());
|
||||
size_type __n_move = __sz - __pos;
|
||||
if (__n_move != 0)
|
||||
@ -2972,6 +3137,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_ty
|
||||
}
|
||||
else
|
||||
{
|
||||
__annotate_increase(1);
|
||||
__p = std::__to_address(__get_pointer());
|
||||
size_type __n_move = __sz - __ip;
|
||||
if (__n_move != 0)
|
||||
@ -3002,6 +3168,8 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __
|
||||
value_type* __p = std::__to_address(__get_pointer());
|
||||
if (__n1 != __n2)
|
||||
{
|
||||
if (__n2 > __n1)
|
||||
__annotate_increase(__n2 - __n1);
|
||||
size_type __n_move = __sz - __pos - __n1;
|
||||
if (__n_move != 0)
|
||||
{
|
||||
@ -3046,20 +3214,18 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __
|
||||
__n1 = std::min(__n1, __sz - __pos);
|
||||
size_type __cap = capacity();
|
||||
value_type* __p;
|
||||
if (__cap - __sz + __n1 >= __n2)
|
||||
{
|
||||
__p = std::__to_address(__get_pointer());
|
||||
if (__n1 != __n2)
|
||||
{
|
||||
size_type __n_move = __sz - __pos - __n1;
|
||||
if (__n_move != 0)
|
||||
traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2);
|
||||
__p = std::__to_address(__get_long_pointer());
|
||||
if (__cap - __sz + __n1 >= __n2) {
|
||||
__p = std::__to_address(__get_pointer());
|
||||
if (__n1 != __n2) {
|
||||
if (__n2 > __n1)
|
||||
__annotate_increase(__n2 - __n1);
|
||||
size_type __n_move = __sz - __pos - __n1;
|
||||
if (__n_move != 0)
|
||||
traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move);
|
||||
}
|
||||
} else {
|
||||
__grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2);
|
||||
__p = std::__to_address(__get_long_pointer());
|
||||
}
|
||||
traits_type::assign(__p + __pos, __n2, __c);
|
||||
return __null_terminate_at(__p, __sz - (__n1 - __n2));
|
||||
@ -3187,6 +3353,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT
|
||||
{
|
||||
size_type __old_size = size();
|
||||
if (__is_long())
|
||||
{
|
||||
traits_type::assign(*__get_long_pointer(), value_type());
|
||||
@ -3197,6 +3364,7 @@ basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT
|
||||
traits_type::assign(*__get_short_pointer(), value_type());
|
||||
__set_short_size(0);
|
||||
}
|
||||
__annotate_shrink(__old_size);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -3259,6 +3427,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity)
|
||||
{
|
||||
__annotate_delete();
|
||||
size_type __cap = capacity();
|
||||
size_type __sz = size();
|
||||
|
||||
@ -3315,6 +3484,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
|
||||
}
|
||||
else
|
||||
__set_short_size(__sz);
|
||||
__annotate_new(__sz);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
@ -3365,8 +3535,16 @@ basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
|
||||
__alloc_traits::propagate_on_container_swap::value ||
|
||||
__alloc_traits::is_always_equal::value ||
|
||||
__alloc() == __str.__alloc(), "swapping non-equal allocators");
|
||||
if (!__is_long())
|
||||
__annotate_delete();
|
||||
if (this != &__str && !__str.__is_long())
|
||||
__str.__annotate_delete();
|
||||
std::swap(__r_.first(), __str.__r_.first());
|
||||
std::__swap_allocator(__alloc(), __str.__alloc());
|
||||
if (!__is_long())
|
||||
__annotate_new(__get_short_size());
|
||||
if (this != &__str && !__str.__is_long())
|
||||
__str.__annotate_new(__str.__get_short_size());
|
||||
}
|
||||
|
||||
// find
|
||||
@ -3854,12 +4032,12 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT
|
||||
{
|
||||
clear();
|
||||
if(__is_long())
|
||||
{
|
||||
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1);
|
||||
__r_.first() = __rep();
|
||||
}
|
||||
clear();
|
||||
if (__is_long()) {
|
||||
__annotate_delete();
|
||||
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1);
|
||||
__r_.first() = __rep();
|
||||
}
|
||||
}
|
||||
|
||||
// operator==
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
@ -28,6 +29,7 @@ TEST_CONSTEXPR_CXX20 void test_invariant(S s, test_allocator_statistics& alloc_s
|
||||
while (s.size() < s.capacity())
|
||||
s.push_back(typename S::value_type());
|
||||
assert(s.size() == s.capacity());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
catch (...) {
|
||||
@ -43,10 +45,12 @@ TEST_CONSTEXPR_CXX20 void test_string(const Alloc& a) {
|
||||
{
|
||||
S const s((Alloc(a)));
|
||||
assert(s.capacity() >= 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
S const s(3, 'x', Alloc(a));
|
||||
assert(s.capacity() >= 3);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#if TEST_STD_VER >= 11
|
||||
// Check that we perform SSO
|
||||
@ -54,6 +58,7 @@ TEST_CONSTEXPR_CXX20 void test_string(const Alloc& a) {
|
||||
S const s;
|
||||
assert(s.capacity() > 0);
|
||||
ASSERT_NOEXCEPT(s.capacity());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -63,18 +68,22 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>());
|
||||
test_string(test_allocator<char>(3));
|
||||
test_string(min_allocator<char>());
|
||||
test_string(safe_allocator<char>());
|
||||
|
||||
{
|
||||
test_allocator_statistics alloc_stats;
|
||||
typedef std::basic_string<char, std::char_traits<char>, test_allocator<char> > S;
|
||||
S s((test_allocator<char>(&alloc_stats)));
|
||||
test_invariant(s, alloc_stats);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
s.assign(10, 'a');
|
||||
s.erase(5);
|
||||
test_invariant(s, alloc_stats);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
s.assign(100, 'a');
|
||||
s.erase(50);
|
||||
test_invariant(s, alloc_stats);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -15,31 +15,39 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s) {
|
||||
s.clear();
|
||||
assert(s.size() == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
S s;
|
||||
test(s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s.assign(10, 'a');
|
||||
s.erase(5);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
test(s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s.assign(100, 'a');
|
||||
s.erase(50);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
test(s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
void test(typename S::size_type min_cap, typename S::size_type erased_index) {
|
||||
@ -33,6 +34,7 @@ void test(typename S::size_type min_cap, typename S::size_type erased_index) {
|
||||
assert(s == s0);
|
||||
assert(s.capacity() <= old_cap);
|
||||
assert(s.capacity() >= s.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -47,6 +49,7 @@ bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -0,0 +1,63 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <string>
|
||||
|
||||
// This test verifies that the ASan annotations for basic_string objects remain accurate
|
||||
// after invoking basic_string::reserve(size_type __requested_capacity).
|
||||
// Different types are used to confirm that ASan works correctly with types of different sizes.
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
void test() {
|
||||
S short_s1(3, 'a'), long_s1(100, 'c');
|
||||
short_s1.reserve(0x1337);
|
||||
long_s1.reserve(0x1337);
|
||||
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s1));
|
||||
|
||||
short_s1.clear();
|
||||
long_s1.clear();
|
||||
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s1));
|
||||
|
||||
short_s1.reserve(0x1);
|
||||
long_s1.reserve(0x1);
|
||||
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s1));
|
||||
|
||||
S short_s2(3, 'a'), long_s2(100, 'c');
|
||||
short_s2.reserve(0x1);
|
||||
long_s2.reserve(0x1);
|
||||
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s2));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s2));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<std::string>();
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<std::wstring>();
|
||||
#endif
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::u16string>();
|
||||
test<std::u32string>();
|
||||
#endif
|
||||
#if TEST_STD_VER >= 20
|
||||
test<std::u8string>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -28,6 +29,7 @@ test(typename S::size_type min_cap, typename S::size_type erased_index, typename
|
||||
s.erase(erased_index);
|
||||
assert(s.size() == erased_index);
|
||||
assert(s.capacity() >= min_cap); // Check that we really have at least this capacity.
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
#if TEST_STD_VER > 17
|
||||
typename S::size_type old_cap = s.capacity();
|
||||
@ -39,6 +41,7 @@ test(typename S::size_type min_cap, typename S::size_type erased_index, typename
|
||||
assert(s == s0);
|
||||
assert(s.capacity() >= res_arg);
|
||||
assert(s.capacity() >= s.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
#if TEST_STD_VER > 17
|
||||
assert(s.capacity() >= old_cap); // reserve never shrinks as of P0966 (C++20)
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "make_string.h"
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) {
|
||||
@ -37,6 +38,7 @@ constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) {
|
||||
const S expected = S(k, 'a') + S(N - k, 'b');
|
||||
assert(s == expected);
|
||||
assert(s.c_str()[N] == '\0');
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -55,6 +57,7 @@ constexpr void test_truncating(std::size_t o, size_t N) {
|
||||
const S expected = S(N - 1, 'a') + S(1, 'b');
|
||||
assert(s == expected);
|
||||
assert(s.c_str()[N] == '\0');
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class String>
|
||||
@ -76,11 +79,14 @@ constexpr bool test() {
|
||||
void test_value_categories() {
|
||||
std::string s;
|
||||
s.resize_and_overwrite(10, [](char*&&, std::size_t&&) { return 0; });
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
s.resize_and_overwrite(10, [](char* const&, const std::size_t&) { return 0; });
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
struct RefQualified {
|
||||
int operator()(char*, std::size_t) && { return 0; }
|
||||
};
|
||||
s.resize_and_overwrite(10, RefQualified{});
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, S expected) {
|
||||
@ -23,6 +24,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, S expected) {
|
||||
s.resize(n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -61,6 +63,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
|
||||
@ -23,6 +24,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_t
|
||||
s.resize(n, c);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -57,12 +59,23 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
'a',
|
||||
S("12345678901234567890123456789012345678901234567890aaaaaaaaaa"));
|
||||
test(S(), S::npos, 'a', S("not going to happen"));
|
||||
//ASan:
|
||||
test(S(), 21, 'a', S("aaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 22, 'a', S("aaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 23, 'a', S("aaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 24, 'a', S("aaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 29, 'a', S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 30, 'a', S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 31, 'a', S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 32, 'a', S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
test(S(), 33, 'a', S("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s) {
|
||||
@ -25,6 +26,7 @@ TEST_CONSTEXPR_CXX20 void test(S s) {
|
||||
assert(s == s0);
|
||||
assert(s.capacity() <= old_cap);
|
||||
assert(s.capacity() >= s.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -43,12 +45,19 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
s.assign(100, 'a');
|
||||
s.erase(50);
|
||||
test(s);
|
||||
|
||||
s.assign(100, 'a');
|
||||
for (int i = 0; i <= 9; ++i) {
|
||||
s.erase(90 - 10 * i);
|
||||
test(s);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class SV>
|
||||
TEST_CONSTEXPR_CXX20 void test(SV sv, std::size_t pos, std::size_t n) {
|
||||
@ -38,6 +39,7 @@ TEST_CONSTEXPR_CXX20 void test(SV sv, std::size_t pos, std::size_t n) {
|
||||
assert(T::compare(s2.data(), sv.data() + pos, rlen) == 0);
|
||||
assert(s2.get_allocator() == A());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -113,6 +115,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>(8));
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string(min_allocator<char>());
|
||||
test_string(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
{
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test() {
|
||||
@ -31,6 +32,7 @@ TEST_CONSTEXPR_CXX20 void test() {
|
||||
assert(s.size() == 0);
|
||||
assert(s.capacity() >= s.size());
|
||||
assert(s.get_allocator() == typename S::allocator_type());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
#if TEST_STD_VER > 14
|
||||
@ -46,6 +48,7 @@ TEST_CONSTEXPR_CXX20 void test() {
|
||||
assert(s.size() == 0);
|
||||
assert(s.capacity() >= s.size());
|
||||
assert(s.get_allocator() == typename S::allocator_type(5));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +68,7 @@ TEST_CONSTEXPR_CXX20 void test2() {
|
||||
assert(s.size() == 0);
|
||||
assert(s.capacity() >= s.size());
|
||||
assert(s.get_allocator() == typename S::allocator_type());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
# if TEST_STD_VER > 14
|
||||
@ -80,6 +84,7 @@ TEST_CONSTEXPR_CXX20 void test2() {
|
||||
assert(s.size() == 0);
|
||||
assert(s.capacity() >= s.size());
|
||||
assert(s.get_allocator() == typename S::allocator_type());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +94,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
|
||||
#if TEST_STD_VER >= 11
|
||||
test2<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test2<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
test2<std::basic_string<char, std::char_traits<char>, explicit_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
// Test that assignment from {} and {ptr, len} are allowed and are not
|
||||
@ -25,11 +26,37 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
std::string s = "hello world";
|
||||
s = {};
|
||||
assert(s.empty());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::string s = "hello world";
|
||||
s = {"abc", 2};
|
||||
assert(s == "ab");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::string s = "hello world";
|
||||
s = {"It'sALongString!NoSSO!qwertyuiop", 30};
|
||||
assert(s == "It'sALongString!NoSSO!qwertyui");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::string s = "Hello world! Hello world! Hello world! Hello world! Hello world!";
|
||||
s = {"It'sALongString!NoSSO!qwertyuiop", 30};
|
||||
assert(s == "It'sALongString!NoSSO!qwertyui");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::string s = "Hello world! Hello world! Hello world! Hello world! Hello world!";
|
||||
s = {"abc", 2};
|
||||
assert(s == "ab");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::string s = "Hello world! Hello world! Hello world! Hello world! Hello world!";
|
||||
s = {"abc", 0};
|
||||
assert(s == "");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, typename S::value_type s2) {
|
||||
@ -24,6 +25,7 @@ TEST_CONSTEXPR_CXX20 void test(S s1, typename S::value_type s2) {
|
||||
assert(s1.size() == 1);
|
||||
assert(T::eq(s1[0], s2));
|
||||
assert(s1.capacity() >= s1.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -38,6 +40,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1) {
|
||||
@ -24,6 +25,8 @@ TEST_CONSTEXPR_CXX20 void test(S s1) {
|
||||
assert(s2 == s1);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
assert(s2.get_allocator() == s1.get_allocator());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
@ -40,6 +43,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>(3));
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string(min_allocator<char>());
|
||||
test_string(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct alloc_imp {
|
||||
@ -83,6 +84,8 @@ TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::allocator_type& a) {
|
||||
assert(s2 == s1);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
assert(s2.get_allocator() == a);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
@ -99,6 +102,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>(3));
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string(min_allocator<char>());
|
||||
test_string(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, const S& s2) {
|
||||
@ -23,6 +24,8 @@ TEST_CONSTEXPR_CXX20 void test(S s1, const S& s2) {
|
||||
LIBCPP_ASSERT(s1.__invariants());
|
||||
assert(s1 == s2);
|
||||
assert(s1.capacity() >= s1.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -47,6 +50,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
// Test the noexcept specification, which is a conforming extension
|
||||
@ -30,6 +31,7 @@ LIBCPP_STATIC_ASSERT(!std::is_nothrow_default_constructible<
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
std::string str;
|
||||
assert(str.empty());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(str));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../../../containers/from_range_helpers.h"
|
||||
#include "../../../containers/sequences/from_range_sequence_containers.h"
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class Container, class Range, class Alloc>
|
||||
concept StringHasFromRangeAllocCtr =
|
||||
@ -70,6 +71,7 @@ constexpr void test_with_input(std::vector<char> input) {
|
||||
LIBCPP_ASSERT(c.__invariants());
|
||||
assert(c.size() == static_cast<std::size_t>(std::distance(c.begin(), c.end())));
|
||||
assert(std::ranges::equal(in, c));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
}
|
||||
|
||||
{ // (range, allocator)
|
||||
@ -80,6 +82,7 @@ constexpr void test_with_input(std::vector<char> input) {
|
||||
assert(c.get_allocator() == alloc);
|
||||
assert(c.size() == static_cast<std::size_t>(std::distance(c.begin(), c.end())));
|
||||
assert(std::ranges::equal(in, c));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "deduction_guides_sfinae_checks.h"
|
||||
#include "test_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
int main(int, char**) {
|
||||
using Char = char16_t;
|
||||
@ -33,12 +34,14 @@ int main(int, char**) {
|
||||
{
|
||||
std::basic_string c(std::from_range, std::array<Char, 0>());
|
||||
static_assert(std::is_same_v<decltype(c), std::basic_string<Char>>);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
}
|
||||
|
||||
{
|
||||
using Alloc = test_allocator<Char>;
|
||||
std::basic_string c(std::from_range, std::array<Char, 0>(), Alloc());
|
||||
static_assert(std::is_same_v<decltype(c), std::basic_string<Char, std::char_traits<Char>, Alloc>>);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
}
|
||||
|
||||
// Note: defining `value_type` is a workaround because one of the deduction guides will end up instantiating
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
// clang-format off
|
||||
template <template <class> class Alloc>
|
||||
@ -25,11 +26,23 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
{
|
||||
std::basic_string<char, std::char_traits<char>, Alloc<char> > s = {'a', 'b', 'c'};
|
||||
assert(s == "abc");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::basic_string<char, std::char_traits<char>, Alloc<char> > s = {'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'};
|
||||
assert(s == "aaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
{
|
||||
std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t> > s = {L'a', L'b', L'c'};
|
||||
assert(s == L"abc");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
{
|
||||
std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t> > s = {L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a'};
|
||||
assert(s == L"aaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -38,6 +51,7 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::allocator>();
|
||||
test_string<min_allocator>();
|
||||
test_string<safe_allocator>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
// clang-format off
|
||||
template <template <class> class Alloc>
|
||||
@ -27,6 +28,16 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
S& result = (s = {'a', 'b', 'c'});
|
||||
assert(s == "abc");
|
||||
assert(&result == &s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(result));
|
||||
}
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, Alloc<char>> S;
|
||||
S s;
|
||||
s = {'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'};
|
||||
assert(s == "aaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
{
|
||||
@ -35,6 +46,17 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
S& result = (s = {L'a', L'b', L'c'});
|
||||
assert(s == L"abc");
|
||||
assert(&result == &s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(result));
|
||||
}
|
||||
{
|
||||
typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, Alloc<wchar_t>> S;
|
||||
S s;
|
||||
S& result = (s = {L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a', L'a'});
|
||||
assert(s == L"aaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
assert(&result == &s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(result));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -43,6 +65,7 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::allocator>();
|
||||
test_string<min_allocator>();
|
||||
test_string<safe_allocator>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "test_allocator.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class Alloc, class It>
|
||||
TEST_CONSTEXPR_CXX20 void test(It first, It last) {
|
||||
@ -37,6 +38,7 @@ TEST_CONSTEXPR_CXX20 void test(It first, It last) {
|
||||
}
|
||||
assert(s2.get_allocator() == Alloc());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc, class It>
|
||||
@ -54,6 +56,7 @@ TEST_CONSTEXPR_CXX20 void test(It first, It last, const Alloc& a) {
|
||||
}
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
class NotAnIterator {};
|
||||
using NotAnInputIterator = std::back_insert_iterator<std::basic_string<char16_t>>;
|
||||
@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
static_assert(std::is_same_v<S::allocator_type, std::allocator<char>>, "");
|
||||
assert(s1.size() == 10);
|
||||
assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
{
|
||||
const char* s = "12345678901234";
|
||||
@ -76,6 +78,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
static_assert(std::is_same_v<S::allocator_type, std::allocator<char>>, "");
|
||||
assert(s1.size() == 10);
|
||||
assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
{
|
||||
@ -87,6 +90,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
static_assert(std::is_same_v<S::allocator_type, test_allocator<wchar_t>>, "");
|
||||
assert(s1.size() == 10);
|
||||
assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
@ -98,6 +102,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
static_assert(std::is_same_v<S::allocator_type, min_allocator<char16_t>>, "");
|
||||
assert(s1.size() == 10);
|
||||
assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
{
|
||||
const char32_t* s = U"12345678901234";
|
||||
@ -108,6 +113,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
static_assert(std::is_same_v<S::allocator_type, explicit_allocator<char32_t>>, "");
|
||||
assert(s1.size() == 10);
|
||||
assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s0) {
|
||||
@ -28,6 +29,9 @@ TEST_CONSTEXPR_CXX20 void test(S s0) {
|
||||
assert(s2 == s1);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
assert(s2.get_allocator() == s1.get_allocator());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s0));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s0, const typename S::allocator_type& a) {
|
||||
@ -28,6 +29,9 @@ TEST_CONSTEXPR_CXX20 void test(S s0, const typename S::allocator_type& a) {
|
||||
assert(s2 == s1);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
assert(s2.get_allocator() == a);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s0));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
|
||||
@ -28,6 +29,9 @@ TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
|
||||
LIBCPP_ASSERT(s2.__invariants());
|
||||
assert(s1 == s0);
|
||||
assert(s1.capacity() >= s1.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s0));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -52,6 +56,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class Alloc, class charT>
|
||||
TEST_CONSTEXPR_CXX20 void test(const charT* s) {
|
||||
@ -31,6 +32,7 @@ TEST_CONSTEXPR_CXX20 void test(const charT* s) {
|
||||
assert(T::compare(s2.data(), s, n) == 0);
|
||||
assert(s2.get_allocator() == Alloc());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc, class charT>
|
||||
@ -44,6 +46,7 @@ TEST_CONSTEXPR_CXX20 void test(const charT* s, const Alloc& a) {
|
||||
assert(T::compare(s2.data(), s, n) == 0);
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
@ -67,6 +70,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test(test_allocator<char>(2));
|
||||
#if TEST_STD_VER >= 11
|
||||
test(min_allocator<char>());
|
||||
test(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::value_type* s2) {
|
||||
@ -25,6 +26,7 @@ TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::value_type* s2) {
|
||||
assert(s1.size() == T::length(s2));
|
||||
assert(T::compare(s1.data(), s2, s1.size()) == 0);
|
||||
assert(s1.capacity() >= s1.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -49,6 +51,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class Alloc, class CharT>
|
||||
TEST_CONSTEXPR_CXX20 void test(const CharT* s, unsigned n) {
|
||||
@ -29,6 +30,7 @@ TEST_CONSTEXPR_CXX20 void test(const CharT* s, unsigned n) {
|
||||
assert(T::compare(s2.data(), s, n) == 0);
|
||||
assert(s2.get_allocator() == Alloc());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc, class CharT>
|
||||
@ -41,6 +43,7 @@ TEST_CONSTEXPR_CXX20 void test(const CharT* s, unsigned n, const Alloc& a) {
|
||||
assert(T::compare(s2.data(), s, n) == 0);
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc>
|
||||
@ -64,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test(test_allocator<char>(2));
|
||||
#if TEST_STD_VER >= 11
|
||||
test(min_allocator<char>());
|
||||
test(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class Alloc, class charT>
|
||||
TEST_CONSTEXPR_CXX20 void test(unsigned n, charT c) {
|
||||
@ -30,6 +31,7 @@ TEST_CONSTEXPR_CXX20 void test(unsigned n, charT c) {
|
||||
assert(s2[i] == c);
|
||||
assert(s2.get_allocator() == Alloc());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc, class charT>
|
||||
@ -42,6 +44,7 @@ TEST_CONSTEXPR_CXX20 void test(unsigned n, charT c, const Alloc& a) {
|
||||
assert(s2[i] == c);
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class Alloc, class Tp>
|
||||
@ -94,6 +97,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>(2));
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string(min_allocator<char>());
|
||||
test_string(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
static_assert(!std::is_convertible<std::string_view, std::string const&>::value, "");
|
||||
static_assert(!std::is_convertible<std::string_view, std::string>::value, "");
|
||||
@ -35,6 +36,7 @@ TEST_CONSTEXPR_CXX20 void test(std::basic_string_view<CharT> sv) {
|
||||
assert(T::compare(s2.data(), sv.data(), sv.size()) == 0);
|
||||
assert(s2.get_allocator() == Alloc());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
{
|
||||
S s2;
|
||||
@ -44,6 +46,7 @@ TEST_CONSTEXPR_CXX20 void test(std::basic_string_view<CharT> sv) {
|
||||
assert(T::compare(s2.data(), sv.data(), sv.size()) == 0);
|
||||
assert(s2.get_allocator() == Alloc());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +61,7 @@ TEST_CONSTEXPR_CXX20 void test(std::basic_string_view<CharT> sv, const Alloc& a)
|
||||
assert(T::compare(s2.data(), sv.data(), sv.size()) == 0);
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
{
|
||||
S s2(a);
|
||||
@ -67,6 +71,7 @@ TEST_CONSTEXPR_CXX20 void test(std::basic_string_view<CharT> sv, const Alloc& a)
|
||||
assert(T::compare(s2.data(), sv.data(), sv.size()) == 0);
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,6 +98,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>(2));
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string(min_allocator<char>());
|
||||
test_string(safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class SV>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, SV sv) {
|
||||
@ -24,6 +25,7 @@ TEST_CONSTEXPR_CXX20 void test(S s1, SV sv) {
|
||||
assert(s1.size() == sv.size());
|
||||
assert(T::compare(s1.data(), sv.data(), s1.size()) == 0);
|
||||
assert(s1.capacity() >= s1.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -49,6 +51,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos) {
|
||||
@ -40,6 +41,7 @@ TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos) {
|
||||
assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
|
||||
assert(s2.get_allocator() == A());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -65,6 +67,7 @@ TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos, unsigned n) {
|
||||
assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
|
||||
assert(s2.get_allocator() == A());
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -90,6 +93,7 @@ TEST_CONSTEXPR_CXX20 void test(S str, unsigned pos, unsigned n, const typename S
|
||||
assert(T::compare(s2.data(), str.data() + pos, rlen) == 0);
|
||||
assert(s2.get_allocator() == a);
|
||||
assert(s2.capacity() >= s2.size());
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -164,6 +168,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string(test_allocator<char>(3), test_allocator<char>(5));
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string(min_allocator<char>(), min_allocator<char>());
|
||||
test_string(safe_allocator<char>(), safe_allocator<char>());
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
#define STR(string) MAKE_CSTRING(typename S::value_type, string)
|
||||
|
||||
@ -39,6 +40,8 @@ constexpr void test_string_pos(S orig, typename S::size_type pos, S expected) {
|
||||
LIBCPP_ASSERT(orig.empty());
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(orig));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(substr));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -65,6 +68,8 @@ test_string_pos_alloc(S orig, typename S::size_type pos, const typename S::alloc
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
assert(substr.get_allocator() == alloc);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(orig));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(substr));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -95,6 +100,8 @@ constexpr void test_string_pos_n(S orig, typename S::size_type pos, typename S::
|
||||
LIBCPP_ASSERT(orig.empty());
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(orig));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(substr));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -122,6 +129,8 @@ constexpr void test_string_pos_n_alloc(
|
||||
LIBCPP_ASSERT(substr.__invariants());
|
||||
assert(substr == expected);
|
||||
assert(substr.get_allocator() == alloc);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(orig));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(substr));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "../../../../containers/sequences/insert_range_sequence_containers.h"
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
// Tested cases:
|
||||
// - different kinds of insertions (appending an {empty/one-element/mid-sized/long range} into an
|
||||
@ -43,9 +44,13 @@ int main(int, char**) {
|
||||
std::string c;
|
||||
static_assert(std::is_lvalue_reference_v<decltype(c.append_range(FullContainer_Begin_EmptyRange<char>.input))>);
|
||||
assert(&c.append_range(FullContainer_Begin_EmptyRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
assert(&c.append_range(FullContainer_Begin_OneElementRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
assert(&c.append_range(FullContainer_Begin_MidRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
assert(&c.append_range(FullContainer_Begin_LongRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
}
|
||||
|
||||
// Note: `test_append_range_exception_safety_throwing_copy` doesn't apply because copying chars cannot throw.
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "nasty_string.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test() {
|
||||
@ -26,6 +27,7 @@ TEST_CONSTEXPR_CXX20 void test() {
|
||||
S s(CONVERT_TO_CSTRING(CharT, "123"));
|
||||
s.append({CharT('a'), CharT('b'), CharT('c')});
|
||||
assert(s == CONVERT_TO_CSTRING(CharT, "123abc"));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
@ -40,6 +42,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test<std::u32string>();
|
||||
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#ifndef TEST_HAS_NO_NASTY_STRING
|
||||
test<nasty_string>();
|
||||
#endif
|
||||
|
@ -17,12 +17,14 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class It>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, It first, It last, S expected) {
|
||||
s.append(first, last);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
@ -225,6 +227,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
|
||||
s.append(str);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -43,6 +45,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{ // test appending to self
|
||||
|
@ -17,12 +17,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, typename S::size_type n, S expected) {
|
||||
s.append(str, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -48,6 +50,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{ // test appending to self
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
struct VeryLarge {
|
||||
long long a;
|
||||
@ -61,6 +62,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::value_type c, S expected) {
|
||||
s.push_back(c);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -78,6 +80,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
{
|
||||
// https://llvm.org/PR31454
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
|
||||
s.append(n, c);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -49,6 +51,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, S str, S expected) {
|
||||
s.append(str);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -59,6 +61,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S::size_type n, S expected) {
|
||||
@ -25,6 +26,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S
|
||||
s.append(str, pos, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -94,6 +96,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class SV>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, SV sv, typename S::size_type pos, typename S::size_type n, S expected) {
|
||||
@ -24,6 +25,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, SV sv, typename S::size_type pos, typename S
|
||||
s.assign(sv, pos, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -85,6 +87,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "../../../../containers/sequences/insert_range_sequence_containers.h"
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
// Tested cases:
|
||||
// - different kinds of assignments (assigning an {empty/one-element/mid-sized/long range} to an
|
||||
@ -43,9 +44,13 @@ int main(int, char**) {
|
||||
std::string c;
|
||||
static_assert(std::is_lvalue_reference_v<decltype(c.assign_range(FullContainer_Begin_EmptyRange<char>.input))>);
|
||||
assert(&c.assign_range(FullContainer_Begin_EmptyRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
assert(&c.assign_range(FullContainer_Begin_OneElementRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
assert(&c.assign_range(FullContainer_Begin_MidRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
assert(&c.assign_range(FullContainer_Begin_LongRange<char>.input) == &c);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(c));
|
||||
}
|
||||
|
||||
// Note: `test_assign_range_exception_safety_throwing_copy` doesn't apply because copying chars cannot throw.
|
||||
|
@ -17,18 +17,31 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
S s("123");
|
||||
|
||||
s.assign({'a', 'b'});
|
||||
assert(s == "ab");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s.assign({'a', 'b', 'c'});
|
||||
assert(s == "abc");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s.assign({'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'});
|
||||
assert(s == "aaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -17,12 +17,14 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class It>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, It first, It last, S expected) {
|
||||
s.assign(first, last);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
@ -171,6 +173,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
|
||||
s.assign(str);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -48,6 +50,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{ // test assignment to self
|
||||
|
@ -17,12 +17,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, typename S::size_type n, S expected) {
|
||||
s.assign(str, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -54,6 +56,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{ // test assign to self
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
|
||||
s.assign(n, c);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -44,6 +46,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -18,12 +18,15 @@
|
||||
#include "nasty_string.h"
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S dest, S src) {
|
||||
dest.assign(src);
|
||||
LIBCPP_ASSERT(dest.__invariants());
|
||||
assert(dest == src);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(src));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(dest));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S::size_type n, S expected) {
|
||||
@ -25,6 +26,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S
|
||||
s.assign(str, pos, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -85,6 +87,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S str, typename S::value_type* s, typename S::size_type n, typename S::size_type pos) {
|
||||
@ -25,6 +26,9 @@ TEST_CONSTEXPR_CXX20 void test(S str, typename S::value_type* s, typename S::siz
|
||||
typename S::size_type r = cs.copy(s, n, pos);
|
||||
typename S::size_type rlen = std::min(n, cs.size() - pos);
|
||||
assert(r == rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(str));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(cs));
|
||||
|
||||
for (r = 0; r < rlen; ++r)
|
||||
assert(S::traits_type::eq(cs[pos + r], s[r]));
|
||||
}
|
||||
@ -110,6 +114,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, S expected) {
|
||||
@ -24,6 +25,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, S expected)
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
assert(i - s.begin() == pos);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -46,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, typename S::difference_type n, S expected) {
|
||||
@ -25,6 +26,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, typename S:
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
assert(i - s.begin() == pos);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -89,6 +91,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, S expected) {
|
||||
@ -22,6 +23,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, S expected) {
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -29,12 +31,15 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
test(S("abcde"), S("abcd"));
|
||||
test(S("abcdefghij"), S("abcdefghi"));
|
||||
test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrs"));
|
||||
test(S("abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrst"),
|
||||
S("abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrs"));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, typename S::size_type n, S expected) {
|
||||
@ -27,6 +28,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, typename S::size_
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -180,6 +182,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,9 +16,11 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S& s, typename S::const_iterator p, typename S::value_type c, S expected) {
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
bool sufficient_cap = s.size() < s.capacity();
|
||||
typename S::difference_type pos = p - s.begin();
|
||||
typename S::iterator i = s.insert(p, c);
|
||||
@ -28,6 +30,7 @@ TEST_CONSTEXPR_CXX20 void test(S& s, typename S::const_iterator p, typename S::v
|
||||
assert(*i == c);
|
||||
if (sufficient_cap)
|
||||
assert(i == p);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -70,6 +73,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
@ -24,11 +25,18 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
typename S::iterator i = s.insert(s.begin() + 3, {'a', 'b', 'c'});
|
||||
assert(i - s.begin() == 3);
|
||||
assert(s == "123abc456");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
typename S::iterator j = s.insert(s.begin() + 6, {'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'});
|
||||
assert(j - s.begin() == 6);
|
||||
assert(s == "123abcaaaaaaaaaaaaaaaaaaaaaaaaa456");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
struct char_ascii {
|
||||
char char_;
|
||||
@ -95,5 +96,6 @@ int main(int, char**) {
|
||||
str.insert(str.begin(), &ch, &ch + 1);
|
||||
assert(str.size() == 1);
|
||||
assert(str[0].char_ == 'A');
|
||||
LIBCPP_ASSERT(is_string_asan_correct(str));
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class It>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, It first, It last, S expected) {
|
||||
@ -25,6 +26,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, It first, I
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(i - s.begin() == pos);
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
@ -147,6 +149,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -24,6 +25,7 @@ test(S s, typename S::difference_type pos, typename S::size_type n, typename S::
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(i - s.begin() == pos);
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -98,6 +100,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, const typename S::value_type* str, S expected) {
|
||||
@ -26,6 +27,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, const typename S:
|
||||
s.insert(pos, str);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -128,6 +130,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
{ // test inserting into self
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -27,6 +28,7 @@ test(S s, typename S::size_type pos, const typename S::value_type* str, typename
|
||||
s.insert(pos, str, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -388,6 +390,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER > 17
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -27,6 +28,7 @@ test(S s, typename S::size_type pos, typename S::size_type n, typename S::value_
|
||||
s.insert(pos, n, str);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -129,6 +131,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, S str, S expected) {
|
||||
@ -26,6 +27,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, S str, S expected
|
||||
s.insert(pos, str);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -128,6 +130,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -29,6 +30,7 @@ test(S s, typename S::size_type pos1, S str, typename S::size_type pos2, typenam
|
||||
s.insert(pos1, str, pos2, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -1816,6 +1818,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -15,12 +15,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::value_type str, S expected) {
|
||||
s += str;
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -36,6 +38,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -17,17 +17,34 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
S s("123");
|
||||
s += {'a', 'b', 'c'};
|
||||
assert(s == "123abc");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s += {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'};
|
||||
assert(s == "123abcxxxxxxxxxxxxxxxx");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s += {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'};
|
||||
assert(s == "123abcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
|
||||
s += {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
|
||||
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'};
|
||||
assert(s == "123abcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
|
||||
s += str;
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -60,6 +62,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -16,12 +16,14 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, S str, S expected) {
|
||||
s += str;
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -61,11 +63,13 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
{ // LWG 2946
|
||||
std::string s;
|
||||
s += {"abc", 1};
|
||||
assert(s.size() == 1);
|
||||
assert(s == "a");
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, S str, S expected) {
|
||||
@ -29,6 +30,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size
|
||||
assert(s == expected);
|
||||
typename S::size_type rlen = str.size();
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -292,6 +294,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class SV>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -49,6 +50,7 @@ test(S s,
|
||||
SizeT xlen = std::min<SizeT>(n1, old_size - pos1);
|
||||
SizeT rlen = std::min<SizeT>(n2, sv.size() - pos2);
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -6279,6 +6281,7 @@ int main(int, char**) {
|
||||
test<char, std::allocator>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<char, min_allocator>();
|
||||
test<char, safe_allocator>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -31,6 +32,7 @@ test(S s, typename S::size_type pos, typename S::size_type n1, const typename S:
|
||||
typename S::size_type xlen = std::min(n1, old_size - pos);
|
||||
typename S::size_type rlen = S::traits_type::length(str);
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -377,6 +379,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -36,6 +37,7 @@ test(S s,
|
||||
typename S::size_type xlen = std::min(n1, old_size - pos);
|
||||
typename S::size_type rlen = n2;
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -1341,6 +1343,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -36,6 +37,7 @@ test(S s,
|
||||
typename S::size_type xlen = std::min(n1, old_size - pos);
|
||||
typename S::size_type rlen = n2;
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -381,6 +383,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, S str, S expected) {
|
||||
@ -30,6 +31,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size
|
||||
typename S::size_type xlen = std::min(n1, old_size - pos1);
|
||||
typename S::size_type rlen = str.size();
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -385,6 +387,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void
|
||||
@ -41,6 +42,7 @@ test(S s,
|
||||
typename S::size_type xlen = std::min(n1, old_size - pos1);
|
||||
typename S::size_type rlen = std::min(n2, str.size() - pos2);
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -6099,6 +6101,7 @@ int main(int, char**) {
|
||||
test<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S, class SV>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, SV sv, S expected) {
|
||||
@ -30,6 +31,7 @@ TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size
|
||||
typename S::size_type xlen = std::min(n1, old_size - pos1);
|
||||
typename S::size_type rlen = sv.size();
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -376,6 +378,7 @@ int main(int, char**) {
|
||||
test<char, std::allocator>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test<char, min_allocator>();
|
||||
test<char, safe_allocator>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -0,0 +1,91 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <string>
|
||||
|
||||
// This test validates that ASan annotations are correctly updated after swaps.
|
||||
// This test meticulously interchanges objects that store data both within their internal memory (Short
|
||||
// String Optimization) and in external buffers (non-SSO).
|
||||
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class CharT>
|
||||
void test(const CharT val) {
|
||||
using S = std::basic_string<CharT>;
|
||||
|
||||
S empty_s;
|
||||
S short_s(3, val);
|
||||
S long_s(1100, val);
|
||||
|
||||
std::swap(empty_s, empty_s);
|
||||
std::swap(short_s, short_s);
|
||||
std::swap(long_s, long_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(empty_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
|
||||
std::swap(empty_s, short_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(empty_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s));
|
||||
|
||||
std::swap(empty_s, short_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(empty_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s));
|
||||
|
||||
std::swap(empty_s, long_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(empty_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
|
||||
std::swap(empty_s, long_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(empty_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
|
||||
std::swap(short_s, long_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
|
||||
std::swap(short_s, long_s);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(short_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
|
||||
S long_s2(11100, val);
|
||||
|
||||
std::swap(long_s, long_s2);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s2));
|
||||
|
||||
std::swap(long_s, long_s2);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s2));
|
||||
|
||||
S long_s3(111, val);
|
||||
|
||||
std::swap(long_s, long_s3);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(long_s2));
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<char>('x');
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
test<wchar_t>(L'x');
|
||||
#endif
|
||||
#if TEST_STD_VER >= 11
|
||||
test<char16_t>(u'x');
|
||||
test<char32_t>(U'x');
|
||||
#endif
|
||||
#if TEST_STD_VER >= 20
|
||||
test<char8_t>(u8'x');
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
|
||||
@ -27,6 +28,8 @@ TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
|
||||
LIBCPP_ASSERT(s2.__invariants());
|
||||
assert(s1 == s2_);
|
||||
assert(s2 == s1_);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -47,12 +50,18 @@ TEST_CONSTEXPR_CXX20 void test_string() {
|
||||
test(S("abcdefghijklmnopqrst"), S("12345"));
|
||||
test(S("abcdefghijklmnopqrst"), S("1234567890"));
|
||||
test(S("abcdefghijklmnopqrst"), S("12345678901234567890"));
|
||||
test(S("abcdefghijklmnopqrstabcdefghijklmnopqrst"), S(""));
|
||||
test(S("abcdefghijklmnopqrstabcdefghijklmnopqrst"), S("12345"));
|
||||
test(S("abcdefghijklmnopqrstabcdefghijklmnopqrst"), S("1234567890"));
|
||||
test(S("abcdefghijklmnopqrstabcdefghijklmnopqrst"), S("12345678901234567890"));
|
||||
test(S("abcdefghijklmnopqrstabcdefghijklmnopqrst"), S("12345678901234567890abcdefghijklmnopqrst"));
|
||||
}
|
||||
|
||||
TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
|
||||
@ -29,6 +30,8 @@ TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
|
||||
LIBCPP_ASSERT(s2.__invariants());
|
||||
assert(s1 == s2_);
|
||||
assert(s2 == s1_);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s1));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s2));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
@ -59,6 +62,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -22,10 +22,12 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test0(typename S::value_type lhs, const S& rhs, const S& x) {
|
||||
assert(lhs + rhs == x);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(lhs + rhs));
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
@ -53,6 +55,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -22,10 +22,12 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test0(const S& lhs, typename S::value_type rhs, const S& x) {
|
||||
assert(lhs + rhs == x);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(lhs + rhs));
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
@ -55,6 +57,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -22,10 +22,12 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const typename S::value_type* rhs, const S& x) {
|
||||
assert(lhs + rhs == x);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(lhs + rhs));
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
@ -77,6 +79,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -34,10 +34,12 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const S& rhs, const S& x) {
|
||||
assert(lhs + rhs == x);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(lhs + rhs));
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
@ -133,6 +135,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "test_allocator.h"
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
template <class S>
|
||||
TEST_CONSTEXPR_CXX20 void test(const S& s, typename S::size_type pos, typename S::size_type n) {
|
||||
@ -29,6 +30,8 @@ TEST_CONSTEXPR_CXX20 void test(const S& s, typename S::size_type pos, typename S
|
||||
typename S::size_type rlen = std::min(n, s.size() - pos);
|
||||
assert(str.size() == rlen);
|
||||
assert(S::traits_type::compare(s.data() + pos, str.data(), rlen) == 0);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(s));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(str));
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
else if (!TEST_IS_CONSTANT_EVALUATED) {
|
||||
@ -117,6 +120,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
|
||||
test_string<std::string>();
|
||||
#if TEST_STD_VER >= 11
|
||||
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
|
||||
test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "make_string.h"
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
#include "asan_testing.h"
|
||||
|
||||
#define STR(string) MAKE_CSTRING(typename S::value_type, string)
|
||||
|
||||
@ -32,6 +33,8 @@ constexpr void test(S orig, typename S::size_type pos, typename S::size_type n,
|
||||
LIBCPP_ASSERT(orig.__invariants());
|
||||
LIBCPP_ASSERT(str.__invariants());
|
||||
assert(str == expected);
|
||||
LIBCPP_ASSERT(is_string_asan_correct(orig));
|
||||
LIBCPP_ASSERT(is_string_asan_correct(str));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
|
@ -11,26 +11,25 @@
|
||||
|
||||
#include "test_macros.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#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_contiguous_container(const void* beg, const void* mid, const void* end);
|
||||
|
||||
template <typename T, typename Alloc>
|
||||
TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector<T, Alloc> &c )
|
||||
{
|
||||
if (TEST_IS_CONSTANT_EVALUATED)
|
||||
return true;
|
||||
if (std::is_same<Alloc, std::allocator<T> >::value && c.data() != NULL)
|
||||
return __sanitizer_verify_contiguous_container(
|
||||
c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0;
|
||||
TEST_CONSTEXPR bool is_contiguous_container_asan_correct(const std::vector<T, Alloc>& c) {
|
||||
if (TEST_IS_CONSTANT_EVALUATED)
|
||||
return true;
|
||||
if (std::is_same<Alloc, std::allocator<T> >::value && c.data() != NULL)
|
||||
return __sanitizer_verify_contiguous_container(c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
template <typename T, typename Alloc>
|
||||
TEST_CONSTEXPR bool is_contiguous_container_asan_correct ( const std::vector<T, Alloc> &)
|
||||
{
|
||||
return true;
|
||||
TEST_CONSTEXPR bool is_contiguous_container_asan_correct(const std::vector<T, Alloc>&) {
|
||||
return true;
|
||||
}
|
||||
#endif // TEST_HAS_FEATURE(address_sanitizer)
|
||||
|
||||
@ -56,4 +55,42 @@ TEST_CONSTEXPR bool is_double_ended_contiguous_container_asan_correct(const std:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_HAS_FEATURE(address_sanitizer)
|
||||
template <typename S>
|
||||
bool is_string_short(S const& s) {
|
||||
// We do not have access to __is_long(), but we can check if strings
|
||||
// buffer is inside strings memory. If strings memory contains its content,
|
||||
// SSO is in use. To check it, we can just confirm that the beginning is in
|
||||
// the string object memory block.
|
||||
// &s - beginning of objects memory
|
||||
// &s[0] - beginning of the buffer
|
||||
// (&s+1) - end of objects memory
|
||||
return (void*)std::addressof(s) <= (void*)std::addressof(s[0]) &&
|
||||
(void*)std::addressof(s[0]) < (void*)(std::addressof(s) + 1);
|
||||
}
|
||||
|
||||
template <typename ChrT, typename TraitsT, typename Alloc>
|
||||
TEST_CONSTEXPR bool is_string_asan_correct(const std::basic_string<ChrT, TraitsT, Alloc>& c) {
|
||||
if (TEST_IS_CONSTANT_EVALUATED)
|
||||
return true;
|
||||
|
||||
if (!is_string_short(c) || _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED) {
|
||||
if (std::is_same<Alloc, std::allocator<ChrT>>::value)
|
||||
return __sanitizer_verify_contiguous_container(c.data(), c.data() + c.size() + 1, c.data() + c.capacity() + 1) !=
|
||||
0;
|
||||
else
|
||||
return __sanitizer_verify_contiguous_container(
|
||||
c.data(), c.data() + c.capacity() + 1, c.data() + c.capacity() + 1) != 0;
|
||||
} else {
|
||||
return __sanitizer_verify_contiguous_container(std::addressof(c), std::addressof(c) + 1, std::addressof(c) + 1) !=
|
||||
0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# include <string>
|
||||
template <typename ChrT, typename TraitsT, typename Alloc>
|
||||
TEST_CONSTEXPR bool is_string_asan_correct(const std::basic_string<ChrT, TraitsT, Alloc>&) {
|
||||
return true;
|
||||
}
|
||||
#endif // TEST_HAS_FEATURE(address_sanitizer)
|
||||
#endif // ASAN_TESTING_H
|
||||
|
Loading…
Reference in New Issue
Block a user