1 //===-- asan_mem_test.cc --------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 //===----------------------------------------------------------------------===//
11 #include "asan_test_utils.h"
14 void 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);
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);
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
);
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
)));
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));
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
)));
55 // whole interval is to the left
56 EXPECT_DEATH(MEMSET(array
- 2, 0, sizeof(T
)),
57 LeftOOBWriteMessage(2 * sizeof(T
)));
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));
66 TEST(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?
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.
76 static bool AllocateTwoAdjacentArrays(char **x1
, char **x2
, size_t size
) {
79 for (size_t i
= 0; i
< 1000U && !res
; i
++) {
80 v
.push_back(reinterpret_cast<uintptr_t>(new char[size
]));
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]);
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;
103 TEST(AddressSanitizer
, LargeOOBInMemset
) {
104 for (size_t size
= 200; size
< 100000; size
+= size
/ 2) {
106 if (!Ident(AllocateTwoAdjacentArrays
)(&x1
, &x2
, size
))
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");
116 assert(0 && "Did not find two adjacent malloc-ed pointers");
119 // Same test for memcpy and memmove functions
120 template <typename T
, class M
>
121 void 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
));
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);
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
);
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));
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));
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));
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));
164 // Generally we don't need to test cases where both accessing src and writing
165 // to dest address to poisoned memory.
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
)));
182 class MemCpyWrapper
{
184 static void* transfer(void *to
, const void *from
, size_t size
) {
185 return Ident(memcpy
)(to
, from
, size
);
189 TEST(AddressSanitizer
, MemCpyOOBTest
) {
190 MemTransferOOBTestTemplate
<char, MemCpyWrapper
>(100);
191 MemTransferOOBTestTemplate
<int, MemCpyWrapper
>(1024);
194 class MemMoveWrapper
{
196 static void* transfer(void *to
, const void *from
, size_t size
) {
197 return Ident(memmove
)(to
, from
, size
);
201 TEST(AddressSanitizer
, MemMoveOOBTest
) {
202 MemTransferOOBTestTemplate
<char, MemMoveWrapper
>(100);
203 MemTransferOOBTestTemplate
<int, MemMoveWrapper
>(1024);
207 TEST(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.
226 EXPECT_DEATH(Ident(memcmp
)(s1
, s2
, size
+ 1), RightOOBReadMessage(0));
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:
232 EXPECT_DEATH(Ident(memcmp
)(s1
, s2
, size
+ 1), RightOOBReadMessage(0));