1// RUN: %clangxx_asan -O %s -o %t && %run %t
2//
3// Test __sanitizer_annotate_contiguous_container.
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8#include <assert.h>
9#include <sanitizer/asan_interface.h>
10
11void TestContainer(size_t capacity) {
12  char *beg = new char[capacity];
13  char *end = beg + capacity;
14  char *mid = beg + capacity;
15  char *old_mid = 0;
16
17  for (int i = 0; i < 10000; i++) {
18    size_t size = rand() % (capacity + 1);
19    assert(size <= capacity);
20    old_mid = mid;
21    mid = beg + size;
22    __sanitizer_annotate_contiguous_container(beg, end, old_mid, mid);
23
24    for (size_t idx = 0; idx < size; idx++)
25        assert(!__asan_address_is_poisoned(beg + idx));
26    for (size_t idx = size; idx < capacity; idx++)
27        assert(__asan_address_is_poisoned(beg + idx));
28    assert(__sanitizer_verify_contiguous_container(beg, mid, end));
29    if (mid != beg)
30      assert(!__sanitizer_verify_contiguous_container(beg, mid - 1, end));
31    if (mid != end)
32      assert(!__sanitizer_verify_contiguous_container(beg, mid + 1, end));
33  }
34
35  // Don't forget to unpoison the whole thing before destroing/reallocating.
36  __sanitizer_annotate_contiguous_container(beg, end, mid, end);
37  for (size_t idx = 0; idx < capacity; idx++)
38    assert(!__asan_address_is_poisoned(beg + idx));
39  delete[] beg;
40}
41
42__attribute__((noinline))
43void Throw() { throw 1; }
44
45__attribute__((noinline))
46void ThrowAndCatch() {
47  try {
48    Throw();
49  } catch(...) {
50  }
51}
52
53void TestThrow() {
54  char x[32];
55  __sanitizer_annotate_contiguous_container(x, x + 32, x + 32, x + 14);
56  assert(!__asan_address_is_poisoned(x + 13));
57  assert(__asan_address_is_poisoned(x + 14));
58  ThrowAndCatch();
59  assert(!__asan_address_is_poisoned(x + 13));
60  // FIXME: invert the assertion below once we fix
61  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
62  // This assertion works only w/o UAR.
63  if (!__asan_get_current_fake_stack())
64    assert(!__asan_address_is_poisoned(x + 14));
65  __sanitizer_annotate_contiguous_container(x, x + 32, x + 14, x + 32);
66  assert(!__asan_address_is_poisoned(x + 13));
67  assert(!__asan_address_is_poisoned(x + 14));
68}
69
70int main(int argc, char **argv) {
71  int n = argc == 1 ? 128 : atoi(argv[1]);
72  for (int i = 0; i <= n; i++)
73    TestContainer(i);
74  TestThrow();
75}
76