Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions libcxx/include/__debug_utils/sanitizers.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,16 @@
# pragma GCC system_header
#endif

#if __has_feature(address_sanitizer)
// _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS determines whether the containers should provide ASAN container
// overflow checks. Some containers like std::string need stricter requirements in order to enable these
// checks and also need to check that the library was built with sanitizer support (_LIBCPP_INSTRUMENTED_WITH_ASAN).
#if __has_feature(address_sanitizer) && !defined(__SANITIZER_DISABLE_CONTAINER_OVERFLOW__)
# define _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS 1
#else
# define _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS 0
#endif

#if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS

extern "C" {
_LIBCPP_EXPORTED_FROM_ABI void
Expand All @@ -28,12 +37,12 @@ _LIBCPP_EXPORTED_FROM_ABI int
__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*);
}

#endif // __has_feature(address_sanitizer)
#endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS

_LIBCPP_BEGIN_NAMESPACE_STD

// ASan choices
#if __has_feature(address_sanitizer)
#if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1
#endif

Expand All @@ -57,7 +66,7 @@ _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container(
const void* __last_old_contained,
const void* __first_new_contained,
const void* __last_new_contained) {
#if !__has_feature(address_sanitizer)
#if !_LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
(void)__first_storage;
(void)__last_storage;
(void)__first_old_contained;
Expand Down Expand Up @@ -86,7 +95,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __annotate_contiguous_c
const void* __last_storage,
const void* __old_last_contained,
const void* __new_last_contained) {
#if !__has_feature(address_sanitizer)
#if !_LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
(void)__first_storage;
(void)__last_storage;
(void)__old_last_contained;
Expand Down
26 changes: 13 additions & 13 deletions libcxx/include/deque
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ private:
(void)__end;
(void)__annotation_type;
(void)__place;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
// __beg - index of the first item to annotate
// __end - index behind the last item to annotate (so last item + 1)
// __annotation_type - __asan_unposion or __asan_poison
Expand Down Expand Up @@ -1025,23 +1025,23 @@ private:
std::__annotate_double_ended_contiguous_container<_Allocator>(
__mem_beg, __mem_end, __old_beg, __old_end, __new_beg, __new_end);
}
# endif // __has_feature(address_sanitizer)
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
}

_LIBCPP_HIDE_FROM_ABI void __annotate_new(size_type __current_size) const _NOEXCEPT {
(void)__current_size;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
if (__current_size == 0)
__annotate_from_to(0, __map_.size() * __block_size, __asan_poison, __asan_back_moved);
else {
__annotate_from_to(0, __start_, __asan_poison, __asan_front_moved);
__annotate_from_to(__start_ + __current_size, __map_.size() * __block_size, __asan_poison, __asan_back_moved);
}
# endif // __has_feature(address_sanitizer)
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
}

_LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
if (empty()) {
for (size_t __i = 0; __i < __map_.size(); ++__i) {
__annotate_whole_block(__i, __asan_unposion);
Expand All @@ -1050,35 +1050,35 @@ private:
__annotate_from_to(0, __start_, __asan_unposion, __asan_front_moved);
__annotate_from_to(__start_ + size(), __map_.size() * __block_size, __asan_unposion, __asan_back_moved);
}
# endif // __has_feature(address_sanitizer)
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
}

_LIBCPP_HIDE_FROM_ABI void __annotate_increase_front(size_type __n) const _NOEXCEPT {
(void)__n;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
__annotate_from_to(__start_ - __n, __start_, __asan_unposion, __asan_front_moved);
# endif
}

_LIBCPP_HIDE_FROM_ABI void __annotate_increase_back(size_type __n) const _NOEXCEPT {
(void)__n;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
__annotate_from_to(__start_ + size(), __start_ + size() + __n, __asan_unposion, __asan_back_moved);
# endif
}

_LIBCPP_HIDE_FROM_ABI void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT {
(void)__old_size;
(void)__old_start;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
__annotate_from_to(__old_start, __old_start + (__old_size - size()), __asan_poison, __asan_front_moved);
# endif
}

_LIBCPP_HIDE_FROM_ABI void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT {
(void)__old_size;
(void)__old_start;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
__annotate_from_to(__old_start + size(), __old_start + __old_size, __asan_poison, __asan_back_moved);
# endif
}
Expand All @@ -1091,7 +1091,7 @@ private:
__annotate_whole_block(size_t __block_index, __asan_annotation_type __annotation_type) const _NOEXCEPT {
(void)__block_index;
(void)__annotation_type;
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
__map_const_iterator __block_it = __map_.begin() + __block_index;
const void* __block_start = std::__to_address(*__block_it);
const void* __block_end = std::__to_address(*__block_it + __block_size);
Expand All @@ -1104,7 +1104,7 @@ private:
}
# endif
}
# if __has_feature(address_sanitizer)
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS

public:
_LIBCPP_HIDE_FROM_ABI bool __verify_asan_annotations() const _NOEXCEPT {
Expand Down Expand Up @@ -1166,7 +1166,7 @@ public:
}

private:
# endif // __has_feature(address_sanitizer)
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
_LIBCPP_HIDE_FROM_ABI bool __maybe_remove_front_spare(bool __keep_one = true) {
if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) {
__annotate_whole_block(0, __asan_unposion);
Expand Down
22 changes: 13 additions & 9 deletions libcxx/include/string
Original file line number Diff line number Diff line change
Expand Up @@ -678,14 +678,18 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
_LIBCPP_PUSH_MACROS
# include <__undef_macros>

# if __has_feature(address_sanitizer) && _LIBCPP_INSTRUMENTED_WITH_ASAN
// Since std::string is partially instantiated in the built library, we require that the library
// has been built with ASAN support in order to enable the container checks in std::string.
//
// The _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS macro disables AddressSanitizer (ASan) instrumentation
// for a specific function, allowing memory accesses that would normally trigger ASan errors to proceed
// without crashing. This is useful for accessing parts of objects memory, which should not be accessed,
// such as unused bytes in short strings, that should never be accessed by other parts of the program.
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS && _LIBCPP_INSTRUMENTED_WITH_ASAN
# define _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING 1
# define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS __attribute__((__no_sanitize__("address")))
// This macro disables AddressSanitizer (ASan) instrumentation for a specific function,
// allowing memory accesses that would normally trigger ASan errors to proceed without crashing.
// This is useful for accessing parts of objects memory, which should not be accessed,
// such as unused bytes in short strings, that should never be accessed
// by other parts of the program.
# else
# define _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING 0
# define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
# endif

Expand Down Expand Up @@ -749,7 +753,7 @@ public:
//
// This string implementation doesn't contain any references into itself. It only contains a bit that says whether
// it is in small or large string mode, so the entire structure is trivially relocatable if its members are.
# if __has_feature(address_sanitizer) && _LIBCPP_INSTRUMENTED_WITH_ASAN
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
// When compiling with AddressSanitizer (ASan), basic_string cannot be trivially
// relocatable. Because the object's memory might be poisoned when its content
// is kept inside objects memory (short string optimization), instead of in allocated
Expand All @@ -764,7 +768,7 @@ public:
void>;
# endif

# if __has_feature(address_sanitizer) && _LIBCPP_INSTRUMENTED_WITH_ASAN
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __asan_volatile_wrapper(pointer const& __ptr) const {
if (__libcpp_is_constant_evaluated())
return __ptr;
Expand Down Expand Up @@ -2321,7 +2325,7 @@ private:
__annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const {
(void)__old_mid;
(void)__new_mid;
# if _LIBCPP_INSTRUMENTED_WITH_ASAN
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
# if defined(__APPLE__)
// TODO: remove after addressing issue #96099 (https://llvm.org/PR96099)
if (!__is_long())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===----------------------------------------------------------------------===//
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too happy about that test. It's somewhat vacuous to test #if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS since the test would pass if we just renamed that macro to something else.

//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// XFAIL: FROZEN-CXX03-HEADERS-FIXME

//
// Check that libc++ honors when __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ is set.
//

// RUN: %{cxx} %s %{flags} %{compile_flags} -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__
// RUN: %{cxx} %s %{flags} %{compile_flags} -fsanitize=address -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__

#include <vector>
#include <string>
#include <deque>

#if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
# error "Container overflow checks should be disabled in libc++"
#endif

int main(int, char**) {}
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ static_assert(!std::__libcpp_is_trivially_relocatable<std::array<NotTriviallyCop
static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 1> >::value, "");

// basic_string
#if !__has_feature(address_sanitizer) || !_LIBCPP_INSTRUMENTED_WITH_ASAN
#if !_LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
struct MyChar {
char c;
};
Expand Down
Loading