Skip to content

Commit 835c7aa

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 16cfad7 commit 835c7aa

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

libcxx/include/string

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)