summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2013-11-18 14:02:05 +0000
committerKostya Serebryany <kcc@google.com>2013-11-18 14:02:05 +0000
commit2991200255098ac0739952351b2eb2b487819eec (patch)
tree23b44b10ec3658b7058034192afb39e67abe4c65
parent0fbf056b4dbe12f63cefe7488c76d08cb8b26788 (diff)
downloadcompiler-rt-2991200255098ac0739952351b2eb2b487819eec.tar.gz
[asan] introduce __sanitizer_annotate_contiguous_container
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@195011 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/sanitizer/common_interface_defs.h24
-rw-r--r--lib/asan/asan_poisoning.cc42
-rw-r--r--lib/asan/lit_tests/TestCases/contiguous_container.cc47
-rw-r--r--lib/sanitizer_common/sanitizer_internal_defs.h3
4 files changed, 116 insertions, 0 deletions
diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h
index 70a5c0cd3..4cc2aeae2 100644
--- a/include/sanitizer/common_interface_defs.h
+++ b/include/sanitizer/common_interface_defs.h
@@ -50,6 +50,30 @@ extern "C" {
// Record and dump coverage info.
void __sanitizer_cov_dump();
+ // Annotate 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;
+ // end <= mid <= end. For example, in "std::vector<> v"
+ // beg = &v[0];
+ // end = beg + v.capacity() * sizeof(v[0]);
+ // mid = beg + v.size() * sizeof(v[0]);
+ //
+ // 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/pop_back.
+ // Supply the old and the new values of mid (old_mid/new_mid).
+ // In the initial state mid == end and so should be the final
+ // state when the container is destroyed or when it reallocates the storage.
+ //
+ // Use with caution and don't use for anything other than vector-like classes.
+ //
+ // For AddressSanitizer, 'beg' should be 8-aligned.
+ void __sanitizer_annotate_contiguous_container(void *beg, void *end,
+ void *old_mid, void *new_mid);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc
index 0033b61c1..40d3d2508 100644
--- a/lib/asan/asan_poisoning.cc
+++ b/lib/asan/asan_poisoning.cc
@@ -255,3 +255,45 @@ void __asan_unpoison_stack_memory(uptr addr, uptr size) {
Report("unpoisoning: %p %zx\n", (void*)addr, size);
PoisonAlignedStackMemory(addr, size, false);
}
+
+void __sanitizer_annotate_contiguous_container(void *beg_p, void *end_p,
+ void *old_mid_p,
+ void *new_mid_p) {
+ uptr beg = reinterpret_cast<uptr>(beg_p);
+ uptr end= reinterpret_cast<uptr>(end_p);
+ uptr old_mid = reinterpret_cast<uptr>(old_mid_p);
+ uptr new_mid = reinterpret_cast<uptr>(new_mid_p);
+ uptr granularity = SHADOW_GRANULARITY;
+ CHECK(beg <= end && beg <= old_mid && beg <= new_mid && old_mid <= end &&
+ new_mid <= end && IsAligned(beg, granularity));
+ CHECK_LE(end - beg,
+ FIRST_32_SECOND_64(1UL << 30, 1UL << 34)); // Sanity check.
+
+ uptr a = RoundDownTo(Min(old_mid, new_mid), granularity);
+ uptr c = RoundUpTo(Max(old_mid, new_mid), granularity);
+ uptr b = new_mid;
+ uptr b1 = RoundDownTo(b, granularity);
+ uptr b2 = RoundUpTo(b, granularity);
+ uptr d = old_mid;
+ uptr d1 = RoundDownTo(d, granularity);
+ uptr d2 = RoundUpTo(d, granularity);
+ // Currently we should be in this state:
+ // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good.
+ // Make a quick sanity check that we are indeed in this state.
+ if (d1 != d2)
+ CHECK_EQ(*(u8*)MemToShadow(d1), d - d1);
+ if (a + granularity <= d1)
+ CHECK_EQ(*(u8*)MemToShadow(a), 0);
+ if (d2 + granularity <= c && c <= end)
+ CHECK_EQ(*(u8 *)MemToShadow(c - granularity), kAsanUserPoisonedMemoryMagic);
+
+ // New state:
+ // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good.
+ // FIXME: we may want to have a separate poison magic value.
+ PoisonShadow(a, b1 - a, 0);
+ PoisonShadow(b2, c - b2, kAsanUserPoisonedMemoryMagic);
+ if (b1 != b2) {
+ CHECK_EQ(b2 - b1, granularity);
+ *(u8*)MemToShadow(b1) = b - b1;
+ }
+}
diff --git a/lib/asan/lit_tests/TestCases/contiguous_container.cc b/lib/asan/lit_tests/TestCases/contiguous_container.cc
new file mode 100644
index 000000000..aa97592c7
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/contiguous_container.cc
@@ -0,0 +1,47 @@
+// RUN: %clangxx_asan -O %s -o %t && %t
+//
+// Test __sanitizer_annotate_contiguous_container.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+extern "C" {
+void __sanitizer_annotate_contiguous_container(void *beg, void *end,
+ void *old_mid, void *new_mid);
+bool __asan_address_is_poisoned(void *addr);
+} // extern "C"
+
+void TestContainer(size_t capacity) {
+ char *beg = new char[capacity];
+ char *end = beg + capacity;
+ char *mid = beg + capacity;
+ char *old_mid = 0;
+ unsigned seed = 0;
+
+ for (int i = 0; i < 10000; i++) {
+ size_t size = rand_r(&seed) % (capacity + 1);
+ assert(size <= capacity);
+ old_mid = mid;
+ mid = beg + size;
+ __sanitizer_annotate_contiguous_container(beg, end, old_mid, mid);
+
+ for (size_t idx = 0; idx < size; idx++)
+ assert(!__asan_address_is_poisoned(beg + idx));
+ for (size_t idx = size; idx < capacity; idx++)
+ assert(__asan_address_is_poisoned(beg + idx));
+ }
+
+ // Don't forget to unpoison the whole thing before destroing/reallocating.
+ __sanitizer_annotate_contiguous_container(beg, end, mid, end);
+ for (size_t idx = 0; idx < capacity; idx++)
+ assert(!__asan_address_is_poisoned(beg + idx));
+ delete[] beg;
+}
+
+int main(int argc, char **argv) {
+ int n = argc == 1 ? 128 : atoi(argv[1]);
+ for (int i = 0; i <= n; i++)
+ TestContainer(i);
+}
diff --git a/lib/sanitizer_common/sanitizer_internal_defs.h b/lib/sanitizer_common/sanitizer_internal_defs.h
index bf0c56851..daa724be0 100644
--- a/lib/sanitizer_common/sanitizer_internal_defs.h
+++ b/lib/sanitizer_common/sanitizer_internal_defs.h
@@ -113,6 +113,9 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(void *pc);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __sanitizer_annotate_contiguous_container(void *beg, void *end,
+ void *old_mid, void *new_mid);
} // extern "C"