@@ -711,7 +711,23 @@ template <class _CharT, class _Traits, class _Allocator>
711711class basic_string {
712712private:
713713 using __default_allocator_type = allocator<_CharT>;
714+ #ifndef _LIBCPP_HAS_NO_ASAN
715+ pointer __asan_volatile_wrapper (pointer __ptr) const {
716+ volatile pointer __copy_ptr = __ptr;
714717
718+ return __copy_ptr;
719+ }
720+
721+ const_pointer const __asan_volatile_wrapper (const_pointer __ptr) const {
722+ volatile const_pointer __copy_ptr = __ptr;
723+
724+ return __copy_ptr;
725+ }
726+
727+ #define _LIBCPP_ASAN_VOLATILE_WRAPPER (ptr ) __asan_volatile_wrapper(ptr)
728+ #else
729+ #define _LIBCPP_ASAN_VOLATILE_WRAPPER (ptr ) ptr
730+ #endif
715731public:
716732 typedef basic_string __self;
717733 typedef basic_string_view<_CharT, _Traits> __self_view;
@@ -735,10 +751,20 @@ public:
735751 //
736752 // This string implementation doesn't contain any references into itself. It only contains a bit that says whether
737753 // it is in small or large string mode, so the entire structure is trivially relocatable if its members are.
754+ #ifndef _LIBCPP_HAS_NO_ASAN
755+ // When compiling with AddressSanitizer (ASan), basic_string cannot be trivially
756+ // relocatable. Because the object's memory might be poisoned when its content
757+ // is kept inside objects memory (short string optimization), instead of in allocated
758+ // external memory. In such cases, the destructor is responsible for unpoisoning
759+ // the memory to avoid triggering false positives.
760+ // Therefore it's crucial to ensure the destructor is called
761+ using __trivially_relocatable = false_type;
762+ #else
738763 using __trivially_relocatable = __conditional_t <
739764 __libcpp_is_trivially_relocatable<allocator_type>::value && __libcpp_is_trivially_relocatable<pointer>::value,
740765 basic_string,
741766 void >;
767+ #endif
742768
743769 static_assert ((!is_array<value_type>::value), " Character type of basic_string must not be an array" );
744770 static_assert ((is_standard_layout<value_type>::value), " Character type of basic_string must be standard-layout" );
@@ -1885,16 +1911,16 @@ private:
18851911 __r_.first ().__l .__data_ = __p;
18861912 }
18871913 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer () _NOEXCEPT {
1888- return __r_.first ().__l .__data_ ;
1914+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( __r_.first ().__l .__data_ ) ;
18891915 }
18901916 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer () const _NOEXCEPT {
1891- return __r_.first ().__l .__data_ ;
1917+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( __r_.first ().__l .__data_ ) ;
18921918 }
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 ]);
1919+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS pointer __get_short_pointer () _NOEXCEPT {
1920+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( pointer_traits<pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]) );
18951921 }
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 ]);
1922+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS const_pointer __get_short_pointer () const _NOEXCEPT {
1923+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( pointer_traits<const_pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]) );
18981924 }
18991925 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer () _NOEXCEPT {
19001926 return __is_long () ? __get_long_pointer () : __get_short_pointer ();
0 commit comments