]> git.proxmox.com Git - rustc.git/blob - src/compiler-rt/lib/asan/tests/asan_mem_test.cc
New upstream version 1.19.0+dfsg3
[rustc.git] / src / compiler-rt / lib / asan / tests / asan_mem_test.cc
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
15 template<typename T>
16 void 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
68 TEST(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.
78 static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) {
79 vector<uintptr_t> v;
80 bool res = false;
81 for (size_t i = 0; i < 1000U && !res; i++) {
82 v.push_back(reinterpret_cast<uintptr_t>(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 = reinterpret_cast<char*>(v[j]);
89 *x1 = reinterpret_cast<char*>(v[j-1]);
90 res = true;
91 break;
92 }
93 }
94 }
95
96 for (size_t i = 0; i < v.size(); i++) {
97 char *p = reinterpret_cast<char *>(v[i]);
98 if (res && p == *x1) continue;
99 if (res && p == *x2) continue;
100 delete [] p;
101 }
102 return res;
103 }
104
105 TEST(AddressSanitizer, LargeOOBInMemset) {
106 for (size_t size = 200; size < 100000; size += size / 2) {
107 char *x1, *x2;
108 if (!Ident(AllocateTwoAdjacentArrays)(&x1, &x2, size))
109 continue;
110 // fprintf(stderr, " large oob memset: %p %p %zd\n", x1, x2, size);
111 // Do a memset on x1 with huge out-of-bound access that will end up in x2.
112 EXPECT_DEATH(Ident(memset)(x1, 0, size * 2),
113 "is located 0 bytes to the right");
114 delete [] x1;
115 delete [] x2;
116 return;
117 }
118 assert(0 && "Did not find two adjacent malloc-ed pointers");
119 }
120
121 // Same test for memcpy and memmove functions
122 template <typename T, class M>
123 void MemTransferOOBTestTemplate(size_t length) {
124 if (length == 0) return;
125 size_t size = Ident(sizeof(T) * length);
126 T *src = Ident((T*)malloc(size));
127 T *dest = Ident((T*)malloc(size));
128 int zero = Ident(0);
129
130 // valid transfer of bytes between arrays
131 M::transfer(dest, src, size);
132 M::transfer(dest + 1, src, size - sizeof(T));
133 M::transfer(dest, src + length - 1, sizeof(T));
134 M::transfer(dest, src, 1);
135
136 // transfer zero bytes
137 M::transfer(dest - 1, src, 0);
138 M::transfer(dest + length, src, zero);
139 M::transfer(dest, src - 1, zero);
140 M::transfer(dest, src, zero);
141
142 // try to change mem to the right of dest
143 EXPECT_DEATH(M::transfer(dest + 1, src, size),
144 RightOOBWriteMessage(0));
145 EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5),
146 RightOOBWriteMessage(0));
147
148 // try to change mem to the left of dest
149 EXPECT_DEATH(M::transfer(dest - 2, src, size),
150 LeftOOBWriteMessage(2 * sizeof(T)));
151 EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4),
152 LeftOOBWriteMessage(3));
153
154 // try to access mem to the right of src
155 EXPECT_DEATH(M::transfer(dest, src + 2, size),
156 RightOOBReadMessage(0));
157 EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6),
158 RightOOBReadMessage(0));
159
160 // try to access mem to the left of src
161 EXPECT_DEATH(M::transfer(dest, src - 1, size),
162 LeftOOBReadMessage(sizeof(T)));
163 EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7),
164 LeftOOBReadMessage(6));
165
166 // Generally we don't need to test cases where both accessing src and writing
167 // to dest address to poisoned memory.
168
169 T *big_src = Ident((T*)malloc(size * 2));
170 T *big_dest = Ident((T*)malloc(size * 2));
171 // try to change mem to both sides of dest
172 EXPECT_DEATH(M::transfer(dest - 1, big_src, size * 2),
173 LeftOOBWriteMessage(sizeof(T)));
174 // try to access mem to both sides of src
175 EXPECT_DEATH(M::transfer(big_dest, src - 2, size * 2),
176 LeftOOBReadMessage(2 * sizeof(T)));
177
178 free(src);
179 free(dest);
180 free(big_src);
181 free(big_dest);
182 }
183
184 class MemCpyWrapper {
185 public:
186 static void* transfer(void *to, const void *from, size_t size) {
187 return Ident(memcpy)(to, from, size);
188 }
189 };
190
191 TEST(AddressSanitizer, MemCpyOOBTest) {
192 MemTransferOOBTestTemplate<char, MemCpyWrapper>(100);
193 MemTransferOOBTestTemplate<int, MemCpyWrapper>(1024);
194 }
195
196 class MemMoveWrapper {
197 public:
198 static void* transfer(void *to, const void *from, size_t size) {
199 return Ident(memmove)(to, from, size);
200 }
201 };
202
203 TEST(AddressSanitizer, MemMoveOOBTest) {
204 MemTransferOOBTestTemplate<char, MemMoveWrapper>(100);
205 MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024);
206 }
207
208
209 TEST(AddressSanitizer, MemCmpOOBTest) {
210 size_t size = Ident(100);
211 char *s1 = MallocAndMemsetString(size);
212 char *s2 = MallocAndMemsetString(size);
213 // Normal memcmp calls.
214 Ident(memcmp(s1, s2, size));
215 Ident(memcmp(s1 + size - 1, s2 + size - 1, 1));
216 Ident(memcmp(s1 - 1, s2 - 1, 0));
217 // One of arguments points to not allocated memory.
218 EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1));
219 EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1));
220 EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0));
221 EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0));
222 // Hit unallocated memory and die.
223 EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0));
224 EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0));
225 // Zero bytes are not terminators and don't prevent from OOB.
226 s1[size - 1] = '\0';
227 s2[size - 1] = '\0';
228 EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
229
230 // Even if the buffers differ in the first byte, we still assume that
231 // memcmp may access the whole buffer and thus reporting the overflow here:
232 s1[0] = 1;
233 s2[0] = 123;
234 EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0));
235
236 free(s1);
237 free(s2);
238 }
239
240
241