asan_mem_test.cc revision 6cbfae439b81221d2250ffe0331958f130259755
1//===-- asan_mem_test.cc --------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12//===----------------------------------------------------------------------===//
13#include "asan_test_utils.h"
14
15template<typename T>
16void MemSetOOBTestTemplate(size_t length) {
17  if (length == 0) return;
18  size_t size = Ident(sizeof(T) * length);
19  T *array = Ident((T*)malloc(size));
20  int element = Ident(42);
21  int zero = Ident(0);
22  void *(*MEMSET)(void *s, int c, size_t n) = Ident(memset);
23  // memset interval inside array
24  MEMSET(array, element, size);
25  MEMSET(array, element, size - 1);
26  MEMSET(array + length - 1, element, sizeof(T));
27  MEMSET(array, element, 1);
28
29  // memset 0 bytes
30  MEMSET(array - 10, element, zero);
31  MEMSET(array - 1, element, zero);
32  MEMSET(array, element, zero);
33  MEMSET(array + length, 0, zero);
34  MEMSET(array + length + 1, 0, zero);
35
36  // try to memset bytes to the right of array
37  EXPECT_DEATH(MEMSET(array, 0, size + 1),
38               RightOOBWriteMessage(0));
39  EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6),
40               RightOOBWriteMessage(0));
41  EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)),
42               RightOOBWriteMessage(0));
43  // whole interval is to the right
44  EXPECT_DEATH(MEMSET(array + length + 1, 0, 10),
45               RightOOBWriteMessage(sizeof(T)));
46
47  // try to memset bytes to the left of array
48  EXPECT_DEATH(MEMSET((char*)array - 1, element, size),
49               LeftOOBWriteMessage(1));
50  EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6),
51               LeftOOBWriteMessage(5));
52  if (length >= 100) {
53    // Large OOB, we find it only if the redzone is large enough.
54    EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)),
55                 LeftOOBWriteMessage(5 * sizeof(T)));
56  }
57  // whole interval is to the left
58  EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)),
59               LeftOOBWriteMessage(2 * sizeof(T)));
60
61  // try to memset bytes both to the left & to the right
62  EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4),
63               LeftOOBWriteMessage(2));
64
65  free(array);
66}
67
68TEST(AddressSanitizer, MemSetOOBTest) {
69  MemSetOOBTestTemplate<char>(100);
70  MemSetOOBTestTemplate<int>(5);
71  MemSetOOBTestTemplate<double>(256);
72  // We can test arrays of structres/classes here, but what for?
73}
74
75// Try to allocate two arrays of 'size' bytes that are near each other.
76// Strictly speaking we are not guaranteed to find such two pointers,
77// but given the structure of asan's allocator we will.
78static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) {
79  vector<char *> v;
80  bool res = false;
81  for (size_t i = 0; i < 1000U && !res; i++) {
82    v.push_back(new char[size]);
83    if (i == 0) continue;
84    sort(v.begin(), v.end());
85    for (size_t j = 1; j < v.size(); j++) {
86      assert(v[j] > v[j-1]);
87      if ((size_t)(v[j] - v[j-1]) < size * 2) {
88        *x2 = v[j];
89        *x1 = v[j-1];
90        res = true;
91        break;
92      }
93    }
94  }
95
96  for (size_t i = 0; i < v.size(); i++) {
97    if (res && v[i] == *x1) continue;
98    if (res && v[i] == *x2) continue;
99    delete [] v[i];
100  }
101  return res;
102}
103
104TEST(AddressSanitizer, LargeOOBInMemset) {
105  for (size_t size = 200; size < 100000; size += size / 2) {
106    char *x1, *x2;
107    if (!Ident(AllocateTwoAdjacentArrays)(&x1, &x2, size))
108      continue;
109    // fprintf(stderr, "  large oob memset: %p %p %zd\n", x1, x2, size);
110    // Do a memset on x1 with huge out-of-bound access that will end up in x2.
111    EXPECT_DEATH(Ident(memset)(x1, 0, size * 2),
112                 "is located 0 bytes to the right");
113    delete [] x1;
114    delete [] x2;
115    return;
116  }
117  assert(0 && "Did not find two adjacent malloc-ed pointers");
118}
119
120// Same test for memcpy and memmove functions
121template <typename T, class M>
122void MemTransferOOBTestTemplate(size_t length) {
123  if (length == 0) return;
124  size_t size = Ident(sizeof(T) * length);
125  T *src = Ident((T*)malloc(size));
126  T *dest = Ident((T*)malloc(size));
127  int zero = Ident(0);
128
129  // valid transfer of bytes between arrays
130  M::transfer(dest, src, size);
131  M::transfer(dest + 1, src, size - sizeof(T));
132  M::transfer(dest, src + length - 1, sizeof(T));
133  M::transfer(dest, src, 1);
134
135  // transfer zero bytes
136  M::transfer(dest - 1, src, 0);
137  M::transfer(dest + length, src, zero);
138  M::transfer(dest, src - 1, zero);
139  M::transfer(dest, src, zero);
140
141  // try to change mem to the right of dest
142  EXPECT_DEATH(M::transfer(dest + 1, src, size),
143               RightOOBWriteMessage(0));
144  EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5),
145               RightOOBWriteMessage(0));
146
147  // try to change mem to the left of dest
148  EXPECT_DEATH(M::transfer(dest - 2, src, size),
149               LeftOOBWriteMessage(2 * sizeof(T)));
150  EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4),
151               LeftOOBWriteMessage(3));
152
153  // try to access mem to the right of src
154  EXPECT_DEATH(M::transfer(dest, src + 2, size),
155               RightOOBReadMessage(0));
156  EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6),
157               RightOOBReadMessage(0));
158
159  // try to access mem to the left of src
160  EXPECT_DEATH(M::transfer(dest, src - 1, size),
161               LeftOOBReadMessage(sizeof(T)));
162  EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7),
163               LeftOOBReadMessage(6));
164
165  // Generally we don't need to test cases where both accessing src and writing
166  // to dest address to poisoned memory.
167
168  T *big_src = Ident((T*)malloc(size * 2));
169  T *big_dest = Ident((T*)malloc(size * 2));
170  // try to change mem to both sides of dest
171  EXPECT_DEATH(M::transfer(dest - 1, big_src, size * 2),
172               LeftOOBWriteMessage(sizeof(T)));
173  // try to access mem to both sides of src
174  EXPECT_DEATH(M::transfer(big_dest, src - 2, size * 2),
175               LeftOOBReadMessage(2 * sizeof(T)));
176
177  free(src);
178  free(dest);
179  free(big_src);
180  free(big_dest);
181}
182
183class MemCpyWrapper {
184 public:
185  static void* transfer(void *to, const void *from, size_t size) {
186    return Ident(memcpy)(to, from, size);
187  }
188};
189
190TEST(AddressSanitizer, MemCpyOOBTest) {
191  MemTransferOOBTestTemplate<char, MemCpyWrapper>(100);
192  MemTransferOOBTestTemplate<int, MemCpyWrapper>(1024);
193}
194
195class MemMoveWrapper {
196 public:
197  static void* transfer(void *to, const void *from, size_t size) {
198    return Ident(memmove)(to, from, size);
199  }
200};
201
202TEST(AddressSanitizer, MemMoveOOBTest) {
203  MemTransferOOBTestTemplate<char, MemMoveWrapper>(100);
204  MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024);
205}
206
207
208TEST(AddressSanitizer, MemCmpOOBTest) {
209  size_t size = Ident(100);
210  char *s1 = MallocAndMemsetString(size);
211  char *s2 = MallocAndMemsetString(size);
212  // Normal memcmp calls.
213  Ident(memcmp(s1, s2, size));
214  Ident(memcmp(s1 + size - 1, s2 + size - 1, 1));
215  Ident(memcmp(s1 - 1, s2 - 1, 0));
216  // One of arguments points to not allocated memory.
217  EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
218  EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
219  EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
220  EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
221  // Hit unallocated memory and die.
222  EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
223  EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
224  // Zero bytes are not terminators and don't prevent from OOB.
225  s1[size - 1] = '\0';
226  s2[size - 1] = '\0';
227  EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
228  free(s1);
229  free(s2);
230}
231
232
233
234