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