From df31c7d747997ca269bfa01781a28f97af7b016d Mon Sep 17 00:00:00 2001 From: Advenam Tacet Date: Thu, 21 Dec 2023 16:39:09 +0100 Subject: [PATCH 1/6] [ASan][libc++] Update string ASan annotations to Zero-overhead This commit introduces Zero-overhead string ASan annotations by wrapping every call to ASan helper functions inside a constexpr if statement. This ensures that ASan checks are only performed at runtime when the compiler determines that the string is potentially vulnerable to memory safety issues. This approach significantly reduces the overhead of ASan while maintaining its effectiveness in detecting memory safety bugs. While the intended execution path should not incur any overhead due to compiler optimizations, a few local variables solely accessed by ASan helper functions are not currently removed and we rely on optimizing them away. A future commit may reduce number of these variables. --- libcxx/include/string | 186 +++++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 85 deletions(-) diff --git a/libcxx/include/string b/libcxx/include/string index fdffca5aed18b..fcfee0e6e2f9d 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -659,6 +659,13 @@ _LIBCPP_PUSH_MACROS #else # define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS #endif +#ifndef _IF_ASAN +# ifndef _LIBCPP_HAS_NO_ASAN +# define _IF_ASAN() if _LIBCPP_CONSTEXPR (true) +# else +# define _IF_ASAN() if _LIBCPP_CONSTEXPR (false) +# endif +#endif #define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false _LIBCPP_BEGIN_NAMESPACE_STD @@ -858,7 +865,7 @@ private: __set_long_pointer(__allocation); __set_long_size(__size); } - __annotate_new(__size); + _IF_ASAN() __annotate_new(__size); } template @@ -880,7 +887,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); + _IF_ASAN() __annotate_new(0); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a) @@ -890,14 +897,14 @@ public: _NOEXCEPT #endif : __r_(__value_init_tag(), __a) { - __annotate_new(0); + _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()); + _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 +914,7 @@ public: : __r_(__default_init_tag(), __a) { if (!__str.__is_long()) { __r_.first() = __str.__r_.first(); - __annotate_new(__get_short_size()); + _IF_ASAN() __annotate_new(__get_short_size()); } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } @@ -919,13 +926,19 @@ 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()) + _IF_ASAN() __str.__annotate_new(0); + _IF_ASAN() if (!__is_long()) __annotate_new(size()); } @@ -936,12 +949,12 @@ public: else { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); - if (!__str.__is_long()) + _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) + _IF_ASAN() __str.__annotate_new(0); + _IF_ASAN() if (!__is_long() && this != &__str) __annotate_new(size()); } } @@ -1100,7 +1113,7 @@ public: #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { - __annotate_delete(); + _IF_ASAN() __annotate_delete(); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } @@ -1357,20 +1370,22 @@ public: // 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()) + _IF_ASAN() if (!__str.__is_long()) __str.__annotate_delete(); __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); - __str.__annotate_new(0); + _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); + _IF_ASAN() { + if (!__is_long()) { + __annotate_new(__len); + } else if (__old_sz > __len) { + __annotate_shrink(__old_sz); + } } } #endif @@ -1801,7 +1816,7 @@ private: size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { - __annotate_increase(__n); + _IF_ASAN() __annotate_increase(__n); __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) @@ -2026,7 +2041,7 @@ private: __clear_and_shrink(); __alloc() = __str.__alloc(); } else { - __annotate_delete(); + _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 +2051,7 @@ private: __set_long_pointer(__allocation.ptr); __set_long_cap(__allocation.count); __set_long_size(__str.size()); - __annotate_new(__get_long_size()); + _IF_ASAN() __annotate_new(__get_long_size()); } } } @@ -2076,13 +2091,13 @@ 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) + _IF_ASAN() 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) + _IF_ASAN() if (__old_size > __n) __annotate_shrink(__old_size); return *this; } @@ -2090,11 +2105,11 @@ private: _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) + _IF_ASAN() if (__newsz > __old_size) __annotate_increase(__newsz - __old_size); __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); - if (__old_size > __newsz) + _IF_ASAN() if (__old_size > __newsz) __annotate_shrink(__old_size); return *this; } @@ -2189,7 +2204,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); + _IF_ASAN() __annotate_new(__sz); } template @@ -2213,7 +2228,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); + _IF_ASAN() __annotate_new(__sz); } template @@ -2237,7 +2252,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); + _IF_ASAN() __annotate_new(__sz); } template @@ -2261,7 +2276,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); + _IF_ASAN() __annotate_new(__n); } template @@ -2276,7 +2291,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); + _IF_ASAN() __annotate_new(0); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { @@ -2285,7 +2300,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator _ push_back(*__first); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { - __annotate_delete(); + _IF_ASAN() __annotate_delete(); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; @@ -2338,7 +2353,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __fir throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS - __annotate_new(__sz); + _IF_ASAN() __annotate_new(__sz); } template @@ -2356,7 +2371,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(); + _IF_ASAN() __annotate_delete(); auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); @@ -2375,7 +2390,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); + _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 +2414,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(); + _IF_ASAN() __annotate_delete(); auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); @@ -2428,7 +2443,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); + _IF_ASAN() __annotate_new(__old_sz - __n_del + __n_add); } // assign @@ -2440,13 +2455,13 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* _ size_type __cap = __is_short ? static_cast(__min_cap) : __get_long_cap(); if (__n < __cap) { size_type __old_size = __is_short ? __get_short_size() : __get_long_size(); - if (__n > __old_size) + _IF_ASAN() 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) + _IF_ASAN() if (__old_size > __n) __annotate_shrink(__old_size); } else { size_type __sz = __is_short ? __get_short_size() : __get_long_size(); @@ -2461,7 +2476,7 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* _ size_type __cap = capacity(); if (__cap >= __n) { size_type __old_size = size(); - if (__n > __old_size) + _IF_ASAN() if (__n > __old_size) __annotate_increase(__n - __old_size); value_type* __p = std::__to_address(__get_pointer()); traits_type::move(__p, __s, __n); @@ -2488,8 +2503,8 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) 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) + _IF_ASAN() __annotate_increase(__n); + } else _IF_ASAN() if (__n > __old_size) __annotate_increase(__n - __old_size); value_type* __p = std::__to_address(__get_pointer()); traits_type::assign(__p, __n, __c); @@ -2501,7 +2516,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; size_type __old_size = size(); - if (__old_size == 0) + _IF_ASAN() if (__old_size == 0) __annotate_increase(1); if (__is_long()) { __p = __get_long_pointer(); @@ -2512,7 +2527,7 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); - if (__old_size > 1) + _IF_ASAN() if (__old_size > 1) __annotate_shrink(__old_size); return *this; } @@ -2525,10 +2540,10 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) if (!__is_long()) { if (!__str.__is_long()) { size_type __old_size = __get_short_size(); - if (__get_short_size() < __str.__get_short_size()) + _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()) + _IF_ASAN() if (__old_size > __get_short_size()) __annotate_shrink(__old_size); } else { return __assign_no_alias(__str.data(), __str.size()); @@ -2561,14 +2576,14 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr _NOEXCEPT_(is_nothrow_move_assignable::value) # endif { - __annotate_delete(); + _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); + _IF_ASAN() __annotate_new(0); } # endif } @@ -2579,24 +2594,25 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr __r_.first() = __str.__r_.first(); __str.__set_short_size(0); traits_type::assign(__str.__get_short_pointer()[0], value_type()); + _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 @@ -2649,15 +2665,15 @@ 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) + _IF_ASAN() __annotate_increase(__n); + } else _IF_ASAN() 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) + _IF_ASAN() if (__n < __old_size) __annotate_shrink(__old_size); } @@ -2709,7 +2725,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); + _IF_ASAN() __annotate_increase(__n); value_type* __p = std::__to_address(__get_pointer()); traits_type::copy(__p + __sz, __s, __n); __sz += __n; @@ -2729,7 +2745,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); + _IF_ASAN() __annotate_increase(__n); pointer __p = __get_pointer(); traits_type::assign(std::__to_address(__p) + __sz, __n, __c); __sz += __n; @@ -2747,7 +2763,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); + _IF_ASAN() __annotate_increase(__n); pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); @@ -2769,10 +2785,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); + _IF_ASAN() __annotate_increase(1); __is_short = false; // the string is always long after __grow_by } else - __annotate_increase(1); + _IF_ASAN() __annotate_increase(1); pointer __p = __get_pointer(); if (__is_short) { __p = __get_short_pointer() + __sz; @@ -2796,7 +2812,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); + _IF_ASAN() __annotate_increase(__n); pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, (void)++__first) traits_type::assign(*__p, *__first); @@ -2852,7 +2868,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); + _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 +2896,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); + _IF_ASAN() __annotate_increase(__n); __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) @@ -2973,7 +2989,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); + _IF_ASAN() __annotate_increase(1); __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) @@ -3001,7 +3017,7 @@ 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) + _IF_ASAN() if (__n2 > __n1) __annotate_increase(__n2 - __n1); size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) { @@ -3044,7 +3060,7 @@ 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) + _IF_ASAN() if (__n2 > __n1) __annotate_increase(__n2 - __n1); size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) @@ -3167,7 +3183,7 @@ 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); + _IF_ASAN() __annotate_shrink(__old_size); } template @@ -3220,7 +3236,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(); + _IF_ASAN() __annotate_delete(); size_type __cap = capacity(); size_type __sz = size(); @@ -3266,7 +3282,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); + _IF_ASAN() __annotate_new(__sz); } template @@ -3308,15 +3324,15 @@ 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()) + _IF_ASAN() if (!__is_long()) __annotate_delete(); - if (this != &__str && !__str.__is_long()) + _IF_ASAN() 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()) + _IF_ASAN() if (!__is_long()) __annotate_new(__get_short_size()); - if (this != &__str && !__str.__is_long()) + _IF_ASAN() if (this != &__str && !__str.__is_long()) __str.__annotate_new(__str.__get_short_size()); } @@ -3673,7 +3689,7 @@ template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { clear(); if (__is_long()) { - __annotate_delete(); + _IF_ASAN() __annotate_delete(); __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); __r_.first() = __rep(); } From 20601991670b9d92f602db38bdbad60547800cab Mon Sep 17 00:00:00 2001 From: Advenam Tacet Date: Thu, 21 Dec 2023 18:32:54 +0100 Subject: [PATCH 2/6] Fixes based on the code review (1) Renamed to `_LIBCPP_IF_ASAN`. (2) Moved to `__config`. (3) Added `{ ... }` after `_LIBCPP_IF_ASAN()`. Missing: `#ifdef` around ASan related variables. --- libcxx/include/__config | 10 ++ libcxx/include/string | 231 +++++++++++++++++++++++----------------- 2 files changed, 144 insertions(+), 97 deletions(-) diff --git a/libcxx/include/__config b/libcxx/include/__config index adff13e714cb6..1e09851d40435 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1490,6 +1490,16 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK # endif +// ASan related macros +// _LIBCPP_IF_ASAN is used to removed ASan related code, whenever compiled without ASan. +#ifndef _LIBCPP_IF_ASAN +# ifndef _LIBCPP_HAS_NO_ASAN +# define _LIBCPP_IF_ASAN() if _LIBCPP_CONSTEXPR (true) +# else +# define _LIBCPP_IF_ASAN() if _LIBCPP_CONSTEXPR (false) +# endif +#endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/libcxx/include/string b/libcxx/include/string index fcfee0e6e2f9d..a32186e5abd80 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -659,13 +659,6 @@ _LIBCPP_PUSH_MACROS #else # define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS #endif -#ifndef _IF_ASAN -# ifndef _LIBCPP_HAS_NO_ASAN -# define _IF_ASAN() if _LIBCPP_CONSTEXPR (true) -# else -# define _IF_ASAN() if _LIBCPP_CONSTEXPR (false) -# endif -#endif #define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false _LIBCPP_BEGIN_NAMESPACE_STD @@ -865,7 +858,7 @@ private: __set_long_pointer(__allocation); __set_long_size(__size); } - _IF_ASAN() __annotate_new(__size); + _LIBCPP_IF_ASAN() { __annotate_new(__size); } } template @@ -887,7 +880,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()) { - _IF_ASAN() __annotate_new(0); + _LIBCPP_IF_ASAN() { __annotate_new(0); } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a) @@ -897,14 +890,14 @@ public: _NOEXCEPT #endif : __r_(__value_init_tag(), __a) { - _IF_ASAN() __annotate_new(0); + _LIBCPP_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(); - _IF_ASAN() __annotate_new(__get_short_size()); + _LIBCPP_IF_ASAN() { __annotate_new(__get_short_size()); } } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } @@ -914,7 +907,7 @@ public: : __r_(__default_init_tag(), __a) { if (!__str.__is_long()) { __r_.first() = __str.__r_.first(); - _IF_ASAN() __annotate_new(__get_short_size()); + _LIBCPP_IF_ASAN() { __annotate_new(__get_short_size()); } } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } @@ -937,9 +930,11 @@ public: : __r_(std::move(__str.__r_)) { #endif __str.__r_.first() = __rep(); - _IF_ASAN() __str.__annotate_new(0); - _IF_ASAN() if (!__is_long()) - __annotate_new(size()); + _LIBCPP_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) @@ -949,13 +944,17 @@ public: else { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); - _IF_ASAN() if (!__str.__is_long()) - __str.__annotate_delete(); + _LIBCPP_IF_ASAN() { + if (!__str.__is_long()) + __str.__annotate_delete(); + } __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); - _IF_ASAN() __str.__annotate_new(0); - _IF_ASAN() if (!__is_long() && this != &__str) - __annotate_new(size()); + _LIBCPP_IF_ASAN() { + __str.__annotate_new(0); + if (!__is_long() && this != &__str) + __annotate_new(size()); + } } } #endif // _LIBCPP_CXX03_LANG @@ -1113,7 +1112,7 @@ public: #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { - _IF_ASAN() __annotate_delete(); + _LIBCPP_IF_ASAN() { __annotate_delete(); } if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } @@ -1370,17 +1369,19 @@ public: // Pilfer the allocation from __str. _LIBCPP_ASSERT_INTERNAL(__alloc() == __str.__alloc(), "__move_assign called with wrong allocator"); size_type __old_sz = __str.size(); - _IF_ASAN() if (!__str.__is_long()) - __str.__annotate_delete(); + _LIBCPP_IF_ASAN() { + if (!__str.__is_long()) + __str.__annotate_delete(); + } __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); - _IF_ASAN() __str.__annotate_new(0); + _LIBCPP_IF_ASAN() { __str.__annotate_new(0); } _Traits::move(data(), data() + __pos, __len); __set_size(__len); _Traits::assign(data()[__len], value_type()); - _IF_ASAN() { + _LIBCPP_IF_ASAN() { if (!__is_long()) { __annotate_new(__len); } else if (__old_sz > __len) { @@ -1816,7 +1817,7 @@ private: size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) @@ -2041,7 +2042,7 @@ private: __clear_and_shrink(); __alloc() = __str.__alloc(); } else { - _IF_ASAN() __annotate_delete(); + _LIBCPP_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); @@ -2051,7 +2052,7 @@ private: __set_long_pointer(__allocation.ptr); __set_long_cap(__allocation.count); __set_long_size(__str.size()); - _IF_ASAN() __annotate_new(__get_long_size()); + _LIBCPP_IF_ASAN() { __annotate_new(__get_long_size()); } } } } @@ -2091,26 +2092,34 @@ 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_ASAN() if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_IF_ASAN() { + 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_ASAN() if (__old_size > __n) - __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { + 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_ASAN() if (__newsz > __old_size) - __annotate_increase(__newsz - __old_size); + _LIBCPP_IF_ASAN() { + if (__newsz > __old_size) + __annotate_increase(__newsz - __old_size); + } __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); - _IF_ASAN() if (__old_size > __newsz) - __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { + if (__old_size > __newsz) + __annotate_shrink(__old_size); + } return *this; } @@ -2204,7 +2213,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()); - _IF_ASAN() __annotate_new(__sz); + _LIBCPP_IF_ASAN() { __annotate_new(__sz); } } template @@ -2228,7 +2237,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()); - _IF_ASAN() __annotate_new(__sz); + _LIBCPP_IF_ASAN() { __annotate_new(__sz); } } template @@ -2252,7 +2261,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); - _IF_ASAN() __annotate_new(__sz); + _LIBCPP_IF_ASAN() { __annotate_new(__sz); } } template @@ -2276,7 +2285,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()); - _IF_ASAN() __annotate_new(__n); + _LIBCPP_IF_ASAN() { __annotate_new(__n); } } template @@ -2291,7 +2300,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(); - _IF_ASAN() __annotate_new(0); + _LIBCPP_IF_ASAN() { __annotate_new(0); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { @@ -2300,7 +2309,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator _ push_back(*__first); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { - _IF_ASAN() __annotate_delete(); + _LIBCPP_IF_ASAN() { __annotate_delete(); } if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; @@ -2353,7 +2362,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __fir throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS - _IF_ASAN() __annotate_new(__sz); + _LIBCPP_IF_ASAN() { __annotate_new(__sz); } } template @@ -2371,7 +2380,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; - _IF_ASAN() __annotate_delete(); + _LIBCPP_IF_ASAN() { __annotate_delete(); } auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); @@ -2390,7 +2399,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()); - _IF_ASAN() __annotate_new(__old_cap + __delta_cap); + _LIBCPP_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 @@ -2414,7 +2423,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; - _IF_ASAN() __annotate_delete(); + _LIBCPP_IF_ASAN() { __annotate_delete(); } auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); @@ -2443,7 +2452,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); - _IF_ASAN() __annotate_new(__old_sz - __n_del + __n_add); + _LIBCPP_IF_ASAN() { __annotate_new(__old_sz - __n_del + __n_add); } } // assign @@ -2455,14 +2464,18 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* _ size_type __cap = __is_short ? static_cast(__min_cap) : __get_long_cap(); if (__n < __cap) { size_type __old_size = __is_short ? __get_short_size() : __get_long_size(); - _IF_ASAN() if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_IF_ASAN() { + 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_ASAN() if (__old_size > __n) - __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { + 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); @@ -2476,8 +2489,10 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* _ size_type __cap = capacity(); if (__cap >= __n) { size_type __old_size = size(); - _IF_ASAN() if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_IF_ASAN() { + 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); @@ -2503,9 +2518,11 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) if (__cap < __n) { size_type __sz = size(); __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); - _IF_ASAN() __annotate_increase(__n); - } else _IF_ASAN() if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } + } else _LIBCPP_IF_ASAN() { + 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); @@ -2516,8 +2533,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; size_type __old_size = size(); - _IF_ASAN() if (__old_size == 0) - __annotate_increase(1); + _LIBCPP_IF_ASAN() { + if (__old_size == 0) + __annotate_increase(1); + } if (__is_long()) { __p = __get_long_pointer(); __set_long_size(1); @@ -2527,8 +2546,10 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); - _IF_ASAN() if (__old_size > 1) - __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { + if (__old_size > 1) + __annotate_shrink(__old_size); + } return *this; } @@ -2540,11 +2561,15 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) if (!__is_long()) { if (!__str.__is_long()) { size_type __old_size = __get_short_size(); - _IF_ASAN() if (__get_short_size() < __str.__get_short_size()) - __annotate_increase(__str.__get_short_size() - __get_short_size()); + _LIBCPP_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_ASAN() if (__old_size > __get_short_size()) - __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { + if (__old_size > __get_short_size()) + __annotate_shrink(__old_size); + } } else { return __assign_no_alias(__str.data(), __str.size()); } @@ -2576,14 +2601,14 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr _NOEXCEPT_(is_nothrow_move_assignable::value) # endif { - _IF_ASAN() __annotate_delete(); + _LIBCPP_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()); - _IF_ASAN() __annotate_new(0); + _LIBCPP_IF_ASAN() { __annotate_new(0); } } # endif } @@ -2594,7 +2619,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr __r_.first() = __str.__r_.first(); __str.__set_short_size(0); traits_type::assign(__str.__get_short_pointer()[0], value_type()); - _IF_ASAN() { + _LIBCPP_IF_ASAN() { if (__str_was_short && this != &__str) __str.__annotate_shrink(__str_old_size); else @@ -2665,16 +2690,20 @@ 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); - _IF_ASAN() __annotate_increase(__n); - } else _IF_ASAN() if (__n > __old_size) - __annotate_increase(__n - __old_size); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } + } else _LIBCPP_IF_ASAN() { + 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_ASAN() if (__n < __old_size) - __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { + if (__n < __old_size) + __annotate_shrink(__old_size); + } } template @@ -2725,7 +2754,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_ty size_type __sz = size(); if (__cap - __sz >= __n) { if (__n) { - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } value_type* __p = std::__to_address(__get_pointer()); traits_type::copy(__p + __sz, __s, __n); __sz += __n; @@ -2745,7 +2774,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); - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer(); traits_type::assign(std::__to_address(__p) + __sz, __n, __c); __sz += __n; @@ -2763,7 +2792,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); - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); @@ -2785,10 +2814,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pu } if (__sz == __cap) { __grow_by_without_replace(__cap, 1, __sz, __sz, 0); - _IF_ASAN() __annotate_increase(1); + _LIBCPP_IF_ASAN() { __annotate_increase(1); } __is_short = false; // the string is always long after __grow_by } else - _IF_ASAN() __annotate_increase(1); + _LIBCPP_IF_ASAN() { __annotate_increase(1); } pointer __p = __get_pointer(); if (__is_short) { __p = __get_short_pointer() + __sz; @@ -2812,7 +2841,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); - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, (void)++__first) traits_type::assign(*__p, *__first); @@ -2868,7 +2897,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_t size_type __cap = capacity(); if (__cap - __sz >= __n) { if (__n) { - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } value_type* __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) { @@ -2896,7 +2925,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { - _IF_ASAN() __annotate_increase(__n); + _LIBCPP_IF_ASAN() { __annotate_increase(__n); } __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) @@ -2989,7 +3018,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 { - _IF_ASAN() __annotate_increase(1); + _LIBCPP_IF_ASAN() { __annotate_increase(1); } __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) @@ -3017,8 +3046,10 @@ basic_string<_CharT, _Traits, _Allocator>::replace( if (__cap - __sz + __n1 >= __n2) { value_type* __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { - _IF_ASAN() if (__n2 > __n1) - __annotate_increase(__n2 - __n1); + _LIBCPP_IF_ASAN() { + if (__n2 > __n1) + __annotate_increase(__n2 - __n1); + } size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) { if (__n1 > __n2) { @@ -3060,8 +3091,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_ASAN() if (__n2 > __n1) - __annotate_increase(__n2 - __n1); + _LIBCPP_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); @@ -3183,7 +3216,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat traits_type::assign(*__get_short_pointer(), value_type()); __set_short_size(0); } - _IF_ASAN() __annotate_shrink(__old_size); + _LIBCPP_IF_ASAN() { __annotate_shrink(__old_size); } } template @@ -3236,7 +3269,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) { - _IF_ASAN() __annotate_delete(); + _LIBCPP_IF_ASAN() { __annotate_delete(); } size_type __cap = capacity(); size_type __sz = size(); @@ -3282,7 +3315,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target __set_long_pointer(__new_data); } else __set_short_size(__sz); - _IF_ASAN() __annotate_new(__sz); + _LIBCPP_IF_ASAN() { __annotate_new(__sz); } } template @@ -3324,16 +3357,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_ASAN() if (!__is_long()) - __annotate_delete(); - _IF_ASAN() if (this != &__str && !__str.__is_long()) - __str.__annotate_delete(); + _LIBCPP_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_ASAN() if (!__is_long()) - __annotate_new(__get_short_size()); - _IF_ASAN() if (this != &__str && !__str.__is_long()) - __str.__annotate_new(__str.__get_short_size()); + _LIBCPP_IF_ASAN() { + if (!__is_long()) + __annotate_new(__get_short_size()); + if (this != &__str && !__str.__is_long()) + __str.__annotate_new(__str.__get_short_size()); + } } // find @@ -3689,7 +3726,7 @@ template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { clear(); if (__is_long()) { - _IF_ASAN() __annotate_delete(); + _LIBCPP_IF_ASAN() { __annotate_delete(); } __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); __r_.first() = __rep(); } From 739aa3e67c3e3ebc351682655b1f151af54ac6aa Mon Sep 17 00:00:00 2001 From: Advenam Tacet Date: Thu, 21 Dec 2023 19:03:57 +0100 Subject: [PATCH 3/6] Conditionalize ASan variables Variables used only by ASan helper functions are conditionalized (put behind `#ifndef _LIBCPP_HAS_NO_ASAN`) after that commit. That should remove any impact on performance. --- libcxx/include/string | 51 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/libcxx/include/string b/libcxx/include/string index a32186e5abd80..cc6efdb89025f 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1368,7 +1368,9 @@ 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(); +#endif _LIBCPP_IF_ASAN() { if (!__str.__is_long()) __str.__annotate_delete(); @@ -1382,11 +1384,13 @@ public: _Traits::assign(data()[__len], value_type()); _LIBCPP_IF_ASAN() { +#ifndef __LIBCPP_HAS_NO_ASAN if (!__is_long()) { __annotate_new(__len); } else if (__old_sz > __len) { __annotate_shrink(__old_sz); } +#endif } } #endif @@ -2091,35 +2095,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(); _LIBCPP_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()); +#ifndef __LIBCPP_HAS_NO_ASAN _LIBCPP_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(); _LIBCPP_IF_ASAN() { if (__newsz > __old_size) __annotate_increase(__newsz - __old_size); } +#endif __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); +#ifndef __LIBCPP_HAS_NO_ASAN _LIBCPP_IF_ASAN() { if (__old_size > __newsz) __annotate_shrink(__old_size); } +#endif return *this; } @@ -2463,19 +2475,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(); _LIBCPP_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()); +#ifndef __LIBCPP_HAS_NO_ASAN _LIBCPP_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); @@ -2488,10 +2504,9 @@ _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(); _LIBCPP_IF_ASAN() { - if (__n > __old_size) - __annotate_increase(__n - __old_size); + if (__n > size()) + __annotate_increase(__n - size()); } value_type* __p = std::__to_address(__get_pointer()); traits_type::move(__p, __s, __n); @@ -2514,14 +2529,13 @@ 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); _LIBCPP_IF_ASAN() { __annotate_increase(__n); } } else _LIBCPP_IF_ASAN() { - if (__n > __old_size) - __annotate_increase(__n - __old_size); + if (__n > size()) + __annotate_increase(__n - size()); } value_type* __p = std::__to_address(__get_pointer()); traits_type::assign(__p, __n, __c); @@ -2532,11 +2546,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(); _LIBCPP_IF_ASAN() { if (__old_size == 0) __annotate_increase(1); } +#endif if (__is_long()) { __p = __get_long_pointer(); __set_long_size(1); @@ -2546,10 +2562,12 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); +#ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_IF_ASAN() { if (__old_size > 1) __annotate_shrink(__old_size); } +#endif return *this; } @@ -2560,16 +2578,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(); +#endif _LIBCPP_IF_ASAN() { if (__get_short_size() < __str.__get_short_size()) __annotate_increase(__str.__get_short_size() - __get_short_size()); } __r_.first() = __str.__r_.first(); +#ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_IF_ASAN() { if (__old_size > __get_short_size()) __annotate_shrink(__old_size); } +#endif } else { return __assign_no_alias(__str.data(), __str.size()); } @@ -2612,13 +2634,16 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr } # endif } +#ifndef _LIBCPP_HAS_NO_ASAN size_type __str_old_size = __str.size(); +#endif 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()); +#ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_IF_ASAN() { if (__str_was_short && this != &__str) __str.__annotate_shrink(__str_old_size); @@ -2638,6 +2663,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr // If it is long string, delete was never called on original __str's buffer. __annotate_new(__get_short_size()); } +#endif } #endif @@ -2678,8 +2704,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 @@ -2692,18 +2719,20 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _ __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); _LIBCPP_IF_ASAN() { __annotate_increase(__n); } } else _LIBCPP_IF_ASAN() { - if (__n > __old_size) - __annotate_increase(__n - __old_size); + 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); +#ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_IF_ASAN() { if (__n < __old_size) __annotate_shrink(__old_size); } +#endif } template @@ -3208,7 +3237,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); @@ -3216,7 +3247,9 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat traits_type::assign(*__get_short_pointer(), value_type()); __set_short_size(0); } +#ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_IF_ASAN() { __annotate_shrink(__old_size); } +#endif } template From bd888d99ab73ea587fde0fa3db43191343f198a2 Mon Sep 17 00:00:00 2001 From: Advenam Tacet Date: Thu, 21 Dec 2023 21:22:10 +0100 Subject: [PATCH 4/6] Changes based on @ldionne code review - Macro moved to from `__config` to `string` file. - `_LIBCPP_IF_ASAN` -> `_LIBCPP_STRING_IF_ASAN`. - No more check `#ifndef _LIBCPP_STRING_IF_ASAN` before defining macro. --- libcxx/include/__config | 9 --- libcxx/include/string | 132 +++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 72 deletions(-) diff --git a/libcxx/include/__config b/libcxx/include/__config index 1e09851d40435..438dbfeeb988c 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1490,15 +1490,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK # endif -// ASan related macros -// _LIBCPP_IF_ASAN is used to removed ASan related code, whenever compiled without ASan. -#ifndef _LIBCPP_IF_ASAN -# ifndef _LIBCPP_HAS_NO_ASAN -# define _LIBCPP_IF_ASAN() if _LIBCPP_CONSTEXPR (true) -# else -# define _LIBCPP_IF_ASAN() if _LIBCPP_CONSTEXPR (false) -# endif -#endif #endif // __cplusplus diff --git a/libcxx/include/string b/libcxx/include/string index cc6efdb89025f..e32dbdeea6684 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 (true) +#else +# define _LIBCPP_STRING_IF_ASAN() if _LIBCPP_CONSTEXPR (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); } - _LIBCPP_IF_ASAN() { __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()) { - _LIBCPP_IF_ASAN() { __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) { - _LIBCPP_IF_ASAN() { __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(); - _LIBCPP_IF_ASAN() { __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(); - _LIBCPP_IF_ASAN() { __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()); } @@ -930,7 +936,7 @@ public: : __r_(std::move(__str.__r_)) { #endif __str.__r_.first() = __rep(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { __str.__annotate_new(0); if (!__is_long()) __annotate_new(size()); @@ -944,13 +950,13 @@ public: else { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (!__str.__is_long()) __str.__annotate_delete(); } __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { __str.__annotate_new(0); if (!__is_long() && this != &__str) __annotate_new(size()); @@ -1112,7 +1118,7 @@ public: #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { - _LIBCPP_IF_ASAN() { __annotate_delete(); } + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } @@ -1371,19 +1377,19 @@ public: #ifndef __LIBCPP_HAS_NO_ASAN size_type __old_sz = __str.size(); #endif - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (!__str.__is_long()) __str.__annotate_delete(); } __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); - _LIBCPP_IF_ASAN() { __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()); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { #ifndef __LIBCPP_HAS_NO_ASAN if (!__is_long()) { __annotate_new(__len); @@ -1821,7 +1827,7 @@ private: size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { - _LIBCPP_IF_ASAN() { __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) @@ -2046,7 +2052,7 @@ private: __clear_and_shrink(); __alloc() = __str.__alloc(); } else { - _LIBCPP_IF_ASAN() { __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); @@ -2056,7 +2062,7 @@ private: __set_long_pointer(__allocation.ptr); __set_long_cap(__allocation.count); __set_long_size(__str.size()); - _LIBCPP_IF_ASAN() { __annotate_new(__get_long_size()); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__get_long_size()); } } } } @@ -2097,7 +2103,7 @@ private: 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(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__n > __old_size) __annotate_increase(__n - __old_size); } @@ -2107,7 +2113,7 @@ private: traits_type::move(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); #ifndef __LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__old_size > __n) __annotate_shrink(__old_size); } @@ -2119,7 +2125,7 @@ private: __null_terminate_at(value_type* __p, size_type __newsz) { #ifndef __LIBCPP_HAS_NO_ASAN size_type __old_size = size(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__newsz > __old_size) __annotate_increase(__newsz - __old_size); } @@ -2127,7 +2133,7 @@ private: __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); #ifndef __LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__old_size > __newsz) __annotate_shrink(__old_size); } @@ -2225,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()); - _LIBCPP_IF_ASAN() { __annotate_new(__sz); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2249,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()); - _LIBCPP_IF_ASAN() { __annotate_new(__sz); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2273,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); - _LIBCPP_IF_ASAN() { __annotate_new(__sz); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2297,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()); - _LIBCPP_IF_ASAN() { __annotate_new(__n); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__n); } } template @@ -2312,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(); - _LIBCPP_IF_ASAN() { __annotate_new(0); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(0); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { @@ -2321,7 +2327,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator _ push_back(*__first); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { - _LIBCPP_IF_ASAN() { __annotate_delete(); } + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; @@ -2374,7 +2380,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __fir throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS - _LIBCPP_IF_ASAN() { __annotate_new(__sz); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -2392,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; - _LIBCPP_IF_ASAN() { __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); @@ -2411,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()); - _LIBCPP_IF_ASAN() { __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 @@ -2435,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; - _LIBCPP_IF_ASAN() { __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); @@ -2464,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); - _LIBCPP_IF_ASAN() { __annotate_new(__old_sz - __n_del + __n_add); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__old_sz - __n_del + __n_add); } } // assign @@ -2477,7 +2483,7 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* _ if (__n < __cap) { #ifndef __LIBCPP_HAS_NO_ASAN size_type __old_size = __is_short ? __get_short_size() : __get_long_size(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__n > __old_size) __annotate_increase(__n - __old_size); } @@ -2487,7 +2493,7 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* _ traits_type::copy(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); #ifndef __LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__old_size > __n) __annotate_shrink(__old_size); } @@ -2504,7 +2510,7 @@ _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) { - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__n > size()) __annotate_increase(__n - size()); } @@ -2532,8 +2538,8 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) if (__cap < __n) { size_type __sz = size(); __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); - _LIBCPP_IF_ASAN() { __annotate_increase(__n); } - } else _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } + } else _LIBCPP_STRING_IF_ASAN() { if (__n > size()) __annotate_increase(__n - size()); } @@ -2548,7 +2554,7 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; #ifndef _LIBCPP_HAS_NO_ASAN size_type __old_size = size(); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__old_size == 0) __annotate_increase(1); } @@ -2563,7 +2569,7 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); #ifndef _LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__old_size > 1) __annotate_shrink(__old_size); } @@ -2581,13 +2587,13 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) #ifndef _LIBCPP_HAS_NO_ASAN size_type __old_size = __get_short_size(); #endif - _LIBCPP_IF_ASAN() { + _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(); #ifndef _LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__old_size > __get_short_size()) __annotate_shrink(__old_size); } @@ -2623,28 +2629,28 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr _NOEXCEPT_(is_nothrow_move_assignable::value) # endif { - _LIBCPP_IF_ASAN() { __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()); - _LIBCPP_IF_ASAN() { __annotate_new(0); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(0); } } # endif } #ifndef _LIBCPP_HAS_NO_ASAN size_type __str_old_size = __str.size(); -#endif 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_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__str_was_short && this != &__str) __str.__annotate_shrink(__str_old_size); else @@ -2717,8 +2723,8 @@ 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); - _LIBCPP_IF_ASAN() { __annotate_increase(__n); } - } else _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } + } else _LIBCPP_STRING_IF_ASAN() { if (__n > size()) __annotate_increase(__n - size()); } @@ -2728,7 +2734,7 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _ traits_type::assign(*__p, value_type()); __set_size(__n); #ifndef _LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__n < __old_size) __annotate_shrink(__old_size); } @@ -2783,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) { - _LIBCPP_IF_ASAN() { __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; @@ -2803,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); - _LIBCPP_IF_ASAN() { __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; @@ -2821,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); - _LIBCPP_IF_ASAN() { __annotate_increase(__n); } + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(__n); } pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); @@ -2843,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); - _LIBCPP_IF_ASAN() { __annotate_increase(1); } + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(1); } __is_short = false; // the string is always long after __grow_by } else - _LIBCPP_IF_ASAN() { __annotate_increase(1); } + _LIBCPP_STRING_IF_ASAN() { __annotate_increase(1); } pointer __p = __get_pointer(); if (__is_short) { __p = __get_short_pointer() + __sz; @@ -2870,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); - _LIBCPP_IF_ASAN() { __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); @@ -2926,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) { - _LIBCPP_IF_ASAN() { __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) { @@ -2954,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) { - _LIBCPP_IF_ASAN() { __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) @@ -3047,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 { - _LIBCPP_IF_ASAN() { __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) @@ -3075,7 +3081,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace( if (__cap - __sz + __n1 >= __n2) { value_type* __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__n2 > __n1) __annotate_increase(__n2 - __n1); } @@ -3120,7 +3126,7 @@ 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) { - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (__n2 > __n1) __annotate_increase(__n2 - __n1); } @@ -3248,7 +3254,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat __set_short_size(0); } #ifndef _LIBCPP_HAS_NO_ASAN - _LIBCPP_IF_ASAN() { __annotate_shrink(__old_size); } + _LIBCPP_STRING_IF_ASAN() { __annotate_shrink(__old_size); } #endif } @@ -3302,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) { - _LIBCPP_IF_ASAN() { __annotate_delete(); } + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } size_type __cap = capacity(); size_type __sz = size(); @@ -3348,7 +3354,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target __set_long_pointer(__new_data); } else __set_short_size(__sz); - _LIBCPP_IF_ASAN() { __annotate_new(__sz); } + _LIBCPP_STRING_IF_ASAN() { __annotate_new(__sz); } } template @@ -3390,7 +3396,7 @@ 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"); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (!__is_long()) __annotate_delete(); if (this != &__str && !__str.__is_long()) @@ -3398,7 +3404,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat } std::swap(__r_.first(), __str.__r_.first()); std::__swap_allocator(__alloc(), __str.__alloc()); - _LIBCPP_IF_ASAN() { + _LIBCPP_STRING_IF_ASAN() { if (!__is_long()) __annotate_new(__get_short_size()); if (this != &__str && !__str.__is_long()) @@ -3759,7 +3765,7 @@ template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { clear(); if (__is_long()) { - _LIBCPP_IF_ASAN() { __annotate_delete(); } + _LIBCPP_STRING_IF_ASAN() { __annotate_delete(); } __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); __r_.first() = __rep(); } From b14b804487034ce784d3f338be2d5f2a1196aa07 Mon Sep 17 00:00:00 2001 From: Advenam Tacet Date: Thu, 21 Dec 2023 21:46:15 +0100 Subject: [PATCH 5/6] Remove additional newline --- libcxx/include/__config | 1 - 1 file changed, 1 deletion(-) diff --git a/libcxx/include/__config b/libcxx/include/__config index 438dbfeeb988c..adff13e714cb6 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1490,7 +1490,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK # endif - #endif // __cplusplus #endif // _LIBCPP___CONFIG From 71ec899e505b0a2b19905f99f93ec4fe1ef9c4f0 Mon Sep 17 00:00:00 2001 From: Advenam Tacet Date: Thu, 21 Dec 2023 22:39:44 +0100 Subject: [PATCH 6/6] if constexpr since C++17 --- libcxx/include/string | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/string b/libcxx/include/string index e32dbdeea6684..36ff0deffca56 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -661,9 +661,9 @@ _LIBCPP_PUSH_MACROS #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 (true) +# define _LIBCPP_STRING_IF_ASAN() if _LIBCPP_CONSTEXPR_SINCE_CXX17 (true) #else -# define _LIBCPP_STRING_IF_ASAN() if _LIBCPP_CONSTEXPR (false) +# define _LIBCPP_STRING_IF_ASAN() if _LIBCPP_CONSTEXPR_SINCE_CXX17 (false) #endif #define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false