diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -105,6 +105,33 @@ // simultaneously. int __sanitizer_acquire_crash_state(); +/// Returns true (one) if memory inside the object may be poisoned. +/// +/// Proper poisoning could occur, for example, with +/// __sanitizer_annotate_contiguous_container. +/// Memory of the object may be poisoned only if: +/// - sizeof(obj) % ASAN_GRANULARITY == 0 +/// - &obj % ASAN_GRANULARITY == 0 +/// +/// Note: user is responsible for consideration of how +/// memory is poisoned inside the object, that function +/// provides a very basic check. +/// +/// Note: this function is irrelevant for objects +/// keeping content in external memory buffer like vector . +/// It is important for cases like std::basic_string with +/// short string optimization (content is kept in objects memory). +/// +/// If this function returns true (one) and object of interest is +/// [a; c), you always can poison [b;c) and keep [a;b) +/// not poisoned for every b in [a; c). +/// +/// \param address Address of the object &obj +/// \param size Size of the object sizeof(obj) +/// +/// \returns True if memory of the object may be poisoned. +int __sanitizer_is_annotable(const void *address, const unsigned long size); + /// Annotates the current state of a contiguous container, such as /// std::vector, std::string, or similar. /// diff --git a/compiler-rt/lib/asan/asan_poisoning.cpp b/compiler-rt/lib/asan/asan_poisoning.cpp --- a/compiler-rt/lib/asan/asan_poisoning.cpp +++ b/compiler-rt/lib/asan/asan_poisoning.cpp @@ -342,6 +342,31 @@ PoisonAlignedStackMemory(addr, size, false); } +// Simple check if memory inside the object may be poisoned. +// User has to make sure that poisoning is possible, +// that function only provides a basic check. +// Remember that there are situations when you can poison objects +// memory even when this function returns false, but +// you have to know programs structure, and it's not adviced +// in general. +// +// Note: this function is irrelevant for objects +// keeping content in external memory buffer like vector . +// It is important for cases like std::basic_string with +// short string optimization (content is kept in objects memory). +// +// If this function returns true (one) and object of +// interest is [a; c), you always can poison [b;c) +// and keep [a;b) not poisoned for every b in [a; c). +int __sanitizer_is_annotable(const void *address_p, + const unsigned long size_v) { + uptr address = reinterpret_cast(address_p); + uptr size = static_cast(size_v); + uptr granularity = ASAN_SHADOW_GRANULARITY; + + return IsAligned(size, granularity) && IsAligned(address, granularity); +} + void __sanitizer_annotate_contiguous_container(const void *beg_p, const void *end_p, const void *old_mid_p, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc @@ -14,6 +14,7 @@ INTERFACE_FUNCTION(__sanitizer_set_report_path) INTERFACE_FUNCTION(__sanitizer_set_report_fd) INTERFACE_FUNCTION(__sanitizer_get_report_path) +INTERFACE_FUNCTION(__sanitizer_is_annotable) INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) INTERFACE_WEAK_FUNCTION(__sanitizer_on_print) INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h @@ -72,6 +72,8 @@ const void *__sanitizer_contiguous_container_find_bad_address(const void *beg, const void *mid, const void *end); +SANITIZER_INTERFACE_ATTRIBUTE +int __sanitizer_is_annotable(const void *address, const unsigned long); SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path,