Skip to content

Commit 7a4cab0

Browse files
committed
[libc++] Honor __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ in libc++
Address sanitizer recently got a new macro __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ which is intended to disable container overflow checks in libraries (either the standard library or user libraries that might provide such checks). This patch makes libc++ honor that macro and, in addition, cleans up how these checks are enabled for string (which is special) by introducing a macro just for string.
1 parent 244b230 commit 7a4cab0

File tree

5 files changed

+67
-28
lines changed

5 files changed

+67
-28
lines changed

libcxx/include/__debug_utils/sanitizers.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,16 @@
1717
# pragma GCC system_header
1818
#endif
1919

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

2231
extern "C" {
2332
_LIBCPP_EXPORTED_FROM_ABI void
@@ -28,12 +37,12 @@ _LIBCPP_EXPORTED_FROM_ABI int
2837
__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*);
2938
}
3039

31-
#endif // __has_feature(address_sanitizer)
40+
#endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
3241

3342
_LIBCPP_BEGIN_NAMESPACE_STD
3443

3544
// ASan choices
36-
#if __has_feature(address_sanitizer)
45+
#if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
3746
# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1
3847
#endif
3948

@@ -57,7 +66,7 @@ _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container(
5766
const void* __last_old_contained,
5867
const void* __first_new_contained,
5968
const void* __last_new_contained) {
60-
#if !__has_feature(address_sanitizer)
69+
#if !_LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
6170
(void)__first_storage;
6271
(void)__last_storage;
6372
(void)__first_old_contained;
@@ -86,7 +95,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __annotate_contiguous_c
8695
const void* __last_storage,
8796
const void* __old_last_contained,
8897
const void* __new_last_contained) {
89-
#if !__has_feature(address_sanitizer)
98+
#if !_LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
9099
(void)__first_storage;
91100
(void)__last_storage;
92101
(void)__old_last_contained;

libcxx/include/deque

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ private:
932932
(void)__end;
933933
(void)__annotation_type;
934934
(void)__place;
935-
# if __has_feature(address_sanitizer)
935+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
936936
// __beg - index of the first item to annotate
937937
// __end - index behind the last item to annotate (so last item + 1)
938938
// __annotation_type - __asan_unposion or __asan_poison
@@ -1025,23 +1025,23 @@ private:
10251025
std::__annotate_double_ended_contiguous_container<_Allocator>(
10261026
__mem_beg, __mem_end, __old_beg, __old_end, __new_beg, __new_end);
10271027
}
1028-
# endif // __has_feature(address_sanitizer)
1028+
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10291029
}
10301030

10311031
_LIBCPP_HIDE_FROM_ABI void __annotate_new(size_type __current_size) const _NOEXCEPT {
10321032
(void)__current_size;
1033-
# if __has_feature(address_sanitizer)
1033+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10341034
if (__current_size == 0)
10351035
__annotate_from_to(0, __map_.size() * __block_size, __asan_poison, __asan_back_moved);
10361036
else {
10371037
__annotate_from_to(0, __start_, __asan_poison, __asan_front_moved);
10381038
__annotate_from_to(__start_ + __current_size, __map_.size() * __block_size, __asan_poison, __asan_back_moved);
10391039
}
1040-
# endif // __has_feature(address_sanitizer)
1040+
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10411041
}
10421042

10431043
_LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
1044-
# if __has_feature(address_sanitizer)
1044+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10451045
if (empty()) {
10461046
for (size_t __i = 0; __i < __map_.size(); ++__i) {
10471047
__annotate_whole_block(__i, __asan_unposion);
@@ -1050,35 +1050,35 @@ private:
10501050
__annotate_from_to(0, __start_, __asan_unposion, __asan_front_moved);
10511051
__annotate_from_to(__start_ + size(), __map_.size() * __block_size, __asan_unposion, __asan_back_moved);
10521052
}
1053-
# endif // __has_feature(address_sanitizer)
1053+
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10541054
}
10551055

10561056
_LIBCPP_HIDE_FROM_ABI void __annotate_increase_front(size_type __n) const _NOEXCEPT {
10571057
(void)__n;
1058-
# if __has_feature(address_sanitizer)
1058+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10591059
__annotate_from_to(__start_ - __n, __start_, __asan_unposion, __asan_front_moved);
10601060
# endif
10611061
}
10621062

10631063
_LIBCPP_HIDE_FROM_ABI void __annotate_increase_back(size_type __n) const _NOEXCEPT {
10641064
(void)__n;
1065-
# if __has_feature(address_sanitizer)
1065+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10661066
__annotate_from_to(__start_ + size(), __start_ + size() + __n, __asan_unposion, __asan_back_moved);
10671067
# endif
10681068
}
10691069

10701070
_LIBCPP_HIDE_FROM_ABI void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT {
10711071
(void)__old_size;
10721072
(void)__old_start;
1073-
# if __has_feature(address_sanitizer)
1073+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10741074
__annotate_from_to(__old_start, __old_start + (__old_size - size()), __asan_poison, __asan_front_moved);
10751075
# endif
10761076
}
10771077

10781078
_LIBCPP_HIDE_FROM_ABI void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT {
10791079
(void)__old_size;
10801080
(void)__old_start;
1081-
# if __has_feature(address_sanitizer)
1081+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10821082
__annotate_from_to(__old_start + size(), __old_start + __old_size, __asan_poison, __asan_back_moved);
10831083
# endif
10841084
}
@@ -1091,7 +1091,7 @@ private:
10911091
__annotate_whole_block(size_t __block_index, __asan_annotation_type __annotation_type) const _NOEXCEPT {
10921092
(void)__block_index;
10931093
(void)__annotation_type;
1094-
# if __has_feature(address_sanitizer)
1094+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
10951095
__map_const_iterator __block_it = __map_.begin() + __block_index;
10961096
const void* __block_start = std::__to_address(*__block_it);
10971097
const void* __block_end = std::__to_address(*__block_it + __block_size);
@@ -1104,7 +1104,7 @@ private:
11041104
}
11051105
# endif
11061106
}
1107-
# if __has_feature(address_sanitizer)
1107+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
11081108

11091109
public:
11101110
_LIBCPP_HIDE_FROM_ABI bool __verify_asan_annotations() const _NOEXCEPT {
@@ -1166,7 +1166,7 @@ public:
11661166
}
11671167

11681168
private:
1169-
# endif // __has_feature(address_sanitizer)
1169+
# endif // _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
11701170
_LIBCPP_HIDE_FROM_ABI bool __maybe_remove_front_spare(bool __keep_one = true) {
11711171
if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) {
11721172
__annotate_whole_block(0, __asan_unposion);

libcxx/include/string

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -678,14 +678,18 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
678678
_LIBCPP_PUSH_MACROS
679679
# include <__undef_macros>
680680

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

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

767-
# if __has_feature(address_sanitizer) && _LIBCPP_INSTRUMENTED_WITH_ASAN
771+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
768772
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __asan_volatile_wrapper(pointer const& __ptr) const {
769773
if (__libcpp_is_constant_evaluated())
770774
return __ptr;
@@ -2321,7 +2325,7 @@ private:
23212325
__annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const {
23222326
(void)__old_mid;
23232327
(void)__new_mid;
2324-
# if _LIBCPP_INSTRUMENTED_WITH_ASAN
2328+
# if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
23252329
# if defined(__APPLE__)
23262330
// TODO: remove after addressing issue #96099 (https://llvm.org/PR96099)
23272331
if (!__is_long())
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
10+
11+
//
12+
// Check that libc++ honors when __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ is set.
13+
//
14+
15+
// RUN: %{cxx} %s %{flags} %{compile_flags} -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__
16+
// RUN: %{cxx} %s %{flags} %{compile_flags} -fsanitize=address -D__SANITIZER_DISABLE_CONTAINER_OVERFLOW__
17+
18+
#include <vector>
19+
#include <string>
20+
#include <deque>
21+
22+
#if _LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS
23+
# error "Container overflow checks should be disabled in libc++"
24+
#endif
25+
26+
int main(int, char**) {}

libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static_assert(!std::__libcpp_is_trivially_relocatable<std::array<NotTriviallyCop
103103
static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 1> >::value, "");
104104

105105
// basic_string
106-
#if !__has_feature(address_sanitizer) || !_LIBCPP_INSTRUMENTED_WITH_ASAN
106+
#if !_LIBCPP_ENABLE_ASAN_CONTAINER_CHECKS_FOR_STRING
107107
struct MyChar {
108108
char c;
109109
};

0 commit comments

Comments
 (0)