diff --git a/libcxx/include/string b/libcxx/include/string index fdffca5aed18b..36ff0deffca56 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -659,6 +659,12 @@ _LIBCPP_PUSH_MACROS #else # define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS #endif +// _LIBCPP_STRING_IF_ASAN is used to removed ASan related code, whenever compiled without ASan. +#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUCTMENTED_WITH_ASAN) +# define _LIBCPP_STRING_IF_ASAN() if _LIBCPP_CONSTEXPR_SINCE_CXX17 (true) +#else +# define _LIBCPP_STRING_IF_ASAN() if _LIBCPP_CONSTEXPR_SINCE_CXX17 (false) +#endif #define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false _LIBCPP_BEGIN_NAMESPACE_STD @@ -858,7 +864,7 @@ private: __set_long_pointer(__allocation); __set_long_size(__size); } - __annotate_new(__size); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__size); } } template @@ -880,7 +886,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string() _NOEXCEPT_(is_nothrow_default_constructible::value) : __r_(__value_init_tag(), __default_init_tag()) { - __annotate_new(0); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(0); } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a) @@ -890,14 +896,14 @@ public: _NOEXCEPT #endif : __r_(__value_init_tag(), __a) { - __annotate_new(0); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(0); } } _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()); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__get_short_size()); } } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } @@ -907,7 +913,7 @@ public: : __r_(__default_init_tag(), __a) { if (!__str.__is_long()) { __r_.first() = __str.__r_.first(); - __annotate_new(__get_short_size()); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__get_short_size()); } } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } @@ -919,14 +925,22 @@ public: # else _NOEXCEPT # endif +#ifndef _LIBCPP_HAS_NO_ASAN // 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_))) { + // ASan TODO: ^ This line results in stack frame growth and isn't correctly optimized by the compiler. + // It should be refactored to improve performance. +#else + : __r_(std::move(__str.__r_)) { +#endif __str.__r_.first() = __rep(); - __str.__annotate_new(0); - if (!__is_long()) - __annotate_new(size()); + _LIBCPP_STRING_IF_ASAN() { + __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) @@ -936,13 +950,17 @@ public: else { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); - if (!__str.__is_long()) - __str.__annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { + 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()); + _LIBCPP_STRING_IF_ASAN() { + __str.__annotate_new(0); + if (!__is_long() && this != &__str) + __annotate_new(size()); + } } } #endif // _LIBCPP_CXX03_LANG @@ -1100,7 +1118,7 @@ public: #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } @@ -1356,21 +1374,29 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr 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"); +#ifndef __LIBCPP_HAS_NO_ASAN size_type __old_sz = __str.size(); - if (!__str.__is_long()) - __str.__annotate_delete(); +#endif + _LIBCPP_STRING_IF_ASAN() { + if (!__str.__is_long()) + __str.__annotate_delete(); + } __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); - __str.__annotate_new(0); + _LIBCPP_STRING_IF_ASAN() { __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); + _LIBCPP_STRING_IF_ASAN() { +#ifndef __LIBCPP_HAS_NO_ASAN + if (!__is_long()) { + __annotate_new(__len); + } else if (__old_sz > __len) { + __annotate_shrink(__old_sz); + } +#endif } } #endif @@ -1801,7 +1827,7 @@ private: size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { - __annotate_increase(__n); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) @@ -2026,7 +2052,7 @@ private: __clear_and_shrink(); __alloc() = __str.__alloc(); } else { - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } allocator_type __a = __str.__alloc(); auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap()); __begin_lifetime(__allocation.ptr, __allocation.count); @@ -2036,7 +2062,7 @@ private: __set_long_pointer(__allocation.ptr); __set_long_cap(__allocation.count); __set_long_size(__str.size()); - __annotate_new(__get_long_size()); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__get_long_size()); } } } } @@ -2075,27 +2101,43 @@ 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) { +#ifndef __LIBCPP_HAS_NO_ASAN size_type __old_size = size(); - if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_STRING_IF_ASAN() { + if (__n > __old_size) + __annotate_increase(__n - __old_size); + } +#endif 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); +#ifndef __LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + if (__old_size > __n) + __annotate_shrink(__old_size); + } +#endif return *this; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __null_terminate_at(value_type* __p, size_type __newsz) { +#ifndef __LIBCPP_HAS_NO_ASAN size_type __old_size = size(); - if (__newsz > __old_size) - __annotate_increase(__newsz - __old_size); + _LIBCPP_STRING_IF_ASAN() { + if (__newsz > __old_size) + __annotate_increase(__newsz - __old_size); + } +#endif __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); - if (__old_size > __newsz) - __annotate_shrink(__old_size); +#ifndef __LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + if (__old_size > __newsz) + __annotate_shrink(__old_size); + } +#endif return *this; } @@ -2189,7 +2231,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); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2213,7 +2255,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); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2237,7 +2279,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz + 1); - __annotate_new(__sz); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2261,7 +2303,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__ } traits_type::assign(std::__to_address(__p), __n, __c); traits_type::assign(__p[__n], value_type()); - __annotate_new(__n); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__n); } } template @@ -2276,7 +2318,7 @@ template _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); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(0); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { @@ -2285,7 +2327,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator _ push_back(*__first); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; @@ -2338,7 +2380,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __fir throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS - __annotate_new(__sz); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2356,7 +2398,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__ pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); @@ -2375,7 +2417,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__ __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); + _LIBCPP_STRING_IF_ASAN() { __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 @@ -2399,7 +2441,7 @@ void _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); @@ -2428,7 +2470,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); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__old_sz - __n_del + __n_add); } } // assign @@ -2439,15 +2481,23 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Al basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) { size_type __cap = __is_short ? static_cast(__min_cap) : __get_long_cap(); if (__n < __cap) { +#ifndef __LIBCPP_HAS_NO_ASAN size_type __old_size = __is_short ? __get_short_size() : __get_long_size(); - if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_STRING_IF_ASAN() { + if (__n > __old_size) + __annotate_increase(__n - __old_size); + } +#endif 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); +#ifndef __LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + if (__old_size > __n) + __annotate_shrink(__old_size); + } +#endif } 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); @@ -2460,9 +2510,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Al 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); + _LIBCPP_STRING_IF_ASAN() { + if (__n > size()) + __annotate_increase(__n - size()); + } value_type* __p = std::__to_address(__get_pointer()); traits_type::move(__p, __s, __n); return __null_terminate_at(__p, __n); @@ -2484,13 +2535,14 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 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); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } + } else _LIBCPP_STRING_IF_ASAN() { + if (__n > size()) + __annotate_increase(__n - size()); + } value_type* __p = std::__to_address(__get_pointer()); traits_type::assign(__p, __n, __c); return __null_terminate_at(__p, __n); @@ -2500,9 +2552,13 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; +#ifndef _LIBCPP_HAS_NO_ASAN size_type __old_size = size(); - if (__old_size == 0) - __annotate_increase(1); + _LIBCPP_STRING_IF_ASAN() { + if (__old_size == 0) + __annotate_increase(1); + } +#endif if (__is_long()) { __p = __get_long_pointer(); __set_long_size(1); @@ -2512,8 +2568,12 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); - if (__old_size > 1) - __annotate_shrink(__old_size); +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + if (__old_size > 1) + __annotate_shrink(__old_size); + } +#endif return *this; } @@ -2524,12 +2584,20 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) __copy_assign_alloc(__str); if (!__is_long()) { if (!__str.__is_long()) { +#ifndef _LIBCPP_HAS_NO_ASAN size_type __old_size = __get_short_size(); - if (__get_short_size() < __str.__get_short_size()) - __annotate_increase(__str.__get_short_size() - __get_short_size()); +#endif + _LIBCPP_STRING_IF_ASAN() { + 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); +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + if (__old_size > __get_short_size()) + __annotate_shrink(__old_size); + } +#endif } else { return __assign_no_alias(__str.data(), __str.size()); } @@ -2561,42 +2629,47 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr _NOEXCEPT_(is_nothrow_move_assignable::value) # endif { - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } if (__is_long()) { __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); # if _LIBCPP_STD_VER <= 14 if (!is_nothrow_move_assignable::value) { __set_short_size(0); traits_type::assign(__get_short_pointer()[0], value_type()); - __annotate_new(0); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(0); } } # endif } +#ifndef _LIBCPP_HAS_NO_ASAN size_type __str_old_size = __str.size(); bool __str_was_short = !__str.__is_long(); +#endif __move_assign_alloc(__str); __r_.first() = __str.__r_.first(); __str.__set_short_size(0); traits_type::assign(__str.__get_short_pointer()[0], value_type()); +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + 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); - 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()); + // 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 } #endif @@ -2637,8 +2710,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _Sentinel __last, size_type __n) { _LIBCPP_ASSERT_INTERNAL( __string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial"); - +#ifndef _LIBCPP_HAS_NO_ASAN size_type __old_size = size(); +#endif 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 @@ -2649,16 +2723,22 @@ 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); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } + } else _LIBCPP_STRING_IF_ASAN() { + if (__n > size()) + __annotate_increase(__n - 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); +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { + if (__n < __old_size) + __annotate_shrink(__old_size); + } +#endif } template @@ -2709,7 +2789,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_ty size_type __sz = size(); if (__cap - __sz >= __n) { if (__n) { - __annotate_increase(__n); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } value_type* __p = std::__to_address(__get_pointer()); traits_type::copy(__p + __sz, __s, __n); __sz += __n; @@ -2729,7 +2809,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); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer(); traits_type::assign(std::__to_address(__p) + __sz, __n, __c); __sz += __n; @@ -2747,7 +2827,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); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); @@ -2769,10 +2849,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pu } if (__sz == __cap) { __grow_by_without_replace(__cap, 1, __sz, __sz, 0); - __annotate_increase(1); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(1); } __is_short = false; // the string is always long after __grow_by } else - __annotate_increase(1); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(1); } pointer __p = __get_pointer(); if (__is_short) { __p = __get_short_pointer() + __sz; @@ -2796,7 +2876,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _For if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) { if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); - __annotate_increase(__n); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, (void)++__first) traits_type::assign(*__p, *__first); @@ -2852,7 +2932,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_t size_type __cap = capacity(); if (__cap - __sz >= __n) { if (__n) { - __annotate_increase(__n); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } value_type* __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) { @@ -2880,7 +2960,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { - __annotate_increase(__n); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) @@ -2973,7 +3053,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_ty __grow_by_without_replace(__cap, 1, __sz, __ip, 0, 1); __p = std::__to_address(__get_long_pointer()); } else { - __annotate_increase(1); + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(1); } __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) @@ -3001,8 +3081,10 @@ basic_string<_CharT, _Traits, _Allocator>::replace( if (__cap - __sz + __n1 >= __n2) { value_type* __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { - if (__n2 > __n1) - __annotate_increase(__n2 - __n1); + _LIBCPP_STRING_IF_ASAN() { + if (__n2 > __n1) + __annotate_increase(__n2 - __n1); + } size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) { if (__n1 > __n2) { @@ -3044,8 +3126,10 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ if (__cap - __sz + __n1 >= __n2) { __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { - if (__n2 > __n1) - __annotate_increase(__n2 - __n1); + _LIBCPP_STRING_IF_ASAN() { + 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); @@ -3159,7 +3243,9 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { +#ifndef _LIBCPP_HAS_NO_ASAN size_type __old_size = size(); +#endif if (__is_long()) { traits_type::assign(*__get_long_pointer(), value_type()); __set_long_size(0); @@ -3167,7 +3253,9 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat traits_type::assign(*__get_short_pointer(), value_type()); __set_short_size(0); } - __annotate_shrink(__old_size); +#ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_STRING_IF_ASAN() { __annotate_shrink(__old_size); } +#endif } template @@ -3220,7 +3308,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) { - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } size_type __cap = capacity(); size_type __sz = size(); @@ -3266,7 +3354,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target __set_long_pointer(__new_data); } else __set_short_size(__sz); - __annotate_new(__sz); + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -3308,16 +3396,20 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat __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(); + _LIBCPP_STRING_IF_ASAN() { + 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()); + _LIBCPP_STRING_IF_ASAN() { + if (!__is_long()) + __annotate_new(__get_short_size()); + if (this != &__str && !__str.__is_long()) + __str.__annotate_new(__str.__get_short_size()); + } } // find @@ -3673,7 +3765,7 @@ template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { clear(); if (__is_long()) { - __annotate_delete(); + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); __r_.first() = __rep(); }