diff options
author | Advenam Tacet <advenam.tacet@trailofbits.com> | 2023-05-04 14:16:06 -0700 |
---|---|---|
committer | Nikolas Klauser <n_klauser@apple.com> | 2023-05-04 14:17:25 -0700 |
commit | 2fa1bec7a20bb23f2e6620085adb257dafaa3be0 (patch) | |
tree | fd8e343731fca6d078149b3a967d7fc1ff7aa1e0 | |
parent | bfbe137888151dfd506df6b3319d08c4de0e00f5 (diff) | |
download | llvm-2fa1bec7a20bb23f2e6620085adb257dafaa3be0.zip llvm-2fa1bec7a20bb23f2e6620085adb257dafaa3be0.tar.gz llvm-2fa1bec7a20bb23f2e6620085adb257dafaa3be0.tar.bz2 |
[ASan][libcxx] A way to turn off annotations for containers with a specific allocator
This revision is part of our efforts to support container annotations with (almost) every allocator.
That patch is necessary to enable support for most annotations (D136765). Without a way to turn off annotations, it's hard to use ASan with area allocators (no calls to destructors).
This is an answer to a request about it. This patch provides a solution to the aforementioned issue by introducing a new template structure `__asan_annotate_container_with_allocator`, which allows the disabling of container annotations for a specific allocator.
This patch also introduces `_LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS` FTM.
To turn off annotations, it is sufficient to create a template specialization with a false value using a [Unary Type Trait](https://en.cppreference.com/w/cpp/types/integral_constant).
The proposed structure is being used in the code enabling annotations for all allocators in `std::vector`, `std::basic_string`, and `std::deque`. (D136765 D146214 D146815)
Possibility to do it was added to ASan API in rGdd1b7b797a116eed588fd752fbe61d34deeb24e4 commit.
For context on not calling a destructor, look at https://eel.is/c++draft/basic.life#5 and notes there, you may also read a discussion in D136765.
Reviewed By: ldionne, philnik, #libc, hans
Spies: EricWF, mikhail.ramalho, #sanitizers, libcxx-commits, hans, vitalybuka
Differential Revision: https://reviews.llvm.org/D145628
-rw-r--r-- | libcxx/docs/UsingLibcxx.rst | 29 | ||||
-rw-r--r-- | libcxx/include/__memory/allocator_traits.h | 19 |
2 files changed, 48 insertions, 0 deletions
diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index ce944b5..a7ab788 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -523,3 +523,32 @@ Standard. Libc++ retroactively updates the Unicode Standard in older C++ versions. This allows the library to have better estimates for newly introduced Unicode code points, without requiring the user to use the latest C++ version in their code base. +======= +Turning off ASan annotation in containers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``__asan_annotate_container_with_allocator`` is a customization point to allow users to disable +`Address Sanitizer annotations for containers <https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow>`_ for specific allocators. This may be necessary for allocators that access allocated memory. +This customization point exists only when ``_LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS`` Feature Test Macro is defined. + +For allocators not running destructors, it is also possible to `bulk-unpoison memory <https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning>`_ instead of disabling annotations altogether. + +The struct may be specialized for user-defined allocators. It is a `Cpp17UnaryTypeTrait <http://eel.is/c++draft/type.traits#meta.rqmts>`_ with a base characteristic of ``true_type`` if the container is allowed to use annotations and ``false_type`` otherwise. + +The annotations for a ``user_allocator`` can be disabled like this: + +.. code-block:: cpp + + #ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS + template <class T> + struct std::__asan_annotate_container_with_allocator<user_allocator<T>> : std::false_type {}; + #endif + +Why may I want to turn it off? +------------------------------ + +There are a few reasons why you may want to turn off annotations for an allocator. +Unpoisoning may not be an option, if (for example) you are not maintaining the allocator. + +* You are using allocator, which does not call destructor during deallocation. +* You are aware that memory allocated with an allocator may be accessed, even when unused by container. diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index 57f88a3..4ed4416 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -401,6 +401,25 @@ struct __is_cpp17_copy_insertable<_Alloc, __enable_if_t< : __is_cpp17_move_insertable<_Alloc> { }; +// ASan choices +#ifndef _LIBCPP_HAS_NO_ASAN +# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 +#endif + +#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS +template <class _Alloc> +struct __asan_annotate_container_with_allocator +# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1600 + : true_type {}; +# else + // TODO LLVM18: Remove the special-casing + : false_type {}; +# endif + +template <class _Tp> +struct __asan_annotate_container_with_allocator<allocator<_Tp> > : true_type {}; +#endif + #undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX _LIBCPP_END_NAMESPACE_STD |