summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sanitizer/common_interface_defs.h6
-rw-r--r--lib/asan/asan_poisoning.cc25
-rw-r--r--lib/sanitizer_common/sanitizer_interface_internal.h5
-rw-r--r--test/asan/TestCases/contiguous_container.cc12
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.