diff options
-rw-r--r-- | include/sanitizer/common_interface_defs.h | 6 | ||||
-rw-r--r-- | lib/asan/asan_poisoning.cc | 25 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_interface_internal.h | 5 | ||||
-rw-r--r-- | test/asan/TestCases/contiguous_container.cc | 12 |
4 files changed, 36 insertions, 12 deletions
diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h index 4cba61a49..b736ed9e5 100644 --- a/include/sanitizer/common_interface_defs.h +++ b/include/sanitizer/common_interface_defs.h @@ -105,6 +105,12 @@ extern "C" { int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); + // Similar to __sanitizer_verify_contiguous_container but returns the address + // of the first improperly poisoned byte otherwise. Returns null if the area + // is poisoned properly. + const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg, const void *mid, const void *end); + // Print the stack trace leading to this call. Useful for debugging user code. void __sanitizer_print_stack_trace(); diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc index 569d359aa..0082e845f 100644 --- a/lib/asan/asan_poisoning.cc +++ b/lib/asan/asan_poisoning.cc @@ -375,10 +375,10 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p, } } -int __sanitizer_verify_contiguous_container(const void *beg_p, - const void *mid_p, - const void *end_p) { - if (!flags()->detect_container_overflow) return 1; +const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg_p, const void *mid_p, const void *end_p) { + if (!flags()->detect_container_overflow) + return nullptr; uptr beg = reinterpret_cast<uptr>(beg_p); uptr end = reinterpret_cast<uptr>(end_p); uptr mid = reinterpret_cast<uptr>(mid_p); @@ -395,17 +395,24 @@ int __sanitizer_verify_contiguous_container(const void *beg_p, uptr r3_end = end; for (uptr i = r1_beg; i < r1_end; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast<const void *>(i); for (uptr i = r2_beg; i < mid; i++) if (AddressIsPoisoned(i)) - return 0; + return reinterpret_cast<const void *>(i); for (uptr i = mid; i < r2_end; i++) if (!AddressIsPoisoned(i)) - return 0; + return reinterpret_cast<const void *>(i); for (uptr i = r3_beg; i < r3_end; i++) if (!AddressIsPoisoned(i)) - return 0; - return 1; + return reinterpret_cast<const void *>(i); + return nullptr; +} + +int __sanitizer_verify_contiguous_container(const void *beg_p, + const void *mid_p, + const void *end_p) { + return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p, + end_p) == nullptr; } extern "C" SANITIZER_INTERFACE_ATTRIBUTE diff --git a/lib/sanitizer_common/sanitizer_interface_internal.h b/lib/sanitizer_common/sanitizer_interface_internal.h index 94d9f4e95..b11ae3010 100644 --- a/lib/sanitizer_common/sanitizer_interface_internal.h +++ b/lib/sanitizer_common/sanitizer_interface_internal.h @@ -53,6 +53,9 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, const void *end); -} // extern "C" + SANITIZER_INTERFACE_ATTRIBUTE + const void *__sanitizer_contiguous_container_find_bad_address( + const void *beg, const void *mid, const void *end); + } // extern "C" #endif // SANITIZER_INTERFACE_INTERNAL_H diff --git a/test/asan/TestCases/contiguous_container.cc b/test/asan/TestCases/contiguous_container.cc index bda0f53de..3f754562a 100644 --- a/test/asan/TestCases/contiguous_container.cc +++ b/test/asan/TestCases/contiguous_container.cc @@ -26,10 +26,18 @@ void TestContainer(size_t capacity) { for (size_t idx = size; idx < capacity; idx++) assert(__asan_address_is_poisoned(beg + idx)); assert(__sanitizer_verify_contiguous_container(beg, mid, end)); - if (mid != beg) + assert(NULL == + __sanitizer_contiguous_container_find_bad_address(beg, mid, end)); + if (mid != beg) { assert(!__sanitizer_verify_contiguous_container(beg, mid - 1, end)); - if (mid != end) + assert(mid - 1 == __sanitizer_contiguous_container_find_bad_address( + beg, mid - 1, end)); + } + if (mid != end) { assert(!__sanitizer_verify_contiguous_container(beg, mid + 1, end)); + assert(mid == __sanitizer_contiguous_container_find_bad_address( + beg, mid + 1, end)); + } } // Don't forget to unpoison the whole thing before destroing/reallocating. |