Skip to content

Commit 0dab486

Browse files
author
Advenam Tacet
committed
[libc++][ASan] Stop optimizations in std::basic_string
This commit stops some optimizations when compiling with ASan. - Short strings make std::basic_string to not be trivially relocatable, because memory has to be unpoisoned. It changes value of `__trivially_relocatable` when compiling with ASan. - It truns off compiler stack optimizations with `__asan_volatile_wrapper`, the function is not used when compiling without ASan. - It turns off instrumentation in a few functions.
1 parent 162366a commit 0dab486

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

libcxx/include/string

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,23 @@ template <class _CharT, class _Traits, class _Allocator>
711711
class basic_string {
712712
private:
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
715731
public:
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

Comments
 (0)