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