@@ -735,11 +735,39 @@ public:
735735 //
736736 // This string implementation doesn't contain any references into itself. It only contains a bit that says whether
737737 // it is in small or large string mode, so the entire structure is trivially relocatable if its members are.
738+ #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
739+ // When compiling with AddressSanitizer (ASan), basic_string cannot be trivially
740+ // relocatable. Because the object's memory might be poisoned when its content
741+ // is kept inside objects memory (short string optimization), instead of in allocated
742+ // external memory. In such cases, the destructor is responsible for unpoisoning
743+ // the memory to avoid triggering false positives.
744+ // Therefore it's crucial to ensure the destructor is called
745+ using __trivially_relocatable = false_type;
746+ #else
738747 using __trivially_relocatable = __conditional_t <
739748 __libcpp_is_trivially_relocatable<allocator_type>::value && __libcpp_is_trivially_relocatable<pointer>::value,
740749 basic_string,
741750 void >;
751+ #endif
752+ #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
753+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
754+ pointer __asan_volatile_wrapper (pointer __ptr) const {
755+ volatile pointer __copy_ptr = __ptr;
756+
757+ return __copy_ptr;
758+ }
742759
760+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
761+ const_pointer const __asan_volatile_wrapper (const_pointer __ptr) const {
762+ volatile const_pointer __copy_ptr = __ptr;
763+
764+ return __copy_ptr;
765+ }
766+
767+ #define _LIBCPP_ASAN_VOLATILE_WRAPPER (ptr ) __asan_volatile_wrapper(ptr)
768+ #else
769+ #define _LIBCPP_ASAN_VOLATILE_WRAPPER (ptr ) ptr
770+ #endif
743771 static_assert ((!is_array<value_type>::value), " Character type of basic_string must not be an array" );
744772 static_assert ((is_standard_layout<value_type>::value), " Character type of basic_string must be standard-layout" );
745773 static_assert ((is_trivial<value_type>::value), " Character type of basic_string must be trivial" );
@@ -1885,16 +1913,16 @@ private:
18851913 __r_.first ().__l .__data_ = __p;
18861914 }
18871915 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer () _NOEXCEPT {
1888- return __r_.first ().__l .__data_ ;
1916+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( __r_.first ().__l .__data_ ) ;
18891917 }
18901918 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer () const _NOEXCEPT {
1891- return __r_.first ().__l .__data_ ;
1919+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( __r_.first ().__l .__data_ ) ;
18921920 }
1893- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_short_pointer () _NOEXCEPT {
1894- return pointer_traits<pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]);
1921+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS pointer __get_short_pointer () _NOEXCEPT {
1922+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( pointer_traits<pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]) );
18951923 }
1896- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_short_pointer () const _NOEXCEPT {
1897- return pointer_traits<const_pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]);
1924+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS const_pointer __get_short_pointer () const _NOEXCEPT {
1925+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( pointer_traits<const_pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]) );
18981926 }
18991927 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer () _NOEXCEPT {
19001928 return __is_long () ? __get_long_pointer () : __get_short_pointer ();
0 commit comments