@@ -711,7 +711,23 @@ template <class _CharT, class _Traits, class _Allocator>
711
711
class basic_string {
712
712
private:
713
713
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;
714
717
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
715
731
public:
716
732
typedef basic_string __self;
717
733
typedef basic_string_view<_CharT, _Traits> __self_view;
@@ -735,10 +751,20 @@ public:
735
751
//
736
752
// This string implementation doesn't contain any references into itself. It only contains a bit that says whether
737
753
// 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
738
763
using __trivially_relocatable = __conditional_t <
739
764
__libcpp_is_trivially_relocatable<allocator_type>::value && __libcpp_is_trivially_relocatable<pointer>::value,
740
765
basic_string,
741
766
void >;
767
+ #endif
742
768
743
769
static_assert ((!is_array<value_type>::value), " Character type of basic_string must not be an array" );
744
770
static_assert ((is_standard_layout<value_type>::value), " Character type of basic_string must be standard-layout" );
@@ -1885,16 +1911,16 @@ private:
1885
1911
__r_.first ().__l .__data_ = __p;
1886
1912
}
1887
1913
_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_ ) ;
1889
1915
}
1890
1916
_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_ ) ;
1892
1918
}
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 ]) );
1895
1921
}
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 ]) );
1898
1924
}
1899
1925
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer () _NOEXCEPT {
1900
1926
return __is_long () ? __get_long_pointer () : __get_short_pointer ();
0 commit comments