@@ -735,10 +735,44 @@ public:
735
735
//
736
736
// This string implementation doesn't contain any references into itself. It only contains a bit that says whether
737
737
// 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
738
747
using __trivially_relocatable = __conditional_t <
739
748
__libcpp_is_trivially_relocatable<allocator_type>::value && __libcpp_is_trivially_relocatable<pointer>::value,
740
749
basic_string,
741
750
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 const &__ptr) const {
755
+ if (__libcpp_is_constant_evaluated ())
756
+ return __ptr;
757
+
758
+ pointer volatile __copy_ptr = __ptr;
759
+
760
+ return const_cast <pointer &>(__copy_ptr);
761
+ }
762
+
763
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
764
+ const_pointer __asan_volatile_wrapper (const_pointer const &__ptr) const {
765
+ if (__libcpp_is_constant_evaluated ())
766
+ return __ptr;
767
+
768
+ const_pointer volatile __copy_ptr = __ptr;
769
+
770
+ return const_cast <const_pointer &>(__copy_ptr);
771
+ }
772
+ #define _LIBCPP_ASAN_VOLATILE_WRAPPER (PTR ) __asan_volatile_wrapper(PTR)
773
+ #else
774
+ #define _LIBCPP_ASAN_VOLATILE_WRAPPER (PTR ) PTR
775
+ #endif
742
776
743
777
static_assert ((!is_array<value_type>::value), " Character type of basic_string must not be an array" );
744
778
static_assert ((is_standard_layout<value_type>::value), " Character type of basic_string must be standard-layout" );
@@ -1885,16 +1919,16 @@ private:
1885
1919
__r_.first ().__l .__data_ = __p;
1886
1920
}
1887
1921
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer () _NOEXCEPT {
1888
- return __r_.first ().__l .__data_ ;
1922
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( __r_.first ().__l .__data_ ) ;
1889
1923
}
1890
1924
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer () const _NOEXCEPT {
1891
- return __r_.first ().__l .__data_ ;
1925
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( __r_.first ().__l .__data_ ) ;
1892
1926
}
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 ]);
1927
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS pointer __get_short_pointer () _NOEXCEPT {
1928
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( pointer_traits<pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]) );
1895
1929
}
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 ]);
1930
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS const_pointer __get_short_pointer () const _NOEXCEPT {
1931
+ return _LIBCPP_ASAN_VOLATILE_WRAPPER ( pointer_traits<const_pointer>::pointer_to (__r_.first ().__s .__data_ [0 ]) );
1898
1932
}
1899
1933
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer () _NOEXCEPT {
1900
1934
return __is_long () ? __get_long_pointer () : __get_short_pointer ();
0 commit comments