diff options
author | Kostya Serebryany <kcc@google.com> | 2013-11-18 14:02:05 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2013-11-18 14:02:05 +0000 |
commit | 2991200255098ac0739952351b2eb2b487819eec (patch) | |
tree | 23b44b10ec3658b7058034192afb39e67abe4c65 | |
parent | 0fbf056b4dbe12f63cefe7488c76d08cb8b26788 (diff) | |
download | compiler-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.h | 24 | ||||
-rw-r--r-- | lib/asan/asan_poisoning.cc | 42 | ||||
-rw-r--r-- | lib/asan/lit_tests/TestCases/contiguous_container.cc | 47 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_internal_defs.h | 3 |
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" |