diff --git a/compiler-rt/include/CMakeLists.txt b/compiler-rt/include/CMakeLists.txt index 242d62b9b447b..746a328b05510 100644 --- a/compiler-rt/include/CMakeLists.txt +++ b/compiler-rt/include/CMakeLists.txt @@ -3,6 +3,7 @@ if (COMPILER_RT_BUILD_SANITIZERS) sanitizer/allocator_interface.h sanitizer/asan_interface.h sanitizer/common_interface_defs.h + sanitizer/container_overflow_defs.h sanitizer/coverage_interface.h sanitizer/dfsan_interface.h sanitizer/hwasan_interface.h diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h index 51104093758cd..2e1f6265a66a8 100644 --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -110,250 +110,11 @@ void SANITIZER_CDECL __sanitizer_unaligned_store64(void *p, uint64_t x); // simultaneously. int SANITIZER_CDECL __sanitizer_acquire_crash_state(); -/// Annotates the current state of a contiguous container, such as -/// std::vector, std::string, or similar. -/// -/// A contiguous container is a container that keeps all of its elements -/// in a contiguous region of memory. The container owns the region of memory -/// [beg, end); the memory [beg, mid) is used to store the -/// current elements, and the memory [mid, end) is reserved for future -/// elements (beg <= mid <= end). For example, in -/// std::vector<> v: -/// -/// \code -/// beg = &v[0]; -/// end = beg + v.capacity() * sizeof(v[0]); -/// mid = beg + v.size() * sizeof(v[0]); -/// \endcode -/// -/// This annotation tells the Sanitizer tool about the current state of the -/// container so that the tool can report errors when memory from -/// [mid, end) is accessed. Insert this annotation into methods like -/// push_back() or pop_back(). Supply the old and new values of -/// mid(old_mid and new_mid). In the initial -/// state mid == end, so that should be the final state when the -/// container is destroyed or when the container reallocates the storage. -/// -/// For ASan, beg no longer needs to be 8-aligned, -/// first and last granule may be shared with other objects -/// and therefore the function can be used for any allocator. -/// -/// The following example shows how to use the function: -/// -/// \code -/// int32_t x[3]; // 12 bytes -/// char *beg = (char*)&x[0]; -/// char *end = beg + 12; -/// __sanitizer_annotate_contiguous_container(beg, end, beg, end); -/// \endcode -/// -/// \note Use this function with caution and do not use for anything other -/// than vector-like classes. -/// \note Unaligned beg or end may miss bugs in -/// these granules. -/// -/// \param beg Beginning of memory region. -/// \param end End of memory region. -/// \param old_mid Old middle of memory region. -/// \param new_mid New middle of memory region. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline void SANITIZER_CDECL -__sanitizer_annotate_contiguous_container(const void *beg, const void *end, - const void *old_mid, - const void *new_mid) {} -#else -void SANITIZER_CDECL __sanitizer_annotate_contiguous_container( - const void *beg, const void *end, const void *old_mid, const void *new_mid); -#endif - -/// Similar to __sanitizer_annotate_contiguous_container. -/// -/// Annotates the current state of a contiguous container memory, -/// such as std::deque's single chunk, when the boundries are moved. -/// -/// A contiguous chunk is a chunk that keeps all of its elements -/// in a contiguous region of memory. The container owns the region of memory -/// [storage_beg, storage_end); the memory [container_beg, -/// container_end) is used to store the current elements, and the memory -/// [storage_beg, container_beg), [container_end, storage_end) is -/// reserved for future elements (storage_beg <= container_beg <= -/// container_end <= storage_end). For example, in std::deque : -/// - chunk with a frist deques element will have container_beg equal to address -/// of the first element. -/// - in every next chunk with elements, true is container_beg == -/// storage_beg . -/// -/// Argument requirements: -/// During unpoisoning memory of empty container (before first element is -/// added): -/// - old_container_beg_p == old_container_end_p -/// During poisoning after last element was removed: -/// - new_container_beg_p == new_container_end_p -/// \param storage_beg Beginning of memory region. -/// \param storage_end End of memory region. -/// \param old_container_beg Old beginning of used region. -/// \param old_container_end End of used region. -/// \param new_container_beg New beginning of used region. -/// \param new_container_end New end of used region. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline void - SANITIZER_CDECL __sanitizer_annotate_double_ended_contiguous_container( - const void *storage_beg, const void *storage_end, - const void *old_container_beg, const void *old_container_end, - const void *new_container_beg, const void *new_container_end) {} -#else -void SANITIZER_CDECL __sanitizer_annotate_double_ended_contiguous_container( - const void *storage_beg, const void *storage_end, - const void *old_container_beg, const void *old_container_end, - const void *new_container_beg, const void *new_container_end); -#endif - -/// Copies memory annotations from a source storage region to a destination -/// storage region. After the operation, the destination region has the same -/// memory annotations as the source region, as long as sanitizer limitations -/// allow it (more bytes may be unpoisoned than in the source region, resulting -/// in more false negatives, but never false positives). If the source and -/// destination regions overlap, only the minimal required changes are made to -/// preserve the correct annotations. Old storage bytes that are not in the new -/// storage should have the same annotations, as long as sanitizer limitations -/// allow it. -/// -/// This function is primarily designed to be used when moving trivially -/// relocatable objects that may have poisoned memory, making direct copying -/// problematic under sanitizer. However, this function does not move memory -/// content itself, only annotations. -/// -/// A contiguous container is a container that keeps all of its elements in a -/// contiguous region of memory. The container owns the region of memory -/// [src_begin, src_end) and [dst_begin, dst_end). The memory -/// within these regions may be alternately poisoned and non-poisoned, with -/// possibly smaller poisoned and unpoisoned regions. -/// -/// If this function fully poisons a granule, it is marked as "container -/// overflow". -/// -/// Argument requirements: The destination container must have the same size as -/// the source container, which is inferred from the beginning and end of the -/// source region. Addresses may be granule-unaligned, but this may affect -/// performance. -/// -/// \param src_begin Begin of the source container region. -/// \param src_end End of the source container region. -/// \param dst_begin Begin of the destination container region. -/// \param dst_end End of the destination container region. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline void SANITIZER_CDECL -__sanitizer_copy_contiguous_container_annotations(const void *src_begin, - const void *src_end, - const void *dst_begin, - const void *dst_end) {} -#else -void SANITIZER_CDECL __sanitizer_copy_contiguous_container_annotations( - const void *src_begin, const void *src_end, const void *dst_begin, - const void *dst_end); -#endif - -/// Returns true if the contiguous container [beg, end) is properly -/// poisoned. -/// -/// Proper poisoning could occur, for example, with -/// __sanitizer_annotate_contiguous_container), that is, if -/// [beg, mid) is addressable and [mid, end) is unaddressable. -/// Full verification requires O (end - beg) time; this function tries -/// to avoid such complexity by touching only parts of the container around -/// beg, mid, and end. -/// -/// \param beg Beginning of memory region. -/// \param mid Middle of memory region. -/// \param end Old end of memory region. -/// -/// \returns True if the contiguous container [beg, end) is properly -/// poisoned. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline int - SANITIZER_CDECL __sanitizer_verify_contiguous_container(const void *beg, - const void *mid, - const void *end) {} -#else -int SANITIZER_CDECL __sanitizer_verify_contiguous_container(const void *beg, - const void *mid, - const void *end); -#endif - -/// Returns true if the double ended contiguous -/// container [storage_beg, storage_end) is properly poisoned. -/// -/// Proper poisoning could occur, for example, with -/// __sanitizer_annotate_double_ended_contiguous_container), that is, if -/// [storage_beg, container_beg) is not addressable, [container_beg, -/// container_end) is addressable and [container_end, end) is -/// unaddressable. Full verification requires O (storage_end - -/// storage_beg) time; this function tries to avoid such complexity by -/// touching only parts of the container around storage_beg, -/// container_beg, container_end, and -/// storage_end. -/// -/// \param storage_beg Beginning of memory region. -/// \param container_beg Beginning of used region. -/// \param container_end End of used region. -/// \param storage_end End of memory region. -/// -/// \returns True if the double-ended contiguous container [storage_beg, -/// container_beg, container_end, end) is properly poisoned - only -/// [container_beg; container_end) is addressable. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline int SANITIZER_CDECL -__sanitizer_verify_double_ended_contiguous_container(const void *storage_beg, - const void *container_beg, - const void *container_end, - const void *storage_end) {} -#else -int SANITIZER_CDECL __sanitizer_verify_double_ended_contiguous_container( - const void *storage_beg, const void *container_beg, - const void *container_end, const void *storage_end); -#endif - -/// Similar to __sanitizer_verify_contiguous_container() but also -/// returns the address of the first improperly poisoned byte. -/// -/// Returns NULL if the area is poisoned properly. -/// -/// \param beg Beginning of memory region. -/// \param mid Middle of memory region. -/// \param end Old end of memory region. -/// -/// \returns The bad address or NULL. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline const void *SANITIZER_CDECL -__sanitizer_contiguous_container_find_bad_address(const void *beg, - const void *mid, - const void *end) {} -#else -const void *SANITIZER_CDECL __sanitizer_contiguous_container_find_bad_address( - const void *beg, const void *mid, const void *end); -#endif - -/// returns the address of the first improperly poisoned byte. -/// -/// Returns NULL if the area is poisoned properly. -/// -/// \param storage_beg Beginning of memory region. -/// \param container_beg Beginning of used region. -/// \param container_end End of used region. -/// \param storage_end End of memory region. -/// -/// \returns The bad address or NULL. -#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ -__attribute__((__internal_linkage__)) inline const void *SANITIZER_CDECL -__sanitizer_double_ended_contiguous_container_find_bad_address( - const void *storage_beg, const void *container_beg, - const void *container_end, const void *storage_end) {} -#else -const void *SANITIZER_CDECL -__sanitizer_double_ended_contiguous_container_find_bad_address( - const void *storage_beg, const void *container_beg, - const void *container_end, const void *storage_end); -#endif +// The container overflow function declarations used to be inline here, but in +// order to allow libcxx to directly use the header they are now in a separate +// file. This file is included here to avoid breaking anyone reliant on +// the definitions appearing in the current file. +#include "container_overflow_defs.h" /// Prints the stack trace leading to this call (useful for calling from the /// debugger). diff --git a/compiler-rt/include/sanitizer/container_overflow_defs.h b/compiler-rt/include/sanitizer/container_overflow_defs.h new file mode 100644 index 0000000000000..fe1d0e9e98f30 --- /dev/null +++ b/compiler-rt/include/sanitizer/container_overflow_defs.h @@ -0,0 +1,275 @@ +//===-- sanitizer/container_overflow_defs.h ---------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Public sanitizer interface defs for container overflow checks. +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_CONTAINER_OVERFLOW_DEFS_H +#define SANITIZER_CONTAINER_OVERFLOW_DEFS_H + +// Windows allows a user to set their default calling convention, but we always +// use __cdecl +#ifdef _WIN32 +#define SANITIZER_CDECL __cdecl +#else +#define SANITIZER_CDECL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/// Annotates the current state of a contiguous container, such as +/// std::vector, std::string, or similar. +/// +/// A contiguous container is a container that keeps all of its elements +/// in a contiguous region of memory. The container owns the region of memory +/// [beg, end); the memory [beg, mid) is used to store the +/// current elements, and the memory [mid, end) is reserved for future +/// elements (beg <= mid <= end). For example, in +/// std::vector<> v: +/// +/// \code +/// beg = &v[0]; +/// end = beg + v.capacity() * sizeof(v[0]); +/// mid = beg + v.size() * sizeof(v[0]); +/// \endcode +/// +/// This annotation tells the Sanitizer tool about the current state of the +/// container so that the tool can report errors when memory from +/// [mid, end) is accessed. Insert this annotation into methods like +/// push_back() or pop_back(). Supply the old and new values of +/// mid(old_mid and new_mid). In the initial +/// state mid == end, so that should be the final state when the +/// container is destroyed or when the container reallocates the storage. +/// +/// For ASan, beg no longer needs to be 8-aligned, +/// first and last granule may be shared with other objects +/// and therefore the function can be used for any allocator. +/// +/// The following example shows how to use the function: +/// +/// \code +/// int32_t x[3]; // 12 bytes +/// char *beg = (char*)&x[0]; +/// char *end = beg + 12; +/// __sanitizer_annotate_contiguous_container(beg, end, beg, end); +/// \endcode +/// +/// \note Use this function with caution and do not use for anything other +/// than vector-like classes. +/// \note Unaligned beg or end may miss bugs in +/// these granules. +/// +/// \param __beg Beginning of memory region. +/// \param __end End of memory region. +/// \param __old_mid Old middle of memory region. +/// \param __new_mid New middle of memory region. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline void SANITIZER_CDECL +__sanitizer_annotate_contiguous_container(const void *__beg, const void *__end, + const void *__old_mid, + const void *__new_mid) {} +#else +void SANITIZER_CDECL __sanitizer_annotate_contiguous_container( + const void *__beg, const void *__end, const void *__old_mid, + const void *__new_mid); +#endif + +/// Similar to __sanitizer_annotate_contiguous_container. +/// +/// Annotates the current state of a contiguous container memory, +/// such as std::deque's single chunk, when the boundries are moved. +/// +/// A contiguous chunk is a chunk that keeps all of its elements +/// in a contiguous region of memory. The container owns the region of memory +/// [storage_beg, storage_end); the memory [container_beg, +/// container_end) is used to store the current elements, and the memory +/// [storage_beg, container_beg), [container_end, storage_end) is +/// reserved for future elements (storage_beg <= container_beg <= +/// container_end <= storage_end). For example, in std::deque : +/// - chunk with a frist deques element will have container_beg equal to address +/// of the first element. +/// - in every next chunk with elements, true is container_beg == +/// storage_beg . +/// +/// Argument requirements: +/// During unpoisoning memory of empty container (before first element is +/// added): +/// - old_container_beg_p == old_container_end_p +/// During poisoning after last element was removed: +/// - new_container_beg_p == new_container_end_p +/// \param __storage_beg Beginning of memory region. +/// \param __storage_end End of memory region. +/// \param __old_container_beg Old beginning of used region. +/// \param __old_container_end End of used region. +/// \param __new_container_beg New beginning of used region. +/// \param __new_container_end New end of used region. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline void + SANITIZER_CDECL __sanitizer_annotate_double_ended_contiguous_container( + const void *__storage_beg, const void *__storage_end, + const void *__old_container_beg, const void *__old_container_end, + const void *__new_container_beg, const void *__new_container_end) {} +#else +void SANITIZER_CDECL __sanitizer_annotate_double_ended_contiguous_container( + const void *__storage_beg, const void *__storage_end, + const void *__old_container_beg, const void *__old_container_end, + const void *__new_container_beg, const void *__new_container_end); +#endif + +/// Copies memory annotations from a source storage region to a destination +/// storage region. After the operation, the destination region has the same +/// memory annotations as the source region, as long as sanitizer limitations +/// allow it (more bytes may be unpoisoned than in the source region, resulting +/// in more false negatives, but never false positives). If the source and +/// destination regions overlap, only the minimal required changes are made to +/// preserve the correct annotations. Old storage bytes that are not in the new +/// storage should have the same annotations, as long as sanitizer limitations +/// allow it. +/// +/// This function is primarily designed to be used when moving trivially +/// relocatable objects that may have poisoned memory, making direct copying +/// problematic under sanitizer. However, this function does not move memory +/// content itself, only annotations. +/// +/// A contiguous container is a container that keeps all of its elements in a +/// contiguous region of memory. The container owns the region of memory +/// [src_begin, src_end) and [dst_begin, dst_end). The memory +/// within these regions may be alternately poisoned and non-poisoned, with +/// possibly smaller poisoned and unpoisoned regions. +/// +/// If this function fully poisons a granule, it is marked as "container +/// overflow". +/// +/// Argument requirements: The destination container must have the same size as +/// the source container, which is inferred from the beginning and end of the +/// source region. Addresses may be granule-unaligned, but this may affect +/// performance. +/// +/// \param __src_begin Begin of the source container region. +/// \param __src_end End of the source container region. +/// \param __dst_begin Begin of the destination container region. +/// \param __dst_end End of the destination container region. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline void SANITIZER_CDECL +__sanitizer_copy_contiguous_container_annotations(const void *__src_begin, + const void *__src_end, + const void *__dst_begin, + const void *__dst_end) {} +#else +void SANITIZER_CDECL __sanitizer_copy_contiguous_container_annotations( + const void *__src_begin, const void *__src_end, const void *__dst_begin, + const void *__dst_end); +#endif + +/// Returns true if the contiguous container [beg, end) is properly +/// poisoned. +/// +/// Proper poisoning could occur, for example, with +/// __sanitizer_annotate_contiguous_container), that is, if +/// [beg, mid) is addressable and [mid, end) is unaddressable. +/// Full verification requires O (end - beg) time; this function tries +/// to avoid such complexity by touching only parts of the container around +/// beg, mid, and end. +/// +/// \param __beg Beginning of memory region. +/// \param __mid Middle of memory region. +/// \param __end Old end of memory region. +/// +/// \returns True if the contiguous container [beg, end) is properly +/// poisoned. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline int SANITIZER_CDECL +__sanitizer_verify_contiguous_container(const void *__beg, const void *__mid, + const void *__end) {} +#else +int SANITIZER_CDECL __sanitizer_verify_contiguous_container(const void *__beg, + const void *__mid, + const void *__end); +#endif + +/// Returns true if the double ended contiguous +/// container [storage_beg, storage_end) is properly poisoned. +/// +/// Proper poisoning could occur, for example, with +/// __sanitizer_annotate_double_ended_contiguous_container), that is, if +/// [storage_beg, container_beg) is not addressable, [container_beg, +/// container_end) is addressable and [container_end, end) is +/// unaddressable. Full verification requires O (storage_end - +/// storage_beg) time; this function tries to avoid such complexity by +/// touching only parts of the container around storage_beg, +/// container_beg, container_end, and +/// storage_end. +/// +/// \param __storage_beg Beginning of memory region. +/// \param __container_beg Beginning of used region. +/// \param __container_end End of used region. +/// \param __storage_end End of memory region. +/// +/// \returns True if the double-ended contiguous container [storage_beg, +/// container_beg, container_end, end) is properly poisoned - only +/// [container_beg; container_end) is addressable. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline int + SANITIZER_CDECL __sanitizer_verify_double_ended_contiguous_container( + const void *__storage_beg, const void *__container_beg, + const void *__container_end, const void *__storage_end) {} +#else +int SANITIZER_CDECL __sanitizer_verify_double_ended_contiguous_container( + const void *__storage_beg, const void *__container_beg, + const void *__container_end, const void *__storage_end); +#endif + +/// Similar to __sanitizer_verify_contiguous_container() but also +/// returns the address of the first improperly poisoned byte. +/// +/// Returns NULL if the area is poisoned properly. +/// +/// \param __beg Beginning of memory region. +/// \param __mid Middle of memory region. +/// \param __end Old end of memory region. +/// +/// \returns The bad address or NULL. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline const void *SANITIZER_CDECL +__sanitizer_contiguous_container_find_bad_address(const void *__beg, + const void *__mid, + const void *__end) {} +#else +const void *SANITIZER_CDECL __sanitizer_contiguous_container_find_bad_address( + const void *__beg, const void *__mid, const void *__end); +#endif + +/// returns the address of the first improperly poisoned byte. +/// +/// Returns NULL if the area is poisoned properly. +/// +/// \param __storage_beg Beginning of memory region. +/// \param __container_beg Beginning of used region. +/// \param __container_end End of used region. +/// \param __storage_end End of memory region. +/// +/// \returns The bad address or NULL. +#ifdef __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ +__attribute__((__internal_linkage__)) inline const void *SANITIZER_CDECL +__sanitizer_double_ended_contiguous_container_find_bad_address( + const void *__storage_beg, const void *__container_beg, + const void *__container_end, const void *__storage_end) {} +#else +const void *SANITIZER_CDECL +__sanitizer_double_ended_contiguous_container_find_bad_address( + const void *__storage_beg, const void *__container_beg, + const void *__container_end, const void *__storage_end); +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // SANITIZER_CONTAINER_OVERFLOW_DEFS_H