]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- msan_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 MemorySanitizer. | |
11 | // | |
12 | // MemorySanitizer unit tests. | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
15 | #ifndef MSAN_EXTERNAL_TEST_CONFIG | |
16 | #include "msan_test_config.h" | |
17 | #endif // MSAN_EXTERNAL_TEST_CONFIG | |
18 | ||
19 | #include "sanitizer_common/tests/sanitizer_test_utils.h" | |
20 | ||
92a42be0 | 21 | #include "sanitizer/allocator_interface.h" |
1a4d82fc | 22 | #include "sanitizer/msan_interface.h" |
92a42be0 SL |
23 | |
24 | #if defined(__FreeBSD__) | |
25 | # define _KERNEL // To declare 'shminfo' structure. | |
26 | # include <sys/shm.h> | |
27 | # undef _KERNEL | |
28 | extern "C" { | |
29 | // <sys/shm.h> doesn't declare these functions in _KERNEL mode. | |
30 | void *shmat(int, const void *, int); | |
31 | int shmget(key_t, size_t, int); | |
32 | int shmctl(int, int, struct shmid_ds *); | |
33 | int shmdt(const void *); | |
34 | } | |
35 | #endif | |
1a4d82fc JJ |
36 | |
37 | #include <inttypes.h> | |
38 | #include <stdlib.h> | |
39 | #include <stdarg.h> | |
40 | #include <stdio.h> | |
41 | #include <wchar.h> | |
42 | #include <math.h> | |
1a4d82fc JJ |
43 | |
44 | #include <arpa/inet.h> | |
45 | #include <dlfcn.h> | |
46 | #include <grp.h> | |
47 | #include <unistd.h> | |
48 | #include <link.h> | |
49 | #include <limits.h> | |
50 | #include <sys/time.h> | |
51 | #include <poll.h> | |
52 | #include <sys/types.h> | |
53 | #include <sys/stat.h> | |
54 | #include <fcntl.h> | |
55 | #include <sys/resource.h> | |
56 | #include <sys/ioctl.h> | |
57 | #include <sys/statvfs.h> | |
1a4d82fc JJ |
58 | #include <sys/utsname.h> |
59 | #include <sys/mman.h> | |
1a4d82fc JJ |
60 | #include <dirent.h> |
61 | #include <pwd.h> | |
62 | #include <sys/socket.h> | |
63 | #include <netdb.h> | |
64 | #include <wordexp.h> | |
1a4d82fc JJ |
65 | #include <sys/ipc.h> |
66 | #include <sys/shm.h> | |
67 | ||
92a42be0 SL |
68 | #if !defined(__FreeBSD__) |
69 | # include <malloc.h> | |
70 | # include <sys/sysinfo.h> | |
71 | # include <sys/vfs.h> | |
72 | # include <mntent.h> | |
73 | # include <netinet/ether.h> | |
74 | #else | |
75 | # include <signal.h> | |
76 | # include <netinet/in.h> | |
77 | # include <pthread_np.h> | |
78 | # include <sys/uio.h> | |
79 | # include <sys/mount.h> | |
80 | # include <sys/sysctl.h> | |
81 | # include <net/ethernet.h> | |
82 | # define f_namelen f_namemax // FreeBSD names this statfs field so. | |
83 | # define cpu_set_t cpuset_t | |
84 | extern "C" { | |
85 | // FreeBSD's <ssp/string.h> defines mempcpy() to be a macro expanding into | |
86 | // a __builtin___mempcpy_chk() call, but since Msan RTL defines it as an | |
87 | // ordinary function, we can declare it here to complete the tests. | |
88 | void *mempcpy(void *dest, const void *src, size_t n); | |
89 | } | |
90 | #endif | |
91 | ||
1a4d82fc JJ |
92 | #if defined(__i386__) || defined(__x86_64__) |
93 | # include <emmintrin.h> | |
94 | # define MSAN_HAS_M128 1 | |
95 | #else | |
96 | # define MSAN_HAS_M128 0 | |
97 | #endif | |
98 | ||
99 | #ifdef __AVX2__ | |
100 | # include <immintrin.h> | |
101 | #endif | |
102 | ||
92a42be0 SL |
103 | // On FreeBSD procfs is not enabled by default. |
104 | #if defined(__FreeBSD__) | |
105 | # define FILE_TO_READ "/bin/cat" | |
106 | # define DIR_TO_READ "/bin" | |
107 | # define SUBFILE_TO_READ "cat" | |
108 | # define SYMLINK_TO_READ "/usr/bin/tar" | |
109 | # define SUPERUSER_GROUP "wheel" | |
110 | #else | |
111 | # define FILE_TO_READ "/proc/self/stat" | |
112 | # define DIR_TO_READ "/proc/self" | |
113 | # define SUBFILE_TO_READ "stat" | |
114 | # define SYMLINK_TO_READ "/proc/self/exe" | |
115 | # define SUPERUSER_GROUP "root" | |
116 | #endif | |
117 | ||
5bcae85e SL |
118 | static uintptr_t GetPageSize() { |
119 | return sysconf(_SC_PAGESIZE); | |
120 | } | |
121 | ||
92a42be0 | 122 | const size_t kMaxPathLength = 4096; |
1a4d82fc JJ |
123 | |
124 | typedef unsigned char U1; | |
125 | typedef unsigned short U2; // NOLINT | |
126 | typedef unsigned int U4; | |
127 | typedef unsigned long long U8; // NOLINT | |
128 | typedef signed char S1; | |
129 | typedef signed short S2; // NOLINT | |
130 | typedef signed int S4; | |
131 | typedef signed long long S8; // NOLINT | |
132 | #define NOINLINE __attribute__((noinline)) | |
133 | #define INLINE __attribute__((always_inline)) | |
134 | ||
135 | static bool TrackingOrigins() { | |
136 | S8 x; | |
137 | __msan_set_origin(&x, sizeof(x), 0x1234); | |
138 | U4 origin = __msan_get_origin(&x); | |
139 | __msan_set_origin(&x, sizeof(x), 0); | |
92a42be0 | 140 | return __msan_origin_is_descendant_or_same(origin, 0x1234); |
1a4d82fc JJ |
141 | } |
142 | ||
92a42be0 SL |
143 | #define EXPECT_ORIGIN(expected, origin) \ |
144 | EXPECT_TRUE(__msan_origin_is_descendant_or_same((origin), (expected))) | |
145 | ||
1a4d82fc JJ |
146 | #define EXPECT_UMR(action) \ |
147 | do { \ | |
148 | __msan_set_expect_umr(1); \ | |
149 | action; \ | |
150 | __msan_set_expect_umr(0); \ | |
151 | } while (0) | |
152 | ||
92a42be0 SL |
153 | #define EXPECT_UMR_O(action, origin) \ |
154 | do { \ | |
155 | __msan_set_expect_umr(1); \ | |
156 | action; \ | |
157 | __msan_set_expect_umr(0); \ | |
158 | if (TrackingOrigins()) EXPECT_ORIGIN(origin, __msan_get_umr_origin()); \ | |
159 | } while (0) | |
1a4d82fc JJ |
160 | |
161 | #define EXPECT_POISONED(x) ExpectPoisoned(x) | |
162 | ||
163 | template<typename T> | |
164 | void ExpectPoisoned(const T& t) { | |
165 | EXPECT_NE(-1, __msan_test_shadow((void*)&t, sizeof(t))); | |
166 | } | |
167 | ||
168 | #define EXPECT_POISONED_O(x, origin) \ | |
169 | ExpectPoisonedWithOrigin(x, origin) | |
170 | ||
171 | template<typename T> | |
172 | void ExpectPoisonedWithOrigin(const T& t, unsigned origin) { | |
173 | EXPECT_NE(-1, __msan_test_shadow((void*)&t, sizeof(t))); | |
92a42be0 | 174 | if (TrackingOrigins()) EXPECT_ORIGIN(origin, __msan_get_origin((void *)&t)); |
1a4d82fc JJ |
175 | } |
176 | ||
92a42be0 | 177 | #define EXPECT_NOT_POISONED(x) EXPECT_EQ(true, TestForNotPoisoned((x))) |
1a4d82fc JJ |
178 | |
179 | template<typename T> | |
92a42be0 SL |
180 | bool TestForNotPoisoned(const T& t) { |
181 | return __msan_test_shadow((void*)&t, sizeof(t)) == -1; | |
1a4d82fc JJ |
182 | } |
183 | ||
184 | static U8 poisoned_array[100]; | |
185 | template<class T> | |
186 | T *GetPoisoned(int i = 0, T val = 0) { | |
187 | T *res = (T*)&poisoned_array[i]; | |
188 | *res = val; | |
189 | __msan_poison(&poisoned_array[i], sizeof(T)); | |
190 | return res; | |
191 | } | |
192 | ||
193 | template<class T> | |
194 | T *GetPoisonedO(int i, U4 origin, T val = 0) { | |
195 | T *res = (T*)&poisoned_array[i]; | |
196 | *res = val; | |
197 | __msan_poison(&poisoned_array[i], sizeof(T)); | |
198 | __msan_set_origin(&poisoned_array[i], sizeof(T), origin); | |
199 | return res; | |
200 | } | |
201 | ||
92a42be0 SL |
202 | template<typename T> |
203 | T Poisoned(T v = 0, T s = (T)(-1)) { | |
204 | __msan_partial_poison(&v, &s, sizeof(T)); | |
205 | return v; | |
206 | } | |
207 | ||
1a4d82fc JJ |
208 | template<class T> NOINLINE T ReturnPoisoned() { return *GetPoisoned<T>(); } |
209 | ||
210 | static volatile int g_one = 1; | |
211 | static volatile int g_zero = 0; | |
212 | static volatile int g_0 = 0; | |
213 | static volatile int g_1 = 1; | |
214 | ||
215 | S4 a_s4[100]; | |
216 | S8 a_s8[100]; | |
217 | ||
218 | // Check that malloc poisons memory. | |
219 | // A lot of tests below depend on this. | |
220 | TEST(MemorySanitizerSanity, PoisonInMalloc) { | |
221 | int *x = (int*)malloc(sizeof(int)); | |
222 | EXPECT_POISONED(*x); | |
223 | free(x); | |
224 | } | |
225 | ||
226 | TEST(MemorySanitizer, NegativeTest1) { | |
227 | S4 *x = GetPoisoned<S4>(); | |
228 | if (g_one) | |
229 | *x = 0; | |
230 | EXPECT_NOT_POISONED(*x); | |
231 | } | |
232 | ||
233 | TEST(MemorySanitizer, PositiveTest1) { | |
234 | // Load to store. | |
235 | EXPECT_POISONED(*GetPoisoned<S1>()); | |
236 | EXPECT_POISONED(*GetPoisoned<S2>()); | |
237 | EXPECT_POISONED(*GetPoisoned<S4>()); | |
238 | EXPECT_POISONED(*GetPoisoned<S8>()); | |
239 | ||
240 | // S->S conversions. | |
241 | EXPECT_POISONED(*GetPoisoned<S1>()); | |
242 | EXPECT_POISONED(*GetPoisoned<S1>()); | |
243 | EXPECT_POISONED(*GetPoisoned<S1>()); | |
244 | ||
245 | EXPECT_POISONED(*GetPoisoned<S2>()); | |
246 | EXPECT_POISONED(*GetPoisoned<S2>()); | |
247 | EXPECT_POISONED(*GetPoisoned<S2>()); | |
248 | ||
249 | EXPECT_POISONED(*GetPoisoned<S4>()); | |
250 | EXPECT_POISONED(*GetPoisoned<S4>()); | |
251 | EXPECT_POISONED(*GetPoisoned<S4>()); | |
252 | ||
253 | EXPECT_POISONED(*GetPoisoned<S8>()); | |
254 | EXPECT_POISONED(*GetPoisoned<S8>()); | |
255 | EXPECT_POISONED(*GetPoisoned<S8>()); | |
256 | ||
257 | // ZExt | |
258 | EXPECT_POISONED(*GetPoisoned<U1>()); | |
259 | EXPECT_POISONED(*GetPoisoned<U1>()); | |
260 | EXPECT_POISONED(*GetPoisoned<U1>()); | |
261 | EXPECT_POISONED(*GetPoisoned<U2>()); | |
262 | EXPECT_POISONED(*GetPoisoned<U2>()); | |
263 | EXPECT_POISONED(*GetPoisoned<U4>()); | |
264 | ||
265 | // Unary ops. | |
266 | EXPECT_POISONED(- *GetPoisoned<S4>()); | |
267 | ||
268 | EXPECT_UMR(a_s4[g_zero] = 100 / *GetPoisoned<S4>(0, 1)); | |
269 | ||
270 | ||
271 | a_s4[g_zero] = 1 - *GetPoisoned<S4>(); | |
272 | a_s4[g_zero] = 1 + *GetPoisoned<S4>(); | |
273 | } | |
274 | ||
275 | TEST(MemorySanitizer, Phi1) { | |
276 | S4 c; | |
277 | if (g_one) { | |
278 | c = *GetPoisoned<S4>(); | |
279 | } else { | |
280 | break_optimization(0); | |
281 | c = 0; | |
282 | } | |
283 | EXPECT_POISONED(c); | |
284 | } | |
285 | ||
286 | TEST(MemorySanitizer, Phi2) { | |
287 | S4 i = *GetPoisoned<S4>(); | |
288 | S4 n = g_one; | |
289 | EXPECT_UMR(for (; i < g_one; i++);); | |
290 | EXPECT_POISONED(i); | |
291 | } | |
292 | ||
293 | NOINLINE void Arg1ExpectUMR(S4 a1) { EXPECT_POISONED(a1); } | |
294 | NOINLINE void Arg2ExpectUMR(S4 a1, S4 a2) { EXPECT_POISONED(a2); } | |
295 | NOINLINE void Arg3ExpectUMR(S1 a1, S4 a2, S8 a3) { EXPECT_POISONED(a3); } | |
296 | ||
297 | TEST(MemorySanitizer, ArgTest) { | |
298 | Arg1ExpectUMR(*GetPoisoned<S4>()); | |
299 | Arg2ExpectUMR(0, *GetPoisoned<S4>()); | |
300 | Arg3ExpectUMR(0, 1, *GetPoisoned<S8>()); | |
301 | } | |
302 | ||
303 | ||
304 | TEST(MemorySanitizer, CallAndRet) { | |
1a4d82fc JJ |
305 | ReturnPoisoned<S1>(); |
306 | ReturnPoisoned<S2>(); | |
307 | ReturnPoisoned<S4>(); | |
308 | ReturnPoisoned<S8>(); | |
309 | ||
310 | EXPECT_POISONED(ReturnPoisoned<S1>()); | |
311 | EXPECT_POISONED(ReturnPoisoned<S2>()); | |
312 | EXPECT_POISONED(ReturnPoisoned<S4>()); | |
313 | EXPECT_POISONED(ReturnPoisoned<S8>()); | |
314 | } | |
315 | ||
316 | // malloc() in the following test may be optimized to produce a compile-time | |
317 | // undef value. Check that we trap on the volatile assignment anyway. | |
318 | TEST(MemorySanitizer, DISABLED_MallocNoIdent) { | |
319 | S4 *x = (int*)malloc(sizeof(S4)); | |
320 | EXPECT_POISONED(*x); | |
321 | free(x); | |
322 | } | |
323 | ||
324 | TEST(MemorySanitizer, Malloc) { | |
325 | S4 *x = (int*)Ident(malloc(sizeof(S4))); | |
326 | EXPECT_POISONED(*x); | |
327 | free(x); | |
328 | } | |
329 | ||
330 | TEST(MemorySanitizer, Realloc) { | |
331 | S4 *x = (int*)Ident(realloc(0, sizeof(S4))); | |
332 | EXPECT_POISONED(x[0]); | |
333 | x[0] = 1; | |
334 | x = (int*)Ident(realloc(x, 2 * sizeof(S4))); | |
335 | EXPECT_NOT_POISONED(x[0]); // Ok, was inited before. | |
336 | EXPECT_POISONED(x[1]); | |
337 | x = (int*)Ident(realloc(x, 3 * sizeof(S4))); | |
338 | EXPECT_NOT_POISONED(x[0]); // Ok, was inited before. | |
339 | EXPECT_POISONED(x[2]); | |
340 | EXPECT_POISONED(x[1]); | |
341 | x[2] = 1; // Init this here. Check that after realloc it is poisoned again. | |
342 | x = (int*)Ident(realloc(x, 2 * sizeof(S4))); | |
343 | EXPECT_NOT_POISONED(x[0]); // Ok, was inited before. | |
344 | EXPECT_POISONED(x[1]); | |
345 | x = (int*)Ident(realloc(x, 3 * sizeof(S4))); | |
346 | EXPECT_POISONED(x[1]); | |
347 | EXPECT_POISONED(x[2]); | |
348 | free(x); | |
349 | } | |
350 | ||
351 | TEST(MemorySanitizer, Calloc) { | |
352 | S4 *x = (int*)Ident(calloc(1, sizeof(S4))); | |
353 | EXPECT_NOT_POISONED(*x); // Should not be poisoned. | |
354 | EXPECT_EQ(0, *x); | |
355 | free(x); | |
356 | } | |
357 | ||
358 | TEST(MemorySanitizer, CallocReturnsZeroMem) { | |
359 | size_t sizes[] = {16, 1000, 10000, 100000, 2100000}; | |
360 | for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) { | |
361 | size_t size = sizes[s]; | |
362 | for (size_t iter = 0; iter < 5; iter++) { | |
363 | char *x = Ident((char*)calloc(1, size)); | |
364 | EXPECT_EQ(x[0], 0); | |
365 | EXPECT_EQ(x[size - 1], 0); | |
366 | EXPECT_EQ(x[size / 2], 0); | |
367 | EXPECT_EQ(x[size / 3], 0); | |
368 | EXPECT_EQ(x[size / 4], 0); | |
369 | memset(x, 0x42, size); | |
370 | free(Ident(x)); | |
371 | } | |
372 | } | |
373 | } | |
374 | ||
375 | TEST(MemorySanitizer, AndOr) { | |
376 | U4 *p = GetPoisoned<U4>(); | |
377 | // We poison two bytes in the midle of a 4-byte word to make the test | |
378 | // correct regardless of endianness. | |
379 | ((U1*)p)[1] = 0; | |
380 | ((U1*)p)[2] = 0xff; | |
381 | EXPECT_NOT_POISONED(*p & 0x00ffff00); | |
382 | EXPECT_NOT_POISONED(*p & 0x00ff0000); | |
383 | EXPECT_NOT_POISONED(*p & 0x0000ff00); | |
384 | EXPECT_POISONED(*p & 0xff000000); | |
385 | EXPECT_POISONED(*p & 0x000000ff); | |
386 | EXPECT_POISONED(*p & 0x0000ffff); | |
387 | EXPECT_POISONED(*p & 0xffff0000); | |
388 | ||
389 | EXPECT_NOT_POISONED(*p | 0xff0000ff); | |
390 | EXPECT_NOT_POISONED(*p | 0xff00ffff); | |
391 | EXPECT_NOT_POISONED(*p | 0xffff00ff); | |
392 | EXPECT_POISONED(*p | 0xff000000); | |
393 | EXPECT_POISONED(*p | 0x000000ff); | |
394 | EXPECT_POISONED(*p | 0x0000ffff); | |
395 | EXPECT_POISONED(*p | 0xffff0000); | |
396 | ||
397 | EXPECT_POISONED(*GetPoisoned<bool>() & *GetPoisoned<bool>()); | |
398 | } | |
399 | ||
400 | template<class T> | |
401 | static bool applyNot(T value, T shadow) { | |
402 | __msan_partial_poison(&value, &shadow, sizeof(T)); | |
403 | return !value; | |
404 | } | |
405 | ||
406 | TEST(MemorySanitizer, Not) { | |
407 | EXPECT_NOT_POISONED(applyNot<U4>(0x0, 0x0)); | |
408 | EXPECT_NOT_POISONED(applyNot<U4>(0xFFFFFFFF, 0x0)); | |
409 | EXPECT_POISONED(applyNot<U4>(0xFFFFFFFF, 0xFFFFFFFF)); | |
410 | EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x0FFFFFFF)); | |
411 | EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x00FFFFFF)); | |
412 | EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x0000FFFF)); | |
413 | EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x00000000)); | |
414 | EXPECT_POISONED(applyNot<U4>(0xFF000000, 0xFF000000)); | |
415 | EXPECT_NOT_POISONED(applyNot<U4>(0xFF800000, 0xFF000000)); | |
416 | EXPECT_POISONED(applyNot<U4>(0x00008000, 0x00008000)); | |
417 | ||
418 | EXPECT_NOT_POISONED(applyNot<U1>(0x0, 0x0)); | |
419 | EXPECT_NOT_POISONED(applyNot<U1>(0xFF, 0xFE)); | |
420 | EXPECT_NOT_POISONED(applyNot<U1>(0xFF, 0x0)); | |
421 | EXPECT_POISONED(applyNot<U1>(0xFF, 0xFF)); | |
422 | ||
423 | EXPECT_POISONED(applyNot<void*>((void*)0xFFFFFF, (void*)(-1))); | |
424 | EXPECT_NOT_POISONED(applyNot<void*>((void*)0xFFFFFF, (void*)(-2))); | |
425 | } | |
426 | ||
427 | TEST(MemorySanitizer, Shift) { | |
428 | U4 *up = GetPoisoned<U4>(); | |
429 | ((U1*)up)[0] = 0; | |
430 | ((U1*)up)[3] = 0xff; | |
431 | EXPECT_NOT_POISONED(*up >> 30); | |
432 | EXPECT_NOT_POISONED(*up >> 24); | |
433 | EXPECT_POISONED(*up >> 23); | |
434 | EXPECT_POISONED(*up >> 10); | |
435 | ||
436 | EXPECT_NOT_POISONED(*up << 30); | |
437 | EXPECT_NOT_POISONED(*up << 24); | |
438 | EXPECT_POISONED(*up << 23); | |
439 | EXPECT_POISONED(*up << 10); | |
440 | ||
441 | S4 *sp = (S4*)up; | |
442 | EXPECT_NOT_POISONED(*sp >> 30); | |
443 | EXPECT_NOT_POISONED(*sp >> 24); | |
444 | EXPECT_POISONED(*sp >> 23); | |
445 | EXPECT_POISONED(*sp >> 10); | |
446 | ||
447 | sp = GetPoisoned<S4>(); | |
448 | ((S1*)sp)[1] = 0; | |
449 | ((S1*)sp)[2] = 0; | |
450 | EXPECT_POISONED(*sp >> 31); | |
451 | ||
452 | EXPECT_POISONED(100 >> *GetPoisoned<S4>()); | |
453 | EXPECT_POISONED(100U >> *GetPoisoned<S4>()); | |
454 | } | |
455 | ||
456 | NOINLINE static int GetPoisonedZero() { | |
457 | int *zero = new int; | |
458 | *zero = 0; | |
459 | __msan_poison(zero, sizeof(*zero)); | |
460 | int res = *zero; | |
461 | delete zero; | |
462 | return res; | |
463 | } | |
464 | ||
465 | TEST(MemorySanitizer, LoadFromDirtyAddress) { | |
466 | int *a = new int; | |
467 | *a = 0; | |
468 | EXPECT_UMR(break_optimization((void*)(U8)a[GetPoisonedZero()])); | |
469 | delete a; | |
470 | } | |
471 | ||
472 | TEST(MemorySanitizer, StoreToDirtyAddress) { | |
473 | int *a = new int; | |
474 | EXPECT_UMR(a[GetPoisonedZero()] = 0); | |
475 | break_optimization(a); | |
476 | delete a; | |
477 | } | |
478 | ||
479 | ||
480 | NOINLINE void StackTestFunc() { | |
481 | S4 p4; | |
482 | S4 ok4 = 1; | |
483 | S2 p2; | |
484 | S2 ok2 = 1; | |
485 | S1 p1; | |
486 | S1 ok1 = 1; | |
487 | break_optimization(&p4); | |
488 | break_optimization(&ok4); | |
489 | break_optimization(&p2); | |
490 | break_optimization(&ok2); | |
491 | break_optimization(&p1); | |
492 | break_optimization(&ok1); | |
493 | ||
494 | EXPECT_POISONED(p4); | |
495 | EXPECT_POISONED(p2); | |
496 | EXPECT_POISONED(p1); | |
497 | EXPECT_NOT_POISONED(ok1); | |
498 | EXPECT_NOT_POISONED(ok2); | |
499 | EXPECT_NOT_POISONED(ok4); | |
500 | } | |
501 | ||
502 | TEST(MemorySanitizer, StackTest) { | |
503 | StackTestFunc(); | |
504 | } | |
505 | ||
506 | NOINLINE void StackStressFunc() { | |
507 | int foo[10000]; | |
508 | break_optimization(foo); | |
509 | } | |
510 | ||
511 | TEST(MemorySanitizer, DISABLED_StackStressTest) { | |
512 | for (int i = 0; i < 1000000; i++) | |
513 | StackStressFunc(); | |
514 | } | |
515 | ||
516 | template<class T> | |
517 | void TestFloatingPoint() { | |
518 | static volatile T v; | |
519 | static T g[100]; | |
520 | break_optimization(&g); | |
521 | T *x = GetPoisoned<T>(); | |
522 | T *y = GetPoisoned<T>(1); | |
523 | EXPECT_POISONED(*x); | |
524 | EXPECT_POISONED((long long)*x); | |
525 | EXPECT_POISONED((int)*x); | |
526 | g[0] = *x; | |
527 | g[1] = *x + *y; | |
528 | g[2] = *x - *y; | |
529 | g[3] = *x * *y; | |
530 | } | |
531 | ||
532 | TEST(MemorySanitizer, FloatingPointTest) { | |
533 | TestFloatingPoint<float>(); | |
534 | TestFloatingPoint<double>(); | |
535 | } | |
536 | ||
537 | TEST(MemorySanitizer, DynMem) { | |
538 | S4 x = 0; | |
539 | S4 *y = GetPoisoned<S4>(); | |
540 | memcpy(y, &x, g_one * sizeof(S4)); | |
541 | EXPECT_NOT_POISONED(*y); | |
542 | } | |
543 | ||
544 | static char *DynRetTestStr; | |
545 | ||
546 | TEST(MemorySanitizer, DynRet) { | |
1a4d82fc | 547 | ReturnPoisoned<S8>(); |
92a42be0 | 548 | EXPECT_NOT_POISONED(atoi("0")); |
1a4d82fc JJ |
549 | } |
550 | ||
1a4d82fc | 551 | TEST(MemorySanitizer, DynRet1) { |
1a4d82fc JJ |
552 | ReturnPoisoned<S8>(); |
553 | } | |
554 | ||
555 | struct LargeStruct { | |
556 | S4 x[10]; | |
557 | }; | |
558 | ||
559 | NOINLINE | |
560 | LargeStruct LargeRetTest() { | |
561 | LargeStruct res; | |
562 | res.x[0] = *GetPoisoned<S4>(); | |
563 | res.x[1] = *GetPoisoned<S4>(); | |
564 | res.x[2] = *GetPoisoned<S4>(); | |
565 | res.x[3] = *GetPoisoned<S4>(); | |
566 | res.x[4] = *GetPoisoned<S4>(); | |
567 | res.x[5] = *GetPoisoned<S4>(); | |
568 | res.x[6] = *GetPoisoned<S4>(); | |
569 | res.x[7] = *GetPoisoned<S4>(); | |
570 | res.x[8] = *GetPoisoned<S4>(); | |
571 | res.x[9] = *GetPoisoned<S4>(); | |
572 | return res; | |
573 | } | |
574 | ||
575 | TEST(MemorySanitizer, strcmp) { | |
576 | char s1[10]; | |
577 | char s2[10]; | |
578 | strncpy(s1, "foo", 10); | |
579 | s2[0] = 'f'; | |
580 | s2[1] = 'n'; | |
581 | EXPECT_GT(strcmp(s1, s2), 0); | |
582 | s2[1] = 'o'; | |
583 | int res; | |
584 | EXPECT_UMR(res = strcmp(s1, s2)); | |
585 | EXPECT_NOT_POISONED(res); | |
586 | EXPECT_EQ(strncmp(s1, s2, 1), 0); | |
587 | } | |
588 | ||
589 | TEST(MemorySanitizer, LargeRet) { | |
590 | LargeStruct a = LargeRetTest(); | |
591 | EXPECT_POISONED(a.x[0]); | |
592 | EXPECT_POISONED(a.x[9]); | |
593 | } | |
594 | ||
595 | TEST(MemorySanitizer, strerror) { | |
596 | char *buf = strerror(EINVAL); | |
597 | EXPECT_NOT_POISONED(strlen(buf)); | |
598 | buf = strerror(123456); | |
599 | EXPECT_NOT_POISONED(strlen(buf)); | |
600 | } | |
601 | ||
602 | TEST(MemorySanitizer, strerror_r) { | |
603 | errno = 0; | |
604 | char buf[1000]; | |
92a42be0 | 605 | char *res = (char*) (size_t) strerror_r(EINVAL, buf, sizeof(buf)); |
1a4d82fc JJ |
606 | ASSERT_EQ(0, errno); |
607 | if (!res) res = buf; // POSIX version success. | |
608 | EXPECT_NOT_POISONED(strlen(res)); | |
609 | } | |
610 | ||
611 | TEST(MemorySanitizer, fread) { | |
612 | char *x = new char[32]; | |
92a42be0 | 613 | FILE *f = fopen(FILE_TO_READ, "r"); |
1a4d82fc JJ |
614 | ASSERT_TRUE(f != NULL); |
615 | fread(x, 1, 32, f); | |
616 | EXPECT_NOT_POISONED(x[0]); | |
617 | EXPECT_NOT_POISONED(x[16]); | |
618 | EXPECT_NOT_POISONED(x[31]); | |
619 | fclose(f); | |
92a42be0 | 620 | delete[] x; |
1a4d82fc JJ |
621 | } |
622 | ||
623 | TEST(MemorySanitizer, read) { | |
624 | char *x = new char[32]; | |
92a42be0 | 625 | int fd = open(FILE_TO_READ, O_RDONLY); |
1a4d82fc JJ |
626 | ASSERT_GT(fd, 0); |
627 | int sz = read(fd, x, 32); | |
628 | ASSERT_EQ(sz, 32); | |
629 | EXPECT_NOT_POISONED(x[0]); | |
630 | EXPECT_NOT_POISONED(x[16]); | |
631 | EXPECT_NOT_POISONED(x[31]); | |
632 | close(fd); | |
92a42be0 | 633 | delete[] x; |
1a4d82fc JJ |
634 | } |
635 | ||
636 | TEST(MemorySanitizer, pread) { | |
637 | char *x = new char[32]; | |
92a42be0 | 638 | int fd = open(FILE_TO_READ, O_RDONLY); |
1a4d82fc JJ |
639 | ASSERT_GT(fd, 0); |
640 | int sz = pread(fd, x, 32, 0); | |
641 | ASSERT_EQ(sz, 32); | |
642 | EXPECT_NOT_POISONED(x[0]); | |
643 | EXPECT_NOT_POISONED(x[16]); | |
644 | EXPECT_NOT_POISONED(x[31]); | |
645 | close(fd); | |
92a42be0 | 646 | delete[] x; |
1a4d82fc JJ |
647 | } |
648 | ||
649 | TEST(MemorySanitizer, readv) { | |
650 | char buf[2011]; | |
651 | struct iovec iov[2]; | |
652 | iov[0].iov_base = buf + 1; | |
653 | iov[0].iov_len = 5; | |
654 | iov[1].iov_base = buf + 10; | |
655 | iov[1].iov_len = 2000; | |
92a42be0 | 656 | int fd = open(FILE_TO_READ, O_RDONLY); |
1a4d82fc JJ |
657 | ASSERT_GT(fd, 0); |
658 | int sz = readv(fd, iov, 2); | |
659 | ASSERT_GE(sz, 0); | |
92a42be0 | 660 | ASSERT_LE(sz, 5 + 2000); |
1a4d82fc JJ |
661 | ASSERT_GT((size_t)sz, iov[0].iov_len); |
662 | EXPECT_POISONED(buf[0]); | |
663 | EXPECT_NOT_POISONED(buf[1]); | |
664 | EXPECT_NOT_POISONED(buf[5]); | |
665 | EXPECT_POISONED(buf[6]); | |
666 | EXPECT_POISONED(buf[9]); | |
667 | EXPECT_NOT_POISONED(buf[10]); | |
668 | EXPECT_NOT_POISONED(buf[10 + (sz - 1) - 5]); | |
669 | EXPECT_POISONED(buf[11 + (sz - 1) - 5]); | |
670 | close(fd); | |
671 | } | |
672 | ||
673 | TEST(MemorySanitizer, preadv) { | |
674 | char buf[2011]; | |
675 | struct iovec iov[2]; | |
676 | iov[0].iov_base = buf + 1; | |
677 | iov[0].iov_len = 5; | |
678 | iov[1].iov_base = buf + 10; | |
679 | iov[1].iov_len = 2000; | |
92a42be0 | 680 | int fd = open(FILE_TO_READ, O_RDONLY); |
1a4d82fc JJ |
681 | ASSERT_GT(fd, 0); |
682 | int sz = preadv(fd, iov, 2, 3); | |
683 | ASSERT_GE(sz, 0); | |
92a42be0 | 684 | ASSERT_LE(sz, 5 + 2000); |
1a4d82fc JJ |
685 | ASSERT_GT((size_t)sz, iov[0].iov_len); |
686 | EXPECT_POISONED(buf[0]); | |
687 | EXPECT_NOT_POISONED(buf[1]); | |
688 | EXPECT_NOT_POISONED(buf[5]); | |
689 | EXPECT_POISONED(buf[6]); | |
690 | EXPECT_POISONED(buf[9]); | |
691 | EXPECT_NOT_POISONED(buf[10]); | |
692 | EXPECT_NOT_POISONED(buf[10 + (sz - 1) - 5]); | |
693 | EXPECT_POISONED(buf[11 + (sz - 1) - 5]); | |
694 | close(fd); | |
695 | } | |
696 | ||
697 | // FIXME: fails now. | |
698 | TEST(MemorySanitizer, DISABLED_ioctl) { | |
699 | struct winsize ws; | |
700 | EXPECT_EQ(ioctl(2, TIOCGWINSZ, &ws), 0); | |
701 | EXPECT_NOT_POISONED(ws.ws_col); | |
702 | } | |
703 | ||
704 | TEST(MemorySanitizer, readlink) { | |
705 | char *x = new char[1000]; | |
92a42be0 | 706 | readlink(SYMLINK_TO_READ, x, 1000); |
1a4d82fc JJ |
707 | EXPECT_NOT_POISONED(x[0]); |
708 | delete [] x; | |
709 | } | |
710 | ||
1a4d82fc JJ |
711 | TEST(MemorySanitizer, stat) { |
712 | struct stat* st = new struct stat; | |
92a42be0 | 713 | int res = stat(FILE_TO_READ, st); |
1a4d82fc JJ |
714 | ASSERT_EQ(0, res); |
715 | EXPECT_NOT_POISONED(st->st_dev); | |
716 | EXPECT_NOT_POISONED(st->st_mode); | |
717 | EXPECT_NOT_POISONED(st->st_size); | |
718 | } | |
719 | ||
720 | TEST(MemorySanitizer, fstatat) { | |
721 | struct stat* st = new struct stat; | |
92a42be0 | 722 | int dirfd = open(DIR_TO_READ, O_RDONLY); |
1a4d82fc | 723 | ASSERT_GT(dirfd, 0); |
92a42be0 | 724 | int res = fstatat(dirfd, SUBFILE_TO_READ, st, 0); |
1a4d82fc JJ |
725 | ASSERT_EQ(0, res); |
726 | EXPECT_NOT_POISONED(st->st_dev); | |
727 | EXPECT_NOT_POISONED(st->st_mode); | |
728 | EXPECT_NOT_POISONED(st->st_size); | |
729 | close(dirfd); | |
730 | } | |
731 | ||
732 | TEST(MemorySanitizer, statfs) { | |
733 | struct statfs st; | |
734 | int res = statfs("/", &st); | |
735 | ASSERT_EQ(0, res); | |
736 | EXPECT_NOT_POISONED(st.f_type); | |
737 | EXPECT_NOT_POISONED(st.f_bfree); | |
738 | EXPECT_NOT_POISONED(st.f_namelen); | |
739 | } | |
740 | ||
741 | TEST(MemorySanitizer, statvfs) { | |
742 | struct statvfs st; | |
743 | int res = statvfs("/", &st); | |
744 | ASSERT_EQ(0, res); | |
745 | EXPECT_NOT_POISONED(st.f_bsize); | |
746 | EXPECT_NOT_POISONED(st.f_blocks); | |
747 | EXPECT_NOT_POISONED(st.f_bfree); | |
748 | EXPECT_NOT_POISONED(st.f_namemax); | |
749 | } | |
750 | ||
751 | TEST(MemorySanitizer, fstatvfs) { | |
752 | struct statvfs st; | |
753 | int fd = open("/", O_RDONLY | O_DIRECTORY); | |
754 | int res = fstatvfs(fd, &st); | |
755 | ASSERT_EQ(0, res); | |
756 | EXPECT_NOT_POISONED(st.f_bsize); | |
757 | EXPECT_NOT_POISONED(st.f_blocks); | |
758 | EXPECT_NOT_POISONED(st.f_bfree); | |
759 | EXPECT_NOT_POISONED(st.f_namemax); | |
760 | close(fd); | |
761 | } | |
762 | ||
763 | TEST(MemorySanitizer, pipe) { | |
764 | int* pipefd = new int[2]; | |
765 | int res = pipe(pipefd); | |
766 | ASSERT_EQ(0, res); | |
767 | EXPECT_NOT_POISONED(pipefd[0]); | |
768 | EXPECT_NOT_POISONED(pipefd[1]); | |
769 | close(pipefd[0]); | |
770 | close(pipefd[1]); | |
771 | } | |
772 | ||
773 | TEST(MemorySanitizer, pipe2) { | |
774 | int* pipefd = new int[2]; | |
775 | int res = pipe2(pipefd, O_NONBLOCK); | |
776 | ASSERT_EQ(0, res); | |
777 | EXPECT_NOT_POISONED(pipefd[0]); | |
778 | EXPECT_NOT_POISONED(pipefd[1]); | |
779 | close(pipefd[0]); | |
780 | close(pipefd[1]); | |
781 | } | |
782 | ||
783 | TEST(MemorySanitizer, socketpair) { | |
784 | int sv[2]; | |
785 | int res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); | |
786 | ASSERT_EQ(0, res); | |
787 | EXPECT_NOT_POISONED(sv[0]); | |
788 | EXPECT_NOT_POISONED(sv[1]); | |
789 | close(sv[0]); | |
790 | close(sv[1]); | |
791 | } | |
792 | ||
793 | TEST(MemorySanitizer, poll) { | |
794 | int* pipefd = new int[2]; | |
795 | int res = pipe(pipefd); | |
796 | ASSERT_EQ(0, res); | |
797 | ||
798 | char data = 42; | |
799 | res = write(pipefd[1], &data, 1); | |
800 | ASSERT_EQ(1, res); | |
801 | ||
802 | pollfd fds[2]; | |
803 | fds[0].fd = pipefd[0]; | |
804 | fds[0].events = POLLIN; | |
805 | fds[1].fd = pipefd[1]; | |
806 | fds[1].events = POLLIN; | |
807 | res = poll(fds, 2, 500); | |
808 | ASSERT_EQ(1, res); | |
809 | EXPECT_NOT_POISONED(fds[0].revents); | |
810 | EXPECT_NOT_POISONED(fds[1].revents); | |
811 | ||
812 | close(pipefd[0]); | |
813 | close(pipefd[1]); | |
814 | } | |
815 | ||
92a42be0 SL |
816 | // There is no ppoll() on FreeBSD. |
817 | #if !defined (__FreeBSD__) | |
1a4d82fc JJ |
818 | TEST(MemorySanitizer, ppoll) { |
819 | int* pipefd = new int[2]; | |
820 | int res = pipe(pipefd); | |
821 | ASSERT_EQ(0, res); | |
822 | ||
823 | char data = 42; | |
824 | res = write(pipefd[1], &data, 1); | |
825 | ASSERT_EQ(1, res); | |
826 | ||
827 | pollfd fds[2]; | |
828 | fds[0].fd = pipefd[0]; | |
829 | fds[0].events = POLLIN; | |
830 | fds[1].fd = pipefd[1]; | |
831 | fds[1].events = POLLIN; | |
832 | sigset_t ss; | |
833 | sigemptyset(&ss); | |
834 | res = ppoll(fds, 2, NULL, &ss); | |
835 | ASSERT_EQ(1, res); | |
836 | EXPECT_NOT_POISONED(fds[0].revents); | |
837 | EXPECT_NOT_POISONED(fds[1].revents); | |
838 | ||
839 | close(pipefd[0]); | |
840 | close(pipefd[1]); | |
841 | } | |
92a42be0 | 842 | #endif |
1a4d82fc JJ |
843 | |
844 | TEST(MemorySanitizer, poll_positive) { | |
845 | int* pipefd = new int[2]; | |
846 | int res = pipe(pipefd); | |
847 | ASSERT_EQ(0, res); | |
848 | ||
849 | pollfd fds[2]; | |
850 | fds[0].fd = pipefd[0]; | |
851 | fds[0].events = POLLIN; | |
852 | // fds[1].fd uninitialized | |
853 | fds[1].events = POLLIN; | |
854 | EXPECT_UMR(poll(fds, 2, 0)); | |
855 | ||
856 | close(pipefd[0]); | |
857 | close(pipefd[1]); | |
858 | } | |
859 | ||
860 | TEST(MemorySanitizer, bind_getsockname) { | |
861 | int sock = socket(AF_UNIX, SOCK_STREAM, 0); | |
862 | ||
863 | struct sockaddr_in sai; | |
864 | memset(&sai, 0, sizeof(sai)); | |
865 | sai.sin_family = AF_UNIX; | |
866 | int res = bind(sock, (struct sockaddr *)&sai, sizeof(sai)); | |
867 | ||
868 | ASSERT_EQ(0, res); | |
869 | char buf[200]; | |
870 | socklen_t addrlen; | |
871 | EXPECT_UMR(getsockname(sock, (struct sockaddr *)&buf, &addrlen)); | |
872 | ||
873 | addrlen = sizeof(buf); | |
874 | res = getsockname(sock, (struct sockaddr *)&buf, &addrlen); | |
875 | EXPECT_NOT_POISONED(addrlen); | |
876 | EXPECT_NOT_POISONED(buf[0]); | |
877 | EXPECT_NOT_POISONED(buf[addrlen - 1]); | |
878 | EXPECT_POISONED(buf[addrlen]); | |
879 | close(sock); | |
880 | } | |
881 | ||
882 | TEST(MemorySanitizer, accept) { | |
883 | int listen_socket = socket(AF_INET, SOCK_STREAM, 0); | |
884 | ASSERT_LT(0, listen_socket); | |
885 | ||
886 | struct sockaddr_in sai; | |
887 | memset(&sai, 0, sizeof(sai)); | |
888 | sai.sin_family = AF_INET; | |
889 | sai.sin_port = 0; | |
890 | sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
891 | int res = bind(listen_socket, (struct sockaddr *)&sai, sizeof(sai)); | |
892 | ASSERT_EQ(0, res); | |
893 | ||
894 | res = listen(listen_socket, 1); | |
895 | ASSERT_EQ(0, res); | |
896 | ||
897 | socklen_t sz = sizeof(sai); | |
898 | res = getsockname(listen_socket, (struct sockaddr *)&sai, &sz); | |
899 | ASSERT_EQ(0, res); | |
900 | ASSERT_EQ(sizeof(sai), sz); | |
901 | ||
902 | int connect_socket = socket(AF_INET, SOCK_STREAM, 0); | |
903 | ASSERT_LT(0, connect_socket); | |
904 | res = fcntl(connect_socket, F_SETFL, O_NONBLOCK); | |
905 | ASSERT_EQ(0, res); | |
906 | res = connect(connect_socket, (struct sockaddr *)&sai, sizeof(sai)); | |
92a42be0 SL |
907 | // On FreeBSD this connection completes immediately. |
908 | if (res != 0) { | |
909 | ASSERT_EQ(-1, res); | |
910 | ASSERT_EQ(EINPROGRESS, errno); | |
911 | } | |
1a4d82fc JJ |
912 | |
913 | __msan_poison(&sai, sizeof(sai)); | |
914 | int new_sock = accept(listen_socket, (struct sockaddr *)&sai, &sz); | |
915 | ASSERT_LT(0, new_sock); | |
916 | ASSERT_EQ(sizeof(sai), sz); | |
917 | EXPECT_NOT_POISONED(sai); | |
918 | ||
919 | __msan_poison(&sai, sizeof(sai)); | |
920 | res = getpeername(new_sock, (struct sockaddr *)&sai, &sz); | |
921 | ASSERT_EQ(0, res); | |
922 | ASSERT_EQ(sizeof(sai), sz); | |
923 | EXPECT_NOT_POISONED(sai); | |
924 | ||
925 | close(new_sock); | |
926 | close(connect_socket); | |
927 | close(listen_socket); | |
928 | } | |
929 | ||
930 | TEST(MemorySanitizer, getaddrinfo) { | |
931 | struct addrinfo *ai; | |
932 | struct addrinfo hints; | |
933 | memset(&hints, 0, sizeof(hints)); | |
934 | hints.ai_family = AF_INET; | |
935 | int res = getaddrinfo("localhost", NULL, &hints, &ai); | |
936 | ASSERT_EQ(0, res); | |
937 | EXPECT_NOT_POISONED(*ai); | |
938 | ASSERT_EQ(sizeof(sockaddr_in), ai->ai_addrlen); | |
939 | EXPECT_NOT_POISONED(*(sockaddr_in*)ai->ai_addr); | |
940 | } | |
941 | ||
942 | TEST(MemorySanitizer, getnameinfo) { | |
943 | struct sockaddr_in sai; | |
944 | memset(&sai, 0, sizeof(sai)); | |
945 | sai.sin_family = AF_INET; | |
946 | sai.sin_port = 80; | |
947 | sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
948 | char host[500]; | |
949 | char serv[500]; | |
950 | int res = getnameinfo((struct sockaddr *)&sai, sizeof(sai), host, | |
951 | sizeof(host), serv, sizeof(serv), 0); | |
952 | ASSERT_EQ(0, res); | |
953 | EXPECT_NOT_POISONED(host[0]); | |
954 | EXPECT_POISONED(host[sizeof(host) - 1]); | |
955 | ||
956 | ASSERT_NE(0U, strlen(host)); | |
957 | EXPECT_NOT_POISONED(serv[0]); | |
958 | EXPECT_POISONED(serv[sizeof(serv) - 1]); | |
959 | ASSERT_NE(0U, strlen(serv)); | |
960 | } | |
961 | ||
962 | #define EXPECT_HOSTENT_NOT_POISONED(he) \ | |
963 | do { \ | |
964 | EXPECT_NOT_POISONED(*(he)); \ | |
965 | ASSERT_NE((void *) 0, (he)->h_name); \ | |
966 | ASSERT_NE((void *) 0, (he)->h_aliases); \ | |
967 | ASSERT_NE((void *) 0, (he)->h_addr_list); \ | |
968 | EXPECT_NOT_POISONED(strlen((he)->h_name)); \ | |
969 | char **p = (he)->h_aliases; \ | |
970 | while (*p) { \ | |
971 | EXPECT_NOT_POISONED(strlen(*p)); \ | |
972 | ++p; \ | |
973 | } \ | |
974 | char **q = (he)->h_addr_list; \ | |
975 | while (*q) { \ | |
976 | EXPECT_NOT_POISONED(*q[0]); \ | |
977 | ++q; \ | |
978 | } \ | |
979 | EXPECT_NOT_POISONED(*q); \ | |
980 | } while (0) | |
981 | ||
982 | TEST(MemorySanitizer, gethostent) { | |
983 | struct hostent *he = gethostent(); | |
984 | ASSERT_NE((void *)NULL, he); | |
985 | EXPECT_HOSTENT_NOT_POISONED(he); | |
986 | } | |
987 | ||
988 | #ifndef MSAN_TEST_DISABLE_GETHOSTBYNAME | |
989 | ||
990 | TEST(MemorySanitizer, gethostbyname) { | |
991 | struct hostent *he = gethostbyname("localhost"); | |
992 | ASSERT_NE((void *)NULL, he); | |
993 | EXPECT_HOSTENT_NOT_POISONED(he); | |
994 | } | |
995 | ||
996 | #endif // MSAN_TEST_DISABLE_GETHOSTBYNAME | |
997 | ||
998 | TEST(MemorySanitizer, recvmsg) { | |
999 | int server_socket = socket(AF_INET, SOCK_DGRAM, 0); | |
1000 | ASSERT_LT(0, server_socket); | |
1001 | ||
1002 | struct sockaddr_in sai; | |
1003 | memset(&sai, 0, sizeof(sai)); | |
1004 | sai.sin_family = AF_INET; | |
1005 | sai.sin_port = 0; | |
1006 | sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
1007 | int res = bind(server_socket, (struct sockaddr *)&sai, sizeof(sai)); | |
1008 | ASSERT_EQ(0, res); | |
1009 | ||
1010 | socklen_t sz = sizeof(sai); | |
1011 | res = getsockname(server_socket, (struct sockaddr *)&sai, &sz); | |
1012 | ASSERT_EQ(0, res); | |
1013 | ASSERT_EQ(sizeof(sai), sz); | |
1014 | ||
1015 | ||
1016 | int client_socket = socket(AF_INET, SOCK_DGRAM, 0); | |
1017 | ASSERT_LT(0, client_socket); | |
1018 | ||
1019 | struct sockaddr_in client_sai; | |
1020 | memset(&client_sai, 0, sizeof(client_sai)); | |
1021 | client_sai.sin_family = AF_INET; | |
1022 | client_sai.sin_port = 0; | |
1023 | client_sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
1024 | res = bind(client_socket, (struct sockaddr *)&client_sai, sizeof(client_sai)); | |
1025 | ASSERT_EQ(0, res); | |
1026 | ||
1027 | sz = sizeof(client_sai); | |
1028 | res = getsockname(client_socket, (struct sockaddr *)&client_sai, &sz); | |
1029 | ASSERT_EQ(0, res); | |
1030 | ASSERT_EQ(sizeof(client_sai), sz); | |
1031 | ||
1a4d82fc JJ |
1032 | const char *s = "message text"; |
1033 | struct iovec iov; | |
1034 | iov.iov_base = (void *)s; | |
1035 | iov.iov_len = strlen(s) + 1; | |
1036 | struct msghdr msg; | |
1037 | memset(&msg, 0, sizeof(msg)); | |
1038 | msg.msg_name = &sai; | |
1039 | msg.msg_namelen = sizeof(sai); | |
1040 | msg.msg_iov = &iov; | |
1041 | msg.msg_iovlen = 1; | |
1042 | res = sendmsg(client_socket, &msg, 0); | |
1043 | ASSERT_LT(0, res); | |
1044 | ||
1045 | ||
1046 | char buf[1000]; | |
1047 | struct iovec recv_iov; | |
1048 | recv_iov.iov_base = (void *)&buf; | |
1049 | recv_iov.iov_len = sizeof(buf); | |
1050 | struct sockaddr_in recv_sai; | |
1051 | struct msghdr recv_msg; | |
1052 | memset(&recv_msg, 0, sizeof(recv_msg)); | |
1053 | recv_msg.msg_name = &recv_sai; | |
1054 | recv_msg.msg_namelen = sizeof(recv_sai); | |
1055 | recv_msg.msg_iov = &recv_iov; | |
1056 | recv_msg.msg_iovlen = 1; | |
1057 | res = recvmsg(server_socket, &recv_msg, 0); | |
1058 | ASSERT_LT(0, res); | |
1059 | ||
1060 | ASSERT_EQ(sizeof(recv_sai), recv_msg.msg_namelen); | |
1061 | EXPECT_NOT_POISONED(*(struct sockaddr_in *)recv_msg.msg_name); | |
1062 | EXPECT_STREQ(s, buf); | |
1063 | ||
1064 | close(server_socket); | |
1065 | close(client_socket); | |
1066 | } | |
1067 | ||
1068 | TEST(MemorySanitizer, gethostbyname2) { | |
1069 | struct hostent *he = gethostbyname2("localhost", AF_INET); | |
1070 | ASSERT_NE((void *)NULL, he); | |
1071 | EXPECT_HOSTENT_NOT_POISONED(he); | |
1072 | } | |
1073 | ||
1074 | TEST(MemorySanitizer, gethostbyaddr) { | |
1075 | in_addr_t addr = inet_addr("127.0.0.1"); | |
1076 | EXPECT_NOT_POISONED(addr); | |
1077 | struct hostent *he = gethostbyaddr(&addr, sizeof(addr), AF_INET); | |
1078 | ASSERT_NE((void *)NULL, he); | |
1079 | EXPECT_HOSTENT_NOT_POISONED(he); | |
1080 | } | |
1081 | ||
1082 | TEST(MemorySanitizer, gethostent_r) { | |
1083 | char buf[2000]; | |
1084 | struct hostent he; | |
1085 | struct hostent *result; | |
1086 | int err; | |
1087 | int res = gethostent_r(&he, buf, sizeof(buf), &result, &err); | |
1088 | ASSERT_EQ(0, res); | |
1089 | EXPECT_NOT_POISONED(result); | |
1090 | ASSERT_NE((void *)NULL, result); | |
1091 | EXPECT_HOSTENT_NOT_POISONED(result); | |
1092 | EXPECT_NOT_POISONED(err); | |
1093 | } | |
1094 | ||
1095 | TEST(MemorySanitizer, gethostbyname_r) { | |
1096 | char buf[2000]; | |
1097 | struct hostent he; | |
1098 | struct hostent *result; | |
1099 | int err; | |
1100 | int res = gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err); | |
1101 | ASSERT_EQ(0, res); | |
1102 | EXPECT_NOT_POISONED(result); | |
1103 | ASSERT_NE((void *)NULL, result); | |
1104 | EXPECT_HOSTENT_NOT_POISONED(result); | |
1105 | EXPECT_NOT_POISONED(err); | |
1106 | } | |
1107 | ||
1108 | TEST(MemorySanitizer, gethostbyname_r_bad_host_name) { | |
1109 | char buf[2000]; | |
1110 | struct hostent he; | |
1111 | struct hostent *result; | |
1112 | int err; | |
1113 | int res = gethostbyname_r("bad-host-name", &he, buf, sizeof(buf), &result, &err); | |
1114 | ASSERT_EQ((struct hostent *)0, result); | |
1115 | EXPECT_NOT_POISONED(err); | |
1116 | } | |
1117 | ||
1118 | TEST(MemorySanitizer, gethostbyname_r_erange) { | |
1119 | char buf[5]; | |
1120 | struct hostent he; | |
1121 | struct hostent *result; | |
1122 | int err; | |
5bcae85e SL |
1123 | gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err); |
1124 | ASSERT_EQ(ERANGE, errno); | |
1a4d82fc JJ |
1125 | EXPECT_NOT_POISONED(err); |
1126 | } | |
1127 | ||
1128 | TEST(MemorySanitizer, gethostbyname2_r) { | |
1129 | char buf[2000]; | |
1130 | struct hostent he; | |
1131 | struct hostent *result; | |
1132 | int err; | |
1133 | int res = gethostbyname2_r("localhost", AF_INET, &he, buf, sizeof(buf), | |
1134 | &result, &err); | |
1135 | ASSERT_EQ(0, res); | |
1136 | EXPECT_NOT_POISONED(result); | |
1137 | ASSERT_NE((void *)NULL, result); | |
1138 | EXPECT_HOSTENT_NOT_POISONED(result); | |
1139 | EXPECT_NOT_POISONED(err); | |
1140 | } | |
1141 | ||
1142 | TEST(MemorySanitizer, gethostbyaddr_r) { | |
1143 | char buf[2000]; | |
1144 | struct hostent he; | |
1145 | struct hostent *result; | |
1146 | int err; | |
1147 | in_addr_t addr = inet_addr("127.0.0.1"); | |
1148 | EXPECT_NOT_POISONED(addr); | |
1149 | int res = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &he, buf, sizeof(buf), | |
1150 | &result, &err); | |
1151 | ASSERT_EQ(0, res); | |
1152 | EXPECT_NOT_POISONED(result); | |
1153 | ASSERT_NE((void *)NULL, result); | |
1154 | EXPECT_HOSTENT_NOT_POISONED(result); | |
1155 | EXPECT_NOT_POISONED(err); | |
1156 | } | |
1157 | ||
1158 | TEST(MemorySanitizer, getsockopt) { | |
1159 | int sock = socket(AF_UNIX, SOCK_STREAM, 0); | |
1160 | struct linger l[2]; | |
1161 | socklen_t sz = sizeof(l[0]); | |
1162 | int res = getsockopt(sock, SOL_SOCKET, SO_LINGER, &l[0], &sz); | |
1163 | ASSERT_EQ(0, res); | |
1164 | ASSERT_EQ(sizeof(l[0]), sz); | |
1165 | EXPECT_NOT_POISONED(l[0]); | |
1166 | EXPECT_POISONED(*(char *)(l + 1)); | |
1167 | } | |
1168 | ||
1169 | TEST(MemorySanitizer, getcwd) { | |
1170 | char path[PATH_MAX + 1]; | |
1171 | char* res = getcwd(path, sizeof(path)); | |
1172 | ASSERT_TRUE(res != NULL); | |
1173 | EXPECT_NOT_POISONED(path[0]); | |
1174 | } | |
1175 | ||
1176 | TEST(MemorySanitizer, getcwd_gnu) { | |
1177 | char* res = getcwd(NULL, 0); | |
1178 | ASSERT_TRUE(res != NULL); | |
1179 | EXPECT_NOT_POISONED(res[0]); | |
1180 | free(res); | |
1181 | } | |
1182 | ||
92a42be0 SL |
1183 | // There's no get_current_dir_name() on FreeBSD. |
1184 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1185 | TEST(MemorySanitizer, get_current_dir_name) { |
1186 | char* res = get_current_dir_name(); | |
1187 | ASSERT_TRUE(res != NULL); | |
1188 | EXPECT_NOT_POISONED(res[0]); | |
1189 | free(res); | |
1190 | } | |
92a42be0 | 1191 | #endif |
1a4d82fc JJ |
1192 | |
1193 | TEST(MemorySanitizer, shmctl) { | |
1194 | int id = shmget(IPC_PRIVATE, 4096, 0644 | IPC_CREAT); | |
1195 | ASSERT_GT(id, -1); | |
1196 | ||
1197 | struct shmid_ds ds; | |
1198 | int res = shmctl(id, IPC_STAT, &ds); | |
1199 | ASSERT_GT(res, -1); | |
1200 | EXPECT_NOT_POISONED(ds); | |
1201 | ||
92a42be0 SL |
1202 | // FreeBSD does not support shmctl(IPC_INFO) and shmctl(SHM_INFO). |
1203 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1204 | struct shminfo si; |
1205 | res = shmctl(id, IPC_INFO, (struct shmid_ds *)&si); | |
1206 | ASSERT_GT(res, -1); | |
1207 | EXPECT_NOT_POISONED(si); | |
1208 | ||
1209 | struct shm_info s_i; | |
1210 | res = shmctl(id, SHM_INFO, (struct shmid_ds *)&s_i); | |
1211 | ASSERT_GT(res, -1); | |
1212 | EXPECT_NOT_POISONED(s_i); | |
92a42be0 | 1213 | #endif |
1a4d82fc JJ |
1214 | |
1215 | res = shmctl(id, IPC_RMID, 0); | |
1216 | ASSERT_GT(res, -1); | |
1217 | } | |
1218 | ||
1219 | TEST(MemorySanitizer, shmat) { | |
5bcae85e SL |
1220 | const int kShmSize = 4096; |
1221 | void *mapping_start = mmap(NULL, kShmSize + SHMLBA, PROT_READ | PROT_WRITE, | |
1222 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
1223 | ASSERT_NE(MAP_FAILED, mapping_start); | |
1224 | ||
1225 | void *p = (void *)(((unsigned long)mapping_start + SHMLBA - 1) / SHMLBA * SHMLBA); | |
1226 | // p is now SHMLBA-aligned; | |
1a4d82fc JJ |
1227 | |
1228 | ((char *)p)[10] = *GetPoisoned<U1>(); | |
5bcae85e | 1229 | ((char *)p)[kShmSize - 1] = *GetPoisoned<U1>(); |
1a4d82fc | 1230 | |
5bcae85e | 1231 | int res = munmap(mapping_start, kShmSize + SHMLBA); |
1a4d82fc JJ |
1232 | ASSERT_EQ(0, res); |
1233 | ||
5bcae85e | 1234 | int id = shmget(IPC_PRIVATE, kShmSize, 0644 | IPC_CREAT); |
1a4d82fc JJ |
1235 | ASSERT_GT(id, -1); |
1236 | ||
1237 | void *q = shmat(id, p, 0); | |
1238 | ASSERT_EQ(p, q); | |
1239 | ||
1240 | EXPECT_NOT_POISONED(((char *)q)[0]); | |
1241 | EXPECT_NOT_POISONED(((char *)q)[10]); | |
5bcae85e | 1242 | EXPECT_NOT_POISONED(((char *)q)[kShmSize - 1]); |
1a4d82fc JJ |
1243 | |
1244 | res = shmdt(q); | |
1245 | ASSERT_EQ(0, res); | |
1246 | ||
1247 | res = shmctl(id, IPC_RMID, 0); | |
1248 | ASSERT_GT(res, -1); | |
1249 | } | |
1250 | ||
92a42be0 SL |
1251 | // There's no random_r() on FreeBSD. |
1252 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1253 | TEST(MemorySanitizer, random_r) { |
1254 | int32_t x; | |
1255 | char z[64]; | |
1256 | memset(z, 0, sizeof(z)); | |
1257 | ||
1258 | struct random_data buf; | |
1259 | memset(&buf, 0, sizeof(buf)); | |
1260 | ||
1261 | int res = initstate_r(0, z, sizeof(z), &buf); | |
1262 | ASSERT_EQ(0, res); | |
1263 | ||
1264 | res = random_r(&buf, &x); | |
1265 | ASSERT_EQ(0, res); | |
1266 | EXPECT_NOT_POISONED(x); | |
1267 | } | |
92a42be0 | 1268 | #endif |
1a4d82fc JJ |
1269 | |
1270 | TEST(MemorySanitizer, confstr) { | |
1271 | char buf[3]; | |
1272 | size_t res = confstr(_CS_PATH, buf, sizeof(buf)); | |
1273 | ASSERT_GT(res, sizeof(buf)); | |
1274 | EXPECT_NOT_POISONED(buf[0]); | |
1275 | EXPECT_NOT_POISONED(buf[sizeof(buf) - 1]); | |
1276 | ||
1277 | char buf2[1000]; | |
1278 | res = confstr(_CS_PATH, buf2, sizeof(buf2)); | |
1279 | ASSERT_LT(res, sizeof(buf2)); | |
1280 | EXPECT_NOT_POISONED(buf2[0]); | |
1281 | EXPECT_NOT_POISONED(buf2[res - 1]); | |
1282 | EXPECT_POISONED(buf2[res]); | |
1283 | ASSERT_EQ(res, strlen(buf2) + 1); | |
1284 | } | |
1285 | ||
92a42be0 SL |
1286 | TEST(MemorySanitizer, opendir) { |
1287 | DIR *dir = opendir("."); | |
1288 | closedir(dir); | |
1289 | ||
1290 | char name[10] = "."; | |
1291 | __msan_poison(name, sizeof(name)); | |
1292 | EXPECT_UMR(dir = opendir(name)); | |
1293 | closedir(dir); | |
1294 | } | |
1295 | ||
1a4d82fc JJ |
1296 | TEST(MemorySanitizer, readdir) { |
1297 | DIR *dir = opendir("."); | |
1298 | struct dirent *d = readdir(dir); | |
1299 | ASSERT_TRUE(d != NULL); | |
1300 | EXPECT_NOT_POISONED(d->d_name[0]); | |
1301 | closedir(dir); | |
1302 | } | |
1303 | ||
1304 | TEST(MemorySanitizer, readdir_r) { | |
1305 | DIR *dir = opendir("."); | |
1306 | struct dirent d; | |
1307 | struct dirent *pd; | |
1308 | int res = readdir_r(dir, &d, &pd); | |
1309 | ASSERT_EQ(0, res); | |
1310 | EXPECT_NOT_POISONED(pd); | |
1311 | EXPECT_NOT_POISONED(d.d_name[0]); | |
1312 | closedir(dir); | |
1313 | } | |
1314 | ||
1315 | TEST(MemorySanitizer, realpath) { | |
1316 | const char* relpath = "."; | |
1317 | char path[PATH_MAX + 1]; | |
1318 | char* res = realpath(relpath, path); | |
1319 | ASSERT_TRUE(res != NULL); | |
1320 | EXPECT_NOT_POISONED(path[0]); | |
1321 | } | |
1322 | ||
1323 | TEST(MemorySanitizer, realpath_null) { | |
1324 | const char* relpath = "."; | |
1325 | char* res = realpath(relpath, NULL); | |
1326 | printf("%d, %s\n", errno, strerror(errno)); | |
1327 | ASSERT_TRUE(res != NULL); | |
1328 | EXPECT_NOT_POISONED(res[0]); | |
1329 | free(res); | |
1330 | } | |
1331 | ||
92a42be0 SL |
1332 | // There's no canonicalize_file_name() on FreeBSD. |
1333 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1334 | TEST(MemorySanitizer, canonicalize_file_name) { |
1335 | const char* relpath = "."; | |
1336 | char* res = canonicalize_file_name(relpath); | |
1337 | ASSERT_TRUE(res != NULL); | |
1338 | EXPECT_NOT_POISONED(res[0]); | |
1339 | free(res); | |
1340 | } | |
92a42be0 | 1341 | #endif |
1a4d82fc JJ |
1342 | |
1343 | extern char **environ; | |
1344 | ||
1345 | TEST(MemorySanitizer, setenv) { | |
1346 | setenv("AAA", "BBB", 1); | |
1347 | for (char **envp = environ; *envp; ++envp) { | |
1348 | EXPECT_NOT_POISONED(*envp); | |
1349 | EXPECT_NOT_POISONED(*envp[0]); | |
1350 | } | |
1351 | } | |
1352 | ||
1353 | TEST(MemorySanitizer, putenv) { | |
1354 | char s[] = "AAA=BBB"; | |
1355 | putenv(s); | |
1356 | for (char **envp = environ; *envp; ++envp) { | |
1357 | EXPECT_NOT_POISONED(*envp); | |
1358 | EXPECT_NOT_POISONED(*envp[0]); | |
1359 | } | |
1360 | } | |
1361 | ||
1362 | TEST(MemorySanitizer, memcpy) { | |
1363 | char* x = new char[2]; | |
1364 | char* y = new char[2]; | |
1365 | x[0] = 1; | |
1366 | x[1] = *GetPoisoned<char>(); | |
1367 | memcpy(y, x, 2); | |
1368 | EXPECT_NOT_POISONED(y[0]); | |
1369 | EXPECT_POISONED(y[1]); | |
1370 | } | |
1371 | ||
92a42be0 SL |
1372 | void TestUnalignedMemcpy(unsigned left, unsigned right, bool src_is_aligned, |
1373 | bool src_is_poisoned, bool dst_is_poisoned) { | |
1374 | fprintf(stderr, "%s(%d, %d, %d, %d, %d)\n", __func__, left, right, | |
1375 | src_is_aligned, src_is_poisoned, dst_is_poisoned); | |
1376 | ||
1377 | const unsigned sz = 20; | |
1378 | U4 dst_origin, src_origin; | |
1a4d82fc | 1379 | char *dst = (char *)malloc(sz); |
92a42be0 SL |
1380 | if (dst_is_poisoned) |
1381 | dst_origin = __msan_get_origin(dst); | |
1382 | else | |
1383 | memset(dst, 0, sz); | |
1a4d82fc JJ |
1384 | |
1385 | char *src = (char *)malloc(sz); | |
92a42be0 SL |
1386 | if (src_is_poisoned) |
1387 | src_origin = __msan_get_origin(src); | |
1388 | else | |
1389 | memset(src, 0, sz); | |
1a4d82fc JJ |
1390 | |
1391 | memcpy(dst + left, src_is_aligned ? src + left : src, sz - left - right); | |
92a42be0 SL |
1392 | |
1393 | for (unsigned i = 0; i < (left & (~3U)); ++i) | |
1394 | if (dst_is_poisoned) | |
1395 | EXPECT_POISONED_O(dst[i], dst_origin); | |
1396 | else | |
1397 | EXPECT_NOT_POISONED(dst[i]); | |
1398 | ||
1399 | for (unsigned i = 0; i < (right & (~3U)); ++i) | |
1400 | if (dst_is_poisoned) | |
1401 | EXPECT_POISONED_O(dst[sz - i - 1], dst_origin); | |
1402 | else | |
1403 | EXPECT_NOT_POISONED(dst[sz - i - 1]); | |
1404 | ||
1405 | for (unsigned i = left; i < sz - right; ++i) | |
1406 | if (src_is_poisoned) | |
1407 | EXPECT_POISONED_O(dst[i], src_origin); | |
1408 | else | |
1409 | EXPECT_NOT_POISONED(dst[i]); | |
1a4d82fc JJ |
1410 | |
1411 | free(dst); | |
1412 | free(src); | |
1413 | } | |
1414 | ||
1415 | TEST(MemorySanitizer, memcpy_unaligned) { | |
92a42be0 SL |
1416 | for (int i = 0; i < 10; ++i) |
1417 | for (int j = 0; j < 10; ++j) | |
1418 | for (int aligned = 0; aligned < 2; ++aligned) | |
1419 | for (int srcp = 0; srcp < 2; ++srcp) | |
1420 | for (int dstp = 0; dstp < 2; ++dstp) | |
1421 | TestUnalignedMemcpy(i, j, aligned, srcp, dstp); | |
1a4d82fc JJ |
1422 | } |
1423 | ||
1424 | TEST(MemorySanitizer, memmove) { | |
1425 | char* x = new char[2]; | |
1426 | char* y = new char[2]; | |
1427 | x[0] = 1; | |
1428 | x[1] = *GetPoisoned<char>(); | |
1429 | memmove(y, x, 2); | |
1430 | EXPECT_NOT_POISONED(y[0]); | |
1431 | EXPECT_POISONED(y[1]); | |
1432 | } | |
1433 | ||
1434 | TEST(MemorySanitizer, memccpy_nomatch) { | |
1435 | char* x = new char[5]; | |
1436 | char* y = new char[5]; | |
1437 | strcpy(x, "abc"); | |
1438 | memccpy(y, x, 'd', 4); | |
1439 | EXPECT_NOT_POISONED(y[0]); | |
1440 | EXPECT_NOT_POISONED(y[1]); | |
1441 | EXPECT_NOT_POISONED(y[2]); | |
1442 | EXPECT_NOT_POISONED(y[3]); | |
1443 | EXPECT_POISONED(y[4]); | |
1444 | delete[] x; | |
1445 | delete[] y; | |
1446 | } | |
1447 | ||
1448 | TEST(MemorySanitizer, memccpy_match) { | |
1449 | char* x = new char[5]; | |
1450 | char* y = new char[5]; | |
1451 | strcpy(x, "abc"); | |
1452 | memccpy(y, x, 'b', 4); | |
1453 | EXPECT_NOT_POISONED(y[0]); | |
1454 | EXPECT_NOT_POISONED(y[1]); | |
1455 | EXPECT_POISONED(y[2]); | |
1456 | EXPECT_POISONED(y[3]); | |
1457 | EXPECT_POISONED(y[4]); | |
1458 | delete[] x; | |
1459 | delete[] y; | |
1460 | } | |
1461 | ||
1462 | TEST(MemorySanitizer, memccpy_nomatch_positive) { | |
1463 | char* x = new char[5]; | |
1464 | char* y = new char[5]; | |
1465 | strcpy(x, "abc"); | |
1466 | EXPECT_UMR(memccpy(y, x, 'd', 5)); | |
1467 | delete[] x; | |
1468 | delete[] y; | |
1469 | } | |
1470 | ||
1471 | TEST(MemorySanitizer, memccpy_match_positive) { | |
1472 | char* x = new char[5]; | |
1473 | char* y = new char[5]; | |
1474 | x[0] = 'a'; | |
1475 | x[2] = 'b'; | |
1476 | EXPECT_UMR(memccpy(y, x, 'b', 5)); | |
1477 | delete[] x; | |
1478 | delete[] y; | |
1479 | } | |
1480 | ||
1481 | TEST(MemorySanitizer, bcopy) { | |
1482 | char* x = new char[2]; | |
1483 | char* y = new char[2]; | |
1484 | x[0] = 1; | |
1485 | x[1] = *GetPoisoned<char>(); | |
1486 | bcopy(x, y, 2); | |
1487 | EXPECT_NOT_POISONED(y[0]); | |
1488 | EXPECT_POISONED(y[1]); | |
1489 | } | |
1490 | ||
1491 | TEST(MemorySanitizer, strdup) { | |
1492 | char buf[4] = "abc"; | |
1493 | __msan_poison(buf + 2, sizeof(*buf)); | |
1494 | char *x = strdup(buf); | |
1495 | EXPECT_NOT_POISONED(x[0]); | |
1496 | EXPECT_NOT_POISONED(x[1]); | |
1497 | EXPECT_POISONED(x[2]); | |
1498 | EXPECT_NOT_POISONED(x[3]); | |
1499 | free(x); | |
1500 | } | |
1501 | ||
1502 | TEST(MemorySanitizer, strndup) { | |
1503 | char buf[4] = "abc"; | |
1504 | __msan_poison(buf + 2, sizeof(*buf)); | |
1505 | char *x = strndup(buf, 3); | |
1506 | EXPECT_NOT_POISONED(x[0]); | |
1507 | EXPECT_NOT_POISONED(x[1]); | |
1508 | EXPECT_POISONED(x[2]); | |
1509 | EXPECT_NOT_POISONED(x[3]); | |
1510 | free(x); | |
1511 | } | |
1512 | ||
1513 | TEST(MemorySanitizer, strndup_short) { | |
1514 | char buf[4] = "abc"; | |
1515 | __msan_poison(buf + 1, sizeof(*buf)); | |
1516 | __msan_poison(buf + 2, sizeof(*buf)); | |
1517 | char *x = strndup(buf, 2); | |
1518 | EXPECT_NOT_POISONED(x[0]); | |
1519 | EXPECT_POISONED(x[1]); | |
1520 | EXPECT_NOT_POISONED(x[2]); | |
1521 | free(x); | |
1522 | } | |
1523 | ||
1524 | ||
1525 | template<class T, int size> | |
1526 | void TestOverlapMemmove() { | |
1527 | T *x = new T[size]; | |
1528 | ASSERT_GE(size, 3); | |
1529 | x[2] = 0; | |
1530 | memmove(x, x + 1, (size - 1) * sizeof(T)); | |
1531 | EXPECT_NOT_POISONED(x[1]); | |
92a42be0 SL |
1532 | EXPECT_POISONED(x[0]); |
1533 | EXPECT_POISONED(x[2]); | |
1a4d82fc JJ |
1534 | delete [] x; |
1535 | } | |
1536 | ||
1537 | TEST(MemorySanitizer, overlap_memmove) { | |
1538 | TestOverlapMemmove<U1, 10>(); | |
1539 | TestOverlapMemmove<U1, 1000>(); | |
1540 | TestOverlapMemmove<U8, 4>(); | |
1541 | TestOverlapMemmove<U8, 1000>(); | |
1542 | } | |
1543 | ||
1544 | TEST(MemorySanitizer, strcpy) { // NOLINT | |
1545 | char* x = new char[3]; | |
1546 | char* y = new char[3]; | |
1547 | x[0] = 'a'; | |
1548 | x[1] = *GetPoisoned<char>(1, 1); | |
1549 | x[2] = 0; | |
1550 | strcpy(y, x); // NOLINT | |
1551 | EXPECT_NOT_POISONED(y[0]); | |
1552 | EXPECT_POISONED(y[1]); | |
1553 | EXPECT_NOT_POISONED(y[2]); | |
1554 | } | |
1555 | ||
1556 | TEST(MemorySanitizer, strncpy) { // NOLINT | |
1557 | char* x = new char[3]; | |
92a42be0 | 1558 | char* y = new char[5]; |
1a4d82fc JJ |
1559 | x[0] = 'a'; |
1560 | x[1] = *GetPoisoned<char>(1, 1); | |
92a42be0 SL |
1561 | x[2] = '\0'; |
1562 | strncpy(y, x, 4); // NOLINT | |
1a4d82fc JJ |
1563 | EXPECT_NOT_POISONED(y[0]); |
1564 | EXPECT_POISONED(y[1]); | |
92a42be0 SL |
1565 | EXPECT_NOT_POISONED(y[2]); |
1566 | EXPECT_NOT_POISONED(y[3]); | |
1567 | EXPECT_POISONED(y[4]); | |
1a4d82fc JJ |
1568 | } |
1569 | ||
1570 | TEST(MemorySanitizer, stpcpy) { // NOLINT | |
1571 | char* x = new char[3]; | |
1572 | char* y = new char[3]; | |
1573 | x[0] = 'a'; | |
1574 | x[1] = *GetPoisoned<char>(1, 1); | |
1575 | x[2] = 0; | |
1576 | char *res = stpcpy(y, x); // NOLINT | |
1577 | ASSERT_EQ(res, y + 2); | |
1578 | EXPECT_NOT_POISONED(y[0]); | |
1579 | EXPECT_POISONED(y[1]); | |
1580 | EXPECT_NOT_POISONED(y[2]); | |
1581 | } | |
1582 | ||
1583 | TEST(MemorySanitizer, strcat) { // NOLINT | |
1584 | char a[10]; | |
1585 | char b[] = "def"; | |
1586 | strcpy(a, "abc"); | |
1587 | __msan_poison(b + 1, 1); | |
1588 | strcat(a, b); | |
1589 | EXPECT_NOT_POISONED(a[3]); | |
1590 | EXPECT_POISONED(a[4]); | |
1591 | EXPECT_NOT_POISONED(a[5]); | |
1592 | EXPECT_NOT_POISONED(a[6]); | |
1593 | EXPECT_POISONED(a[7]); | |
1594 | } | |
1595 | ||
1596 | TEST(MemorySanitizer, strncat) { // NOLINT | |
1597 | char a[10]; | |
1598 | char b[] = "def"; | |
1599 | strcpy(a, "abc"); | |
1600 | __msan_poison(b + 1, 1); | |
1601 | strncat(a, b, 5); | |
1602 | EXPECT_NOT_POISONED(a[3]); | |
1603 | EXPECT_POISONED(a[4]); | |
1604 | EXPECT_NOT_POISONED(a[5]); | |
1605 | EXPECT_NOT_POISONED(a[6]); | |
1606 | EXPECT_POISONED(a[7]); | |
1607 | } | |
1608 | ||
1609 | TEST(MemorySanitizer, strncat_overflow) { // NOLINT | |
1610 | char a[10]; | |
1611 | char b[] = "def"; | |
1612 | strcpy(a, "abc"); | |
1613 | __msan_poison(b + 1, 1); | |
1614 | strncat(a, b, 2); | |
1615 | EXPECT_NOT_POISONED(a[3]); | |
1616 | EXPECT_POISONED(a[4]); | |
1617 | EXPECT_NOT_POISONED(a[5]); | |
1618 | EXPECT_POISONED(a[6]); | |
1619 | EXPECT_POISONED(a[7]); | |
1620 | } | |
1621 | ||
92a42be0 SL |
1622 | #define TEST_STRTO_INT(func_name, char_type, str_prefix) \ |
1623 | TEST(MemorySanitizer, func_name) { \ | |
1624 | char_type *e; \ | |
1625 | EXPECT_EQ(1U, func_name(str_prefix##"1", &e, 10)); \ | |
1626 | EXPECT_NOT_POISONED((S8)e); \ | |
1a4d82fc JJ |
1627 | } |
1628 | ||
92a42be0 SL |
1629 | #define TEST_STRTO_FLOAT(func_name, char_type, str_prefix) \ |
1630 | TEST(MemorySanitizer, func_name) { \ | |
1631 | char_type *e; \ | |
1632 | EXPECT_NE(0, func_name(str_prefix##"1.5", &e)); \ | |
1633 | EXPECT_NOT_POISONED((S8)e); \ | |
1a4d82fc JJ |
1634 | } |
1635 | ||
92a42be0 | 1636 | #define TEST_STRTO_FLOAT_LOC(func_name, char_type, str_prefix) \ |
1a4d82fc JJ |
1637 | TEST(MemorySanitizer, func_name) { \ |
1638 | locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); \ | |
92a42be0 SL |
1639 | char_type *e; \ |
1640 | EXPECT_NE(0, func_name(str_prefix##"1.5", &e, loc)); \ | |
1a4d82fc JJ |
1641 | EXPECT_NOT_POISONED((S8)e); \ |
1642 | freelocale(loc); \ | |
1643 | } | |
1644 | ||
92a42be0 | 1645 | #define TEST_STRTO_INT_LOC(func_name, char_type, str_prefix) \ |
1a4d82fc JJ |
1646 | TEST(MemorySanitizer, func_name) { \ |
1647 | locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); \ | |
92a42be0 SL |
1648 | char_type *e; \ |
1649 | ASSERT_EQ(1U, func_name(str_prefix##"1", &e, 10, loc)); \ | |
1a4d82fc JJ |
1650 | EXPECT_NOT_POISONED((S8)e); \ |
1651 | freelocale(loc); \ | |
1652 | } | |
1653 | ||
92a42be0 SL |
1654 | TEST_STRTO_INT(strtol, char, ) |
1655 | TEST_STRTO_INT(strtoll, char, ) | |
1656 | TEST_STRTO_INT(strtoul, char, ) | |
1657 | TEST_STRTO_INT(strtoull, char, ) | |
1658 | ||
1659 | TEST_STRTO_FLOAT(strtof, char, ) | |
1660 | TEST_STRTO_FLOAT(strtod, char, ) | |
1661 | TEST_STRTO_FLOAT(strtold, char, ) | |
1662 | ||
1663 | TEST_STRTO_FLOAT_LOC(strtof_l, char, ) | |
1664 | TEST_STRTO_FLOAT_LOC(strtod_l, char, ) | |
1665 | TEST_STRTO_FLOAT_LOC(strtold_l, char, ) | |
1666 | ||
1667 | TEST_STRTO_INT_LOC(strtol_l, char, ) | |
1668 | TEST_STRTO_INT_LOC(strtoll_l, char, ) | |
1669 | TEST_STRTO_INT_LOC(strtoul_l, char, ) | |
1670 | TEST_STRTO_INT_LOC(strtoull_l, char, ) | |
1671 | ||
1672 | TEST_STRTO_INT(wcstol, wchar_t, L) | |
1673 | TEST_STRTO_INT(wcstoll, wchar_t, L) | |
1674 | TEST_STRTO_INT(wcstoul, wchar_t, L) | |
1675 | TEST_STRTO_INT(wcstoull, wchar_t, L) | |
1a4d82fc | 1676 | |
92a42be0 SL |
1677 | TEST_STRTO_FLOAT(wcstof, wchar_t, L) |
1678 | TEST_STRTO_FLOAT(wcstod, wchar_t, L) | |
1679 | TEST_STRTO_FLOAT(wcstold, wchar_t, L) | |
1a4d82fc | 1680 | |
92a42be0 SL |
1681 | TEST_STRTO_FLOAT_LOC(wcstof_l, wchar_t, L) |
1682 | TEST_STRTO_FLOAT_LOC(wcstod_l, wchar_t, L) | |
1683 | TEST_STRTO_FLOAT_LOC(wcstold_l, wchar_t, L) | |
1a4d82fc | 1684 | |
92a42be0 SL |
1685 | TEST_STRTO_INT_LOC(wcstol_l, wchar_t, L) |
1686 | TEST_STRTO_INT_LOC(wcstoll_l, wchar_t, L) | |
1687 | TEST_STRTO_INT_LOC(wcstoul_l, wchar_t, L) | |
1688 | TEST_STRTO_INT_LOC(wcstoull_l, wchar_t, L) | |
1a4d82fc | 1689 | |
92a42be0 SL |
1690 | |
1691 | TEST(MemorySanitizer, strtoimax) { | |
1a4d82fc JJ |
1692 | char *e; |
1693 | ASSERT_EQ(1, strtoimax("1", &e, 10)); | |
1694 | EXPECT_NOT_POISONED((S8) e); | |
1695 | } | |
1696 | ||
92a42be0 | 1697 | TEST(MemorySanitizer, strtoumax) { |
1a4d82fc JJ |
1698 | char *e; |
1699 | ASSERT_EQ(1U, strtoumax("1", &e, 10)); | |
1700 | EXPECT_NOT_POISONED((S8) e); | |
1701 | } | |
1702 | ||
1703 | #ifdef __GLIBC__ | |
1704 | extern "C" float __strtof_l(const char *nptr, char **endptr, locale_t loc); | |
92a42be0 | 1705 | TEST_STRTO_FLOAT_LOC(__strtof_l, char, ) |
1a4d82fc | 1706 | extern "C" double __strtod_l(const char *nptr, char **endptr, locale_t loc); |
92a42be0 | 1707 | TEST_STRTO_FLOAT_LOC(__strtod_l, char, ) |
1a4d82fc JJ |
1708 | extern "C" long double __strtold_l(const char *nptr, char **endptr, |
1709 | locale_t loc); | |
92a42be0 SL |
1710 | TEST_STRTO_FLOAT_LOC(__strtold_l, char, ) |
1711 | ||
1712 | extern "C" float __wcstof_l(const wchar_t *nptr, wchar_t **endptr, locale_t loc); | |
1713 | TEST_STRTO_FLOAT_LOC(__wcstof_l, wchar_t, L) | |
1714 | extern "C" double __wcstod_l(const wchar_t *nptr, wchar_t **endptr, locale_t loc); | |
1715 | TEST_STRTO_FLOAT_LOC(__wcstod_l, wchar_t, L) | |
1716 | extern "C" long double __wcstold_l(const wchar_t *nptr, wchar_t **endptr, | |
1717 | locale_t loc); | |
1718 | TEST_STRTO_FLOAT_LOC(__wcstold_l, wchar_t, L) | |
1a4d82fc JJ |
1719 | #endif // __GLIBC__ |
1720 | ||
1721 | TEST(MemorySanitizer, modf) { | |
1722 | double x, y; | |
1723 | x = modf(2.1, &y); | |
1724 | EXPECT_NOT_POISONED(y); | |
1725 | } | |
1726 | ||
1727 | TEST(MemorySanitizer, modff) { | |
1728 | float x, y; | |
1729 | x = modff(2.1, &y); | |
1730 | EXPECT_NOT_POISONED(y); | |
1731 | } | |
1732 | ||
1733 | TEST(MemorySanitizer, modfl) { | |
1734 | long double x, y; | |
1735 | x = modfl(2.1, &y); | |
1736 | EXPECT_NOT_POISONED(y); | |
1737 | } | |
1738 | ||
92a42be0 SL |
1739 | // There's no sincos() on FreeBSD. |
1740 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1741 | TEST(MemorySanitizer, sincos) { |
1742 | double s, c; | |
1743 | sincos(0.2, &s, &c); | |
1744 | EXPECT_NOT_POISONED(s); | |
1745 | EXPECT_NOT_POISONED(c); | |
1746 | } | |
92a42be0 | 1747 | #endif |
1a4d82fc | 1748 | |
92a42be0 SL |
1749 | // There's no sincosf() on FreeBSD. |
1750 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1751 | TEST(MemorySanitizer, sincosf) { |
1752 | float s, c; | |
1753 | sincosf(0.2, &s, &c); | |
1754 | EXPECT_NOT_POISONED(s); | |
1755 | EXPECT_NOT_POISONED(c); | |
1756 | } | |
92a42be0 | 1757 | #endif |
1a4d82fc | 1758 | |
92a42be0 SL |
1759 | // There's no sincosl() on FreeBSD. |
1760 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1761 | TEST(MemorySanitizer, sincosl) { |
1762 | long double s, c; | |
1763 | sincosl(0.2, &s, &c); | |
1764 | EXPECT_NOT_POISONED(s); | |
1765 | EXPECT_NOT_POISONED(c); | |
1766 | } | |
92a42be0 | 1767 | #endif |
1a4d82fc JJ |
1768 | |
1769 | TEST(MemorySanitizer, remquo) { | |
1770 | int quo; | |
1771 | double res = remquo(29.0, 3.0, &quo); | |
1772 | ASSERT_NE(0.0, res); | |
1773 | EXPECT_NOT_POISONED(quo); | |
1774 | } | |
1775 | ||
1776 | TEST(MemorySanitizer, remquof) { | |
1777 | int quo; | |
1778 | float res = remquof(29.0, 3.0, &quo); | |
1779 | ASSERT_NE(0.0, res); | |
1780 | EXPECT_NOT_POISONED(quo); | |
1781 | } | |
1782 | ||
1783 | TEST(MemorySanitizer, remquol) { | |
1784 | int quo; | |
1785 | long double res = remquof(29.0, 3.0, &quo); | |
1786 | ASSERT_NE(0.0, res); | |
1787 | EXPECT_NOT_POISONED(quo); | |
1788 | } | |
1789 | ||
1790 | TEST(MemorySanitizer, lgamma) { | |
1791 | double res = lgamma(1.1); | |
1792 | ASSERT_NE(0.0, res); | |
1793 | EXPECT_NOT_POISONED(signgam); | |
1794 | } | |
1795 | ||
1796 | TEST(MemorySanitizer, lgammaf) { | |
1797 | float res = lgammaf(1.1); | |
1798 | ASSERT_NE(0.0, res); | |
1799 | EXPECT_NOT_POISONED(signgam); | |
1800 | } | |
1801 | ||
1802 | TEST(MemorySanitizer, lgammal) { | |
1803 | long double res = lgammal(1.1); | |
1804 | ASSERT_NE(0.0, res); | |
1805 | EXPECT_NOT_POISONED(signgam); | |
1806 | } | |
1807 | ||
1808 | TEST(MemorySanitizer, lgamma_r) { | |
1809 | int sgn; | |
1810 | double res = lgamma_r(1.1, &sgn); | |
1811 | ASSERT_NE(0.0, res); | |
1812 | EXPECT_NOT_POISONED(sgn); | |
1813 | } | |
1814 | ||
1815 | TEST(MemorySanitizer, lgammaf_r) { | |
1816 | int sgn; | |
1817 | float res = lgammaf_r(1.1, &sgn); | |
1818 | ASSERT_NE(0.0, res); | |
1819 | EXPECT_NOT_POISONED(sgn); | |
1820 | } | |
1821 | ||
92a42be0 SL |
1822 | // There's no lgammal_r() on FreeBSD. |
1823 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1824 | TEST(MemorySanitizer, lgammal_r) { |
1825 | int sgn; | |
1826 | long double res = lgammal_r(1.1, &sgn); | |
1827 | ASSERT_NE(0.0, res); | |
1828 | EXPECT_NOT_POISONED(sgn); | |
1829 | } | |
92a42be0 | 1830 | #endif |
1a4d82fc | 1831 | |
92a42be0 SL |
1832 | // There's no drand48_r() on FreeBSD. |
1833 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1834 | TEST(MemorySanitizer, drand48_r) { |
1835 | struct drand48_data buf; | |
1836 | srand48_r(0, &buf); | |
1837 | double d; | |
1838 | drand48_r(&buf, &d); | |
1839 | EXPECT_NOT_POISONED(d); | |
1840 | } | |
92a42be0 | 1841 | #endif |
1a4d82fc | 1842 | |
92a42be0 SL |
1843 | // There's no lrand48_r() on FreeBSD. |
1844 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
1845 | TEST(MemorySanitizer, lrand48_r) { |
1846 | struct drand48_data buf; | |
1847 | srand48_r(0, &buf); | |
1848 | long d; | |
1849 | lrand48_r(&buf, &d); | |
1850 | EXPECT_NOT_POISONED(d); | |
1851 | } | |
92a42be0 | 1852 | #endif |
1a4d82fc JJ |
1853 | |
1854 | TEST(MemorySanitizer, sprintf) { // NOLINT | |
1855 | char buff[10]; | |
1856 | break_optimization(buff); | |
1857 | EXPECT_POISONED(buff[0]); | |
1858 | int res = sprintf(buff, "%d", 1234567); // NOLINT | |
1859 | ASSERT_EQ(res, 7); | |
1860 | ASSERT_EQ(buff[0], '1'); | |
1861 | ASSERT_EQ(buff[1], '2'); | |
1862 | ASSERT_EQ(buff[2], '3'); | |
1863 | ASSERT_EQ(buff[6], '7'); | |
1864 | ASSERT_EQ(buff[7], 0); | |
1865 | EXPECT_POISONED(buff[8]); | |
1866 | } | |
1867 | ||
1868 | TEST(MemorySanitizer, snprintf) { | |
1869 | char buff[10]; | |
1870 | break_optimization(buff); | |
1871 | EXPECT_POISONED(buff[0]); | |
1872 | int res = snprintf(buff, sizeof(buff), "%d", 1234567); | |
1873 | ASSERT_EQ(res, 7); | |
1874 | ASSERT_EQ(buff[0], '1'); | |
1875 | ASSERT_EQ(buff[1], '2'); | |
1876 | ASSERT_EQ(buff[2], '3'); | |
1877 | ASSERT_EQ(buff[6], '7'); | |
1878 | ASSERT_EQ(buff[7], 0); | |
1879 | EXPECT_POISONED(buff[8]); | |
1880 | } | |
1881 | ||
1882 | TEST(MemorySanitizer, swprintf) { | |
1883 | wchar_t buff[10]; | |
1884 | ASSERT_EQ(4U, sizeof(wchar_t)); | |
1885 | break_optimization(buff); | |
1886 | EXPECT_POISONED(buff[0]); | |
1887 | int res = swprintf(buff, 9, L"%d", 1234567); | |
1888 | ASSERT_EQ(res, 7); | |
1889 | ASSERT_EQ(buff[0], '1'); | |
1890 | ASSERT_EQ(buff[1], '2'); | |
1891 | ASSERT_EQ(buff[2], '3'); | |
1892 | ASSERT_EQ(buff[6], '7'); | |
3157f602 | 1893 | ASSERT_EQ(buff[7], L'\0'); |
1a4d82fc JJ |
1894 | EXPECT_POISONED(buff[8]); |
1895 | } | |
1896 | ||
1897 | TEST(MemorySanitizer, asprintf) { // NOLINT | |
1898 | char *pbuf; | |
1899 | EXPECT_POISONED(pbuf); | |
1900 | int res = asprintf(&pbuf, "%d", 1234567); // NOLINT | |
1901 | ASSERT_EQ(res, 7); | |
1902 | EXPECT_NOT_POISONED(pbuf); | |
1903 | ASSERT_EQ(pbuf[0], '1'); | |
1904 | ASSERT_EQ(pbuf[1], '2'); | |
1905 | ASSERT_EQ(pbuf[2], '3'); | |
1906 | ASSERT_EQ(pbuf[6], '7'); | |
1907 | ASSERT_EQ(pbuf[7], 0); | |
1908 | free(pbuf); | |
1909 | } | |
1910 | ||
1911 | TEST(MemorySanitizer, mbstowcs) { | |
1912 | const char *x = "abc"; | |
1913 | wchar_t buff[10]; | |
1914 | int res = mbstowcs(buff, x, 2); | |
1915 | EXPECT_EQ(2, res); | |
1916 | EXPECT_EQ(L'a', buff[0]); | |
1917 | EXPECT_EQ(L'b', buff[1]); | |
1918 | EXPECT_POISONED(buff[2]); | |
1919 | res = mbstowcs(buff, x, 10); | |
1920 | EXPECT_EQ(3, res); | |
1921 | EXPECT_NOT_POISONED(buff[3]); | |
1922 | } | |
1923 | ||
1924 | TEST(MemorySanitizer, wcstombs) { | |
1925 | const wchar_t *x = L"abc"; | |
1926 | char buff[10]; | |
1927 | int res = wcstombs(buff, x, 4); | |
1928 | EXPECT_EQ(res, 3); | |
1929 | EXPECT_EQ(buff[0], 'a'); | |
1930 | EXPECT_EQ(buff[1], 'b'); | |
1931 | EXPECT_EQ(buff[2], 'c'); | |
1932 | } | |
1933 | ||
1934 | TEST(MemorySanitizer, wcsrtombs) { | |
1935 | const wchar_t *x = L"abc"; | |
1936 | const wchar_t *p = x; | |
1937 | char buff[10]; | |
1938 | mbstate_t mbs; | |
1939 | memset(&mbs, 0, sizeof(mbs)); | |
1940 | int res = wcsrtombs(buff, &p, 4, &mbs); | |
1941 | EXPECT_EQ(res, 3); | |
1942 | EXPECT_EQ(buff[0], 'a'); | |
1943 | EXPECT_EQ(buff[1], 'b'); | |
1944 | EXPECT_EQ(buff[2], 'c'); | |
1945 | EXPECT_EQ(buff[3], '\0'); | |
1946 | EXPECT_POISONED(buff[4]); | |
1947 | } | |
1948 | ||
1949 | TEST(MemorySanitizer, wcsnrtombs) { | |
1950 | const wchar_t *x = L"abc"; | |
1951 | const wchar_t *p = x; | |
1952 | char buff[10]; | |
1953 | mbstate_t mbs; | |
1954 | memset(&mbs, 0, sizeof(mbs)); | |
1955 | int res = wcsnrtombs(buff, &p, 2, 4, &mbs); | |
1956 | EXPECT_EQ(res, 2); | |
1957 | EXPECT_EQ(buff[0], 'a'); | |
1958 | EXPECT_EQ(buff[1], 'b'); | |
1959 | EXPECT_POISONED(buff[2]); | |
1960 | } | |
1961 | ||
92a42be0 SL |
1962 | TEST(MemorySanitizer, wcrtomb) { |
1963 | wchar_t x = L'a'; | |
1964 | char buff[10]; | |
1965 | mbstate_t mbs; | |
1966 | memset(&mbs, 0, sizeof(mbs)); | |
1967 | size_t res = wcrtomb(buff, x, &mbs); | |
1968 | EXPECT_EQ(res, (size_t)1); | |
1969 | EXPECT_EQ(buff[0], 'a'); | |
1970 | } | |
1971 | ||
1972 | TEST(MemorySanitizer, wmemset) { | |
1973 | wchar_t x[25]; | |
1974 | break_optimization(x); | |
1975 | EXPECT_POISONED(x[0]); | |
1976 | wmemset(x, L'A', 10); | |
1977 | EXPECT_EQ(x[0], L'A'); | |
1978 | EXPECT_EQ(x[9], L'A'); | |
1979 | EXPECT_POISONED(x[10]); | |
1980 | } | |
1981 | ||
1a4d82fc JJ |
1982 | TEST(MemorySanitizer, mbtowc) { |
1983 | const char *x = "abc"; | |
1984 | wchar_t wx; | |
1985 | int res = mbtowc(&wx, x, 3); | |
1986 | EXPECT_GT(res, 0); | |
1987 | EXPECT_NOT_POISONED(wx); | |
1988 | } | |
1989 | ||
1990 | TEST(MemorySanitizer, mbrtowc) { | |
1991 | const char *x = "abc"; | |
1992 | wchar_t wx; | |
1993 | mbstate_t mbs; | |
1994 | memset(&mbs, 0, sizeof(mbs)); | |
1995 | int res = mbrtowc(&wx, x, 3, &mbs); | |
1996 | EXPECT_GT(res, 0); | |
1997 | EXPECT_NOT_POISONED(wx); | |
1998 | } | |
1999 | ||
2000 | TEST(MemorySanitizer, wcsftime) { | |
2001 | wchar_t x[100]; | |
2002 | time_t t = time(NULL); | |
2003 | struct tm tms; | |
2004 | struct tm *tmres = localtime_r(&t, &tms); | |
2005 | ASSERT_NE((void *)0, tmres); | |
2006 | size_t res = wcsftime(x, sizeof(x) / sizeof(x[0]), L"%Y-%m-%d", tmres); | |
2007 | EXPECT_GT(res, 0UL); | |
2008 | EXPECT_EQ(res, wcslen(x)); | |
2009 | } | |
2010 | ||
2011 | TEST(MemorySanitizer, gettimeofday) { | |
2012 | struct timeval tv; | |
2013 | struct timezone tz; | |
2014 | break_optimization(&tv); | |
2015 | break_optimization(&tz); | |
2016 | ASSERT_EQ(16U, sizeof(tv)); | |
2017 | ASSERT_EQ(8U, sizeof(tz)); | |
2018 | EXPECT_POISONED(tv.tv_sec); | |
2019 | EXPECT_POISONED(tv.tv_usec); | |
2020 | EXPECT_POISONED(tz.tz_minuteswest); | |
2021 | EXPECT_POISONED(tz.tz_dsttime); | |
2022 | ASSERT_EQ(0, gettimeofday(&tv, &tz)); | |
2023 | EXPECT_NOT_POISONED(tv.tv_sec); | |
2024 | EXPECT_NOT_POISONED(tv.tv_usec); | |
2025 | EXPECT_NOT_POISONED(tz.tz_minuteswest); | |
2026 | EXPECT_NOT_POISONED(tz.tz_dsttime); | |
2027 | } | |
2028 | ||
2029 | TEST(MemorySanitizer, clock_gettime) { | |
2030 | struct timespec tp; | |
2031 | EXPECT_POISONED(tp.tv_sec); | |
2032 | EXPECT_POISONED(tp.tv_nsec); | |
2033 | ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp)); | |
2034 | EXPECT_NOT_POISONED(tp.tv_sec); | |
2035 | EXPECT_NOT_POISONED(tp.tv_nsec); | |
2036 | } | |
2037 | ||
2038 | TEST(MemorySanitizer, clock_getres) { | |
2039 | struct timespec tp; | |
2040 | EXPECT_POISONED(tp.tv_sec); | |
2041 | EXPECT_POISONED(tp.tv_nsec); | |
2042 | ASSERT_EQ(0, clock_getres(CLOCK_REALTIME, 0)); | |
2043 | EXPECT_POISONED(tp.tv_sec); | |
2044 | EXPECT_POISONED(tp.tv_nsec); | |
2045 | ASSERT_EQ(0, clock_getres(CLOCK_REALTIME, &tp)); | |
2046 | EXPECT_NOT_POISONED(tp.tv_sec); | |
2047 | EXPECT_NOT_POISONED(tp.tv_nsec); | |
2048 | } | |
2049 | ||
2050 | TEST(MemorySanitizer, getitimer) { | |
2051 | struct itimerval it1, it2; | |
2052 | int res; | |
2053 | EXPECT_POISONED(it1.it_interval.tv_sec); | |
2054 | EXPECT_POISONED(it1.it_interval.tv_usec); | |
2055 | EXPECT_POISONED(it1.it_value.tv_sec); | |
2056 | EXPECT_POISONED(it1.it_value.tv_usec); | |
2057 | res = getitimer(ITIMER_VIRTUAL, &it1); | |
2058 | ASSERT_EQ(0, res); | |
2059 | EXPECT_NOT_POISONED(it1.it_interval.tv_sec); | |
2060 | EXPECT_NOT_POISONED(it1.it_interval.tv_usec); | |
2061 | EXPECT_NOT_POISONED(it1.it_value.tv_sec); | |
2062 | EXPECT_NOT_POISONED(it1.it_value.tv_usec); | |
2063 | ||
2064 | it1.it_interval.tv_sec = it1.it_value.tv_sec = 10000; | |
2065 | it1.it_interval.tv_usec = it1.it_value.tv_usec = 0; | |
2066 | ||
2067 | res = setitimer(ITIMER_VIRTUAL, &it1, &it2); | |
2068 | ASSERT_EQ(0, res); | |
2069 | EXPECT_NOT_POISONED(it2.it_interval.tv_sec); | |
2070 | EXPECT_NOT_POISONED(it2.it_interval.tv_usec); | |
2071 | EXPECT_NOT_POISONED(it2.it_value.tv_sec); | |
2072 | EXPECT_NOT_POISONED(it2.it_value.tv_usec); | |
2073 | ||
2074 | // Check that old_value can be 0, and disable the timer. | |
2075 | memset(&it1, 0, sizeof(it1)); | |
2076 | res = setitimer(ITIMER_VIRTUAL, &it1, 0); | |
2077 | ASSERT_EQ(0, res); | |
2078 | } | |
2079 | ||
2080 | TEST(MemorySanitizer, setitimer_null) { | |
2081 | setitimer(ITIMER_VIRTUAL, 0, 0); | |
2082 | // Not testing the return value, since it the behaviour seems to differ | |
2083 | // between libc implementations and POSIX. | |
2084 | // Should never crash, though. | |
2085 | } | |
2086 | ||
2087 | TEST(MemorySanitizer, time) { | |
2088 | time_t t; | |
2089 | EXPECT_POISONED(t); | |
2090 | time_t t2 = time(&t); | |
2091 | ASSERT_NE(t2, (time_t)-1); | |
2092 | EXPECT_NOT_POISONED(t); | |
2093 | } | |
2094 | ||
2095 | TEST(MemorySanitizer, strptime) { | |
2096 | struct tm time; | |
2097 | char *p = strptime("11/1/2013-05:39", "%m/%d/%Y-%H:%M", &time); | |
2098 | ASSERT_TRUE(p != NULL); | |
2099 | EXPECT_NOT_POISONED(time.tm_sec); | |
2100 | EXPECT_NOT_POISONED(time.tm_hour); | |
2101 | EXPECT_NOT_POISONED(time.tm_year); | |
2102 | } | |
2103 | ||
2104 | TEST(MemorySanitizer, localtime) { | |
2105 | time_t t = 123; | |
2106 | struct tm *time = localtime(&t); | |
2107 | ASSERT_TRUE(time != NULL); | |
2108 | EXPECT_NOT_POISONED(time->tm_sec); | |
2109 | EXPECT_NOT_POISONED(time->tm_hour); | |
2110 | EXPECT_NOT_POISONED(time->tm_year); | |
2111 | EXPECT_NOT_POISONED(time->tm_isdst); | |
2112 | EXPECT_NE(0U, strlen(time->tm_zone)); | |
2113 | } | |
2114 | ||
2115 | TEST(MemorySanitizer, localtime_r) { | |
2116 | time_t t = 123; | |
2117 | struct tm time; | |
2118 | struct tm *res = localtime_r(&t, &time); | |
2119 | ASSERT_TRUE(res != NULL); | |
2120 | EXPECT_NOT_POISONED(time.tm_sec); | |
2121 | EXPECT_NOT_POISONED(time.tm_hour); | |
2122 | EXPECT_NOT_POISONED(time.tm_year); | |
2123 | EXPECT_NOT_POISONED(time.tm_isdst); | |
2124 | EXPECT_NE(0U, strlen(time.tm_zone)); | |
2125 | } | |
2126 | ||
92a42be0 SL |
2127 | // There's no getmntent() on FreeBSD. |
2128 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
2129 | TEST(MemorySanitizer, getmntent) { |
2130 | FILE *fp = setmntent("/etc/fstab", "r"); | |
2131 | struct mntent *mnt = getmntent(fp); | |
2132 | ASSERT_TRUE(mnt != NULL); | |
2133 | ASSERT_NE(0U, strlen(mnt->mnt_fsname)); | |
2134 | ASSERT_NE(0U, strlen(mnt->mnt_dir)); | |
2135 | ASSERT_NE(0U, strlen(mnt->mnt_type)); | |
2136 | ASSERT_NE(0U, strlen(mnt->mnt_opts)); | |
2137 | EXPECT_NOT_POISONED(mnt->mnt_freq); | |
2138 | EXPECT_NOT_POISONED(mnt->mnt_passno); | |
2139 | fclose(fp); | |
2140 | } | |
92a42be0 | 2141 | #endif |
1a4d82fc | 2142 | |
92a42be0 SL |
2143 | // There's no getmntent_r() on FreeBSD. |
2144 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
2145 | TEST(MemorySanitizer, getmntent_r) { |
2146 | FILE *fp = setmntent("/etc/fstab", "r"); | |
2147 | struct mntent mntbuf; | |
2148 | char buf[1000]; | |
2149 | struct mntent *mnt = getmntent_r(fp, &mntbuf, buf, sizeof(buf)); | |
2150 | ASSERT_TRUE(mnt != NULL); | |
2151 | ASSERT_NE(0U, strlen(mnt->mnt_fsname)); | |
2152 | ASSERT_NE(0U, strlen(mnt->mnt_dir)); | |
2153 | ASSERT_NE(0U, strlen(mnt->mnt_type)); | |
2154 | ASSERT_NE(0U, strlen(mnt->mnt_opts)); | |
2155 | EXPECT_NOT_POISONED(mnt->mnt_freq); | |
2156 | EXPECT_NOT_POISONED(mnt->mnt_passno); | |
2157 | fclose(fp); | |
2158 | } | |
92a42be0 | 2159 | #endif |
1a4d82fc JJ |
2160 | |
2161 | TEST(MemorySanitizer, ether) { | |
2162 | const char *asc = "11:22:33:44:55:66"; | |
2163 | struct ether_addr *paddr = ether_aton(asc); | |
2164 | EXPECT_NOT_POISONED(*paddr); | |
2165 | ||
2166 | struct ether_addr addr; | |
2167 | paddr = ether_aton_r(asc, &addr); | |
2168 | ASSERT_EQ(paddr, &addr); | |
2169 | EXPECT_NOT_POISONED(addr); | |
2170 | ||
2171 | char *s = ether_ntoa(&addr); | |
2172 | ASSERT_NE(0U, strlen(s)); | |
2173 | ||
2174 | char buf[100]; | |
2175 | s = ether_ntoa_r(&addr, buf); | |
2176 | ASSERT_EQ(s, buf); | |
2177 | ASSERT_NE(0U, strlen(buf)); | |
2178 | } | |
2179 | ||
2180 | TEST(MemorySanitizer, mmap) { | |
2181 | const int size = 4096; | |
2182 | void *p1, *p2; | |
2183 | p1 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); | |
2184 | __msan_poison(p1, size); | |
2185 | munmap(p1, size); | |
2186 | for (int i = 0; i < 1000; i++) { | |
2187 | p2 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); | |
2188 | if (p2 == p1) | |
2189 | break; | |
2190 | else | |
2191 | munmap(p2, size); | |
2192 | } | |
2193 | if (p1 == p2) { | |
2194 | EXPECT_NOT_POISONED(*(char*)p2); | |
2195 | munmap(p2, size); | |
2196 | } | |
2197 | } | |
2198 | ||
92a42be0 SL |
2199 | // There's no fcvt() on FreeBSD. |
2200 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
2201 | // FIXME: enable and add ecvt. |
2202 | // FIXME: check why msandr does nt handle fcvt. | |
2203 | TEST(MemorySanitizer, fcvt) { | |
2204 | int a, b; | |
2205 | break_optimization(&a); | |
2206 | break_optimization(&b); | |
2207 | EXPECT_POISONED(a); | |
2208 | EXPECT_POISONED(b); | |
2209 | char *str = fcvt(12345.6789, 10, &a, &b); | |
2210 | EXPECT_NOT_POISONED(a); | |
2211 | EXPECT_NOT_POISONED(b); | |
92a42be0 SL |
2212 | ASSERT_NE(nullptr, str); |
2213 | EXPECT_NOT_POISONED(str[0]); | |
2214 | ASSERT_NE(0U, strlen(str)); | |
2215 | } | |
2216 | #endif | |
2217 | ||
2218 | // There's no fcvt_long() on FreeBSD. | |
2219 | #if !defined(__FreeBSD__) | |
2220 | TEST(MemorySanitizer, fcvt_long) { | |
2221 | int a, b; | |
2222 | break_optimization(&a); | |
2223 | break_optimization(&b); | |
2224 | EXPECT_POISONED(a); | |
2225 | EXPECT_POISONED(b); | |
2226 | char *str = fcvt(111111112345.6789, 10, &a, &b); | |
2227 | EXPECT_NOT_POISONED(a); | |
2228 | EXPECT_NOT_POISONED(b); | |
2229 | ASSERT_NE(nullptr, str); | |
2230 | EXPECT_NOT_POISONED(str[0]); | |
2231 | ASSERT_NE(0U, strlen(str)); | |
1a4d82fc | 2232 | } |
92a42be0 | 2233 | #endif |
1a4d82fc JJ |
2234 | |
2235 | TEST(MemorySanitizer, memchr) { | |
2236 | char x[10]; | |
2237 | break_optimization(x); | |
2238 | EXPECT_POISONED(x[0]); | |
2239 | x[2] = '2'; | |
2240 | void *res; | |
2241 | EXPECT_UMR(res = memchr(x, '2', 10)); | |
2242 | EXPECT_NOT_POISONED(res); | |
2243 | x[0] = '0'; | |
2244 | x[1] = '1'; | |
2245 | res = memchr(x, '2', 10); | |
2246 | EXPECT_EQ(&x[2], res); | |
2247 | EXPECT_UMR(res = memchr(x, '3', 10)); | |
2248 | EXPECT_NOT_POISONED(res); | |
2249 | } | |
2250 | ||
2251 | TEST(MemorySanitizer, memrchr) { | |
2252 | char x[10]; | |
2253 | break_optimization(x); | |
2254 | EXPECT_POISONED(x[0]); | |
2255 | x[9] = '9'; | |
2256 | void *res; | |
2257 | EXPECT_UMR(res = memrchr(x, '9', 10)); | |
2258 | EXPECT_NOT_POISONED(res); | |
2259 | x[0] = '0'; | |
2260 | x[1] = '1'; | |
2261 | res = memrchr(x, '0', 2); | |
2262 | EXPECT_EQ(&x[0], res); | |
2263 | EXPECT_UMR(res = memrchr(x, '7', 10)); | |
2264 | EXPECT_NOT_POISONED(res); | |
2265 | } | |
2266 | ||
2267 | TEST(MemorySanitizer, frexp) { | |
2268 | int x; | |
2269 | x = *GetPoisoned<int>(); | |
2270 | double r = frexp(1.1, &x); | |
2271 | EXPECT_NOT_POISONED(r); | |
2272 | EXPECT_NOT_POISONED(x); | |
2273 | ||
2274 | x = *GetPoisoned<int>(); | |
2275 | float rf = frexpf(1.1, &x); | |
2276 | EXPECT_NOT_POISONED(rf); | |
2277 | EXPECT_NOT_POISONED(x); | |
2278 | ||
2279 | x = *GetPoisoned<int>(); | |
2280 | double rl = frexpl(1.1, &x); | |
2281 | EXPECT_NOT_POISONED(rl); | |
2282 | EXPECT_NOT_POISONED(x); | |
2283 | } | |
2284 | ||
2285 | namespace { | |
2286 | ||
2287 | static int cnt; | |
2288 | ||
2289 | void SigactionHandler(int signo, siginfo_t* si, void* uc) { | |
2290 | ASSERT_EQ(signo, SIGPROF); | |
2291 | ASSERT_TRUE(si != NULL); | |
2292 | EXPECT_NOT_POISONED(si->si_errno); | |
2293 | EXPECT_NOT_POISONED(si->si_pid); | |
2294 | #if __linux__ | |
2295 | # if defined(__x86_64__) | |
2296 | EXPECT_NOT_POISONED(((ucontext_t*)uc)->uc_mcontext.gregs[REG_RIP]); | |
2297 | # elif defined(__i386__) | |
2298 | EXPECT_NOT_POISONED(((ucontext_t*)uc)->uc_mcontext.gregs[REG_EIP]); | |
2299 | # endif | |
2300 | #endif | |
2301 | ++cnt; | |
2302 | } | |
2303 | ||
2304 | TEST(MemorySanitizer, sigaction) { | |
2305 | struct sigaction act = {}; | |
2306 | struct sigaction oldact = {}; | |
2307 | struct sigaction origact = {}; | |
2308 | ||
2309 | sigaction(SIGPROF, 0, &origact); | |
2310 | ||
2311 | act.sa_flags |= SA_SIGINFO; | |
2312 | act.sa_sigaction = &SigactionHandler; | |
2313 | sigaction(SIGPROF, &act, 0); | |
2314 | ||
2315 | kill(getpid(), SIGPROF); | |
2316 | ||
2317 | act.sa_flags &= ~SA_SIGINFO; | |
2318 | act.sa_handler = SIG_DFL; | |
2319 | sigaction(SIGPROF, &act, 0); | |
2320 | ||
2321 | act.sa_flags &= ~SA_SIGINFO; | |
2322 | act.sa_handler = SIG_IGN; | |
2323 | sigaction(SIGPROF, &act, &oldact); | |
2324 | EXPECT_FALSE(oldact.sa_flags & SA_SIGINFO); | |
2325 | EXPECT_EQ(SIG_DFL, oldact.sa_handler); | |
2326 | kill(getpid(), SIGPROF); | |
2327 | ||
2328 | act.sa_flags |= SA_SIGINFO; | |
2329 | act.sa_sigaction = &SigactionHandler; | |
2330 | sigaction(SIGPROF, &act, &oldact); | |
2331 | EXPECT_FALSE(oldact.sa_flags & SA_SIGINFO); | |
2332 | EXPECT_EQ(SIG_IGN, oldact.sa_handler); | |
2333 | kill(getpid(), SIGPROF); | |
2334 | ||
2335 | act.sa_flags &= ~SA_SIGINFO; | |
2336 | act.sa_handler = SIG_DFL; | |
2337 | sigaction(SIGPROF, &act, &oldact); | |
2338 | EXPECT_TRUE(oldact.sa_flags & SA_SIGINFO); | |
2339 | EXPECT_EQ(&SigactionHandler, oldact.sa_sigaction); | |
2340 | EXPECT_EQ(2, cnt); | |
2341 | ||
2342 | sigaction(SIGPROF, &origact, 0); | |
2343 | } | |
2344 | ||
2345 | } // namespace | |
2346 | ||
2347 | ||
2348 | TEST(MemorySanitizer, sigemptyset) { | |
2349 | sigset_t s; | |
2350 | EXPECT_POISONED(s); | |
2351 | int res = sigemptyset(&s); | |
2352 | ASSERT_EQ(0, res); | |
2353 | EXPECT_NOT_POISONED(s); | |
2354 | } | |
2355 | ||
2356 | TEST(MemorySanitizer, sigfillset) { | |
2357 | sigset_t s; | |
2358 | EXPECT_POISONED(s); | |
2359 | int res = sigfillset(&s); | |
2360 | ASSERT_EQ(0, res); | |
2361 | EXPECT_NOT_POISONED(s); | |
2362 | } | |
2363 | ||
2364 | TEST(MemorySanitizer, sigpending) { | |
2365 | sigset_t s; | |
2366 | EXPECT_POISONED(s); | |
2367 | int res = sigpending(&s); | |
2368 | ASSERT_EQ(0, res); | |
2369 | EXPECT_NOT_POISONED(s); | |
2370 | } | |
2371 | ||
2372 | TEST(MemorySanitizer, sigprocmask) { | |
2373 | sigset_t s; | |
2374 | EXPECT_POISONED(s); | |
2375 | int res = sigprocmask(SIG_BLOCK, 0, &s); | |
2376 | ASSERT_EQ(0, res); | |
2377 | EXPECT_NOT_POISONED(s); | |
2378 | } | |
2379 | ||
2380 | struct StructWithDtor { | |
2381 | ~StructWithDtor(); | |
2382 | }; | |
2383 | ||
2384 | NOINLINE StructWithDtor::~StructWithDtor() { | |
2385 | break_optimization(0); | |
2386 | } | |
2387 | ||
2388 | TEST(MemorySanitizer, Invoke) { | |
2389 | StructWithDtor s; // Will cause the calls to become invokes. | |
2390 | EXPECT_NOT_POISONED(0); | |
2391 | EXPECT_POISONED(*GetPoisoned<int>()); | |
2392 | EXPECT_NOT_POISONED(0); | |
2393 | EXPECT_POISONED(*GetPoisoned<int>()); | |
2394 | EXPECT_POISONED(ReturnPoisoned<S4>()); | |
2395 | } | |
2396 | ||
2397 | TEST(MemorySanitizer, ptrtoint) { | |
2398 | // Test that shadow is propagated through pointer-to-integer conversion. | |
5bcae85e SL |
2399 | unsigned char c = 0; |
2400 | __msan_poison(&c, 1); | |
2401 | uintptr_t u = (uintptr_t)c << 8; | |
2402 | EXPECT_NOT_POISONED(u & 0xFF00FF); | |
2403 | EXPECT_POISONED(u & 0xFF00); | |
2404 | ||
2405 | break_optimization(&u); | |
2406 | void* p = (void*)u; | |
1a4d82fc | 2407 | |
5bcae85e SL |
2408 | break_optimization(&p); |
2409 | EXPECT_POISONED(p); | |
2410 | EXPECT_NOT_POISONED(((uintptr_t)p) & 0xFF00FF); | |
2411 | EXPECT_POISONED(((uintptr_t)p) & 0xFF00); | |
1a4d82fc JJ |
2412 | } |
2413 | ||
2414 | static void vaargsfn2(int guard, ...) { | |
2415 | va_list vl; | |
2416 | va_start(vl, guard); | |
2417 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2418 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2419 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2420 | EXPECT_POISONED(va_arg(vl, double)); | |
2421 | va_end(vl); | |
2422 | } | |
2423 | ||
2424 | static void vaargsfn(int guard, ...) { | |
2425 | va_list vl; | |
2426 | va_start(vl, guard); | |
2427 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2428 | EXPECT_POISONED(va_arg(vl, int)); | |
2429 | // The following call will overwrite __msan_param_tls. | |
2430 | // Checks after it test that arg shadow was somehow saved across the call. | |
2431 | vaargsfn2(1, 2, 3, 4, *GetPoisoned<double>()); | |
2432 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2433 | EXPECT_POISONED(va_arg(vl, int)); | |
2434 | va_end(vl); | |
2435 | } | |
2436 | ||
2437 | TEST(MemorySanitizer, VAArgTest) { | |
2438 | int* x = GetPoisoned<int>(); | |
2439 | int* y = GetPoisoned<int>(4); | |
2440 | vaargsfn(1, 13, *x, 42, *y); | |
2441 | } | |
2442 | ||
2443 | static void vaargsfn_many(int guard, ...) { | |
2444 | va_list vl; | |
2445 | va_start(vl, guard); | |
2446 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2447 | EXPECT_POISONED(va_arg(vl, int)); | |
2448 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2449 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2450 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2451 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2452 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2453 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2454 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2455 | EXPECT_POISONED(va_arg(vl, int)); | |
2456 | va_end(vl); | |
2457 | } | |
2458 | ||
2459 | TEST(MemorySanitizer, VAArgManyTest) { | |
2460 | int* x = GetPoisoned<int>(); | |
2461 | int* y = GetPoisoned<int>(4); | |
2462 | vaargsfn_many(1, 2, *x, 3, 4, 5, 6, 7, 8, 9, *y); | |
2463 | } | |
2464 | ||
5bcae85e SL |
2465 | static void vaargsfn_manyfix(int g1, int g2, int g3, int g4, int g5, int g6, int g7, int g8, int g9, ...) { |
2466 | va_list vl; | |
2467 | va_start(vl, g9); | |
2468 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2469 | EXPECT_POISONED(va_arg(vl, int)); | |
2470 | va_end(vl); | |
2471 | } | |
2472 | ||
2473 | TEST(MemorySanitizer, VAArgManyFixTest) { | |
2474 | int* x = GetPoisoned<int>(); | |
2475 | int* y = GetPoisoned<int>(); | |
2476 | vaargsfn_manyfix(1, *x, 3, 4, 5, 6, 7, 8, 9, 10, *y); | |
2477 | } | |
2478 | ||
1a4d82fc JJ |
2479 | static void vaargsfn_pass2(va_list vl) { |
2480 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2481 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2482 | EXPECT_POISONED(va_arg(vl, int)); | |
2483 | } | |
2484 | ||
2485 | static void vaargsfn_pass(int guard, ...) { | |
2486 | va_list vl; | |
2487 | va_start(vl, guard); | |
2488 | EXPECT_POISONED(va_arg(vl, int)); | |
2489 | vaargsfn_pass2(vl); | |
2490 | va_end(vl); | |
2491 | } | |
2492 | ||
2493 | TEST(MemorySanitizer, VAArgPass) { | |
2494 | int* x = GetPoisoned<int>(); | |
2495 | int* y = GetPoisoned<int>(4); | |
2496 | vaargsfn_pass(1, *x, 2, 3, *y); | |
2497 | } | |
2498 | ||
2499 | static void vaargsfn_copy2(va_list vl) { | |
2500 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2501 | EXPECT_POISONED(va_arg(vl, int)); | |
2502 | } | |
2503 | ||
2504 | static void vaargsfn_copy(int guard, ...) { | |
2505 | va_list vl; | |
2506 | va_start(vl, guard); | |
2507 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2508 | EXPECT_POISONED(va_arg(vl, int)); | |
2509 | va_list vl2; | |
2510 | va_copy(vl2, vl); | |
2511 | vaargsfn_copy2(vl2); | |
2512 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2513 | EXPECT_POISONED(va_arg(vl, int)); | |
2514 | va_end(vl); | |
2515 | } | |
2516 | ||
2517 | TEST(MemorySanitizer, VAArgCopy) { | |
2518 | int* x = GetPoisoned<int>(); | |
2519 | int* y = GetPoisoned<int>(4); | |
2520 | vaargsfn_copy(1, 2, *x, 3, *y); | |
2521 | } | |
2522 | ||
2523 | static void vaargsfn_ptr(int guard, ...) { | |
2524 | va_list vl; | |
2525 | va_start(vl, guard); | |
2526 | EXPECT_NOT_POISONED(va_arg(vl, int*)); | |
2527 | EXPECT_POISONED(va_arg(vl, int*)); | |
2528 | EXPECT_NOT_POISONED(va_arg(vl, int*)); | |
2529 | EXPECT_POISONED(va_arg(vl, double*)); | |
2530 | va_end(vl); | |
2531 | } | |
2532 | ||
2533 | TEST(MemorySanitizer, VAArgPtr) { | |
2534 | int** x = GetPoisoned<int*>(); | |
2535 | double** y = GetPoisoned<double*>(8); | |
2536 | int z; | |
2537 | vaargsfn_ptr(1, &z, *x, &z, *y); | |
2538 | } | |
2539 | ||
2540 | static void vaargsfn_overflow(int guard, ...) { | |
2541 | va_list vl; | |
2542 | va_start(vl, guard); | |
2543 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2544 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2545 | EXPECT_POISONED(va_arg(vl, int)); | |
2546 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2547 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2548 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2549 | ||
2550 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2551 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2552 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2553 | EXPECT_POISONED(va_arg(vl, double)); | |
2554 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2555 | EXPECT_POISONED(va_arg(vl, int*)); | |
2556 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2557 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2558 | ||
2559 | EXPECT_POISONED(va_arg(vl, int)); | |
2560 | EXPECT_POISONED(va_arg(vl, double)); | |
2561 | EXPECT_POISONED(va_arg(vl, int*)); | |
2562 | ||
2563 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2564 | EXPECT_NOT_POISONED(va_arg(vl, double)); | |
2565 | EXPECT_NOT_POISONED(va_arg(vl, int*)); | |
2566 | ||
2567 | EXPECT_POISONED(va_arg(vl, int)); | |
2568 | EXPECT_POISONED(va_arg(vl, double)); | |
2569 | EXPECT_POISONED(va_arg(vl, int*)); | |
2570 | ||
2571 | va_end(vl); | |
2572 | } | |
2573 | ||
2574 | TEST(MemorySanitizer, VAArgOverflow) { | |
2575 | int* x = GetPoisoned<int>(); | |
2576 | double* y = GetPoisoned<double>(8); | |
2577 | int** p = GetPoisoned<int*>(16); | |
2578 | int z; | |
2579 | vaargsfn_overflow(1, | |
2580 | 1, 2, *x, 4, 5, 6, | |
2581 | 1.1, 2.2, 3.3, *y, 5.5, *p, 7.7, 8.8, | |
2582 | // the following args will overflow for sure | |
2583 | *x, *y, *p, | |
2584 | 7, 9.9, &z, | |
2585 | *x, *y, *p); | |
2586 | } | |
2587 | ||
2588 | static void vaargsfn_tlsoverwrite2(int guard, ...) { | |
2589 | va_list vl; | |
2590 | va_start(vl, guard); | |
2591 | for (int i = 0; i < 20; ++i) | |
2592 | EXPECT_NOT_POISONED(va_arg(vl, int)); | |
2593 | va_end(vl); | |
2594 | } | |
2595 | ||
2596 | static void vaargsfn_tlsoverwrite(int guard, ...) { | |
2597 | // This call will overwrite TLS contents unless it's backed up somewhere. | |
2598 | vaargsfn_tlsoverwrite2(2, | |
2599 | 42, 42, 42, 42, 42, | |
2600 | 42, 42, 42, 42, 42, | |
2601 | 42, 42, 42, 42, 42, | |
2602 | 42, 42, 42, 42, 42); // 20x | |
2603 | va_list vl; | |
2604 | va_start(vl, guard); | |
2605 | for (int i = 0; i < 20; ++i) | |
2606 | EXPECT_POISONED(va_arg(vl, int)); | |
2607 | va_end(vl); | |
2608 | } | |
2609 | ||
2610 | TEST(MemorySanitizer, VAArgTLSOverwrite) { | |
2611 | int* x = GetPoisoned<int>(); | |
2612 | vaargsfn_tlsoverwrite(1, | |
2613 | *x, *x, *x, *x, *x, | |
2614 | *x, *x, *x, *x, *x, | |
2615 | *x, *x, *x, *x, *x, | |
2616 | *x, *x, *x, *x, *x); // 20x | |
2617 | ||
2618 | } | |
2619 | ||
2620 | struct StructByVal { | |
2621 | int a, b, c, d, e, f; | |
2622 | }; | |
2623 | ||
2624 | static void vaargsfn_structbyval(int guard, ...) { | |
2625 | va_list vl; | |
2626 | va_start(vl, guard); | |
2627 | { | |
2628 | StructByVal s = va_arg(vl, StructByVal); | |
2629 | EXPECT_NOT_POISONED(s.a); | |
2630 | EXPECT_POISONED(s.b); | |
2631 | EXPECT_NOT_POISONED(s.c); | |
2632 | EXPECT_POISONED(s.d); | |
2633 | EXPECT_NOT_POISONED(s.e); | |
2634 | EXPECT_POISONED(s.f); | |
2635 | } | |
2636 | { | |
2637 | StructByVal s = va_arg(vl, StructByVal); | |
2638 | EXPECT_NOT_POISONED(s.a); | |
2639 | EXPECT_POISONED(s.b); | |
2640 | EXPECT_NOT_POISONED(s.c); | |
2641 | EXPECT_POISONED(s.d); | |
2642 | EXPECT_NOT_POISONED(s.e); | |
2643 | EXPECT_POISONED(s.f); | |
2644 | } | |
2645 | va_end(vl); | |
2646 | } | |
2647 | ||
2648 | TEST(MemorySanitizer, VAArgStructByVal) { | |
2649 | StructByVal s; | |
2650 | s.a = 1; | |
2651 | s.b = *GetPoisoned<int>(); | |
2652 | s.c = 2; | |
2653 | s.d = *GetPoisoned<int>(); | |
2654 | s.e = 3; | |
2655 | s.f = *GetPoisoned<int>(); | |
2656 | vaargsfn_structbyval(0, s, s); | |
2657 | } | |
2658 | ||
2659 | NOINLINE void StructByValTestFunc(struct StructByVal s) { | |
2660 | EXPECT_NOT_POISONED(s.a); | |
2661 | EXPECT_POISONED(s.b); | |
2662 | EXPECT_NOT_POISONED(s.c); | |
2663 | EXPECT_POISONED(s.d); | |
2664 | EXPECT_NOT_POISONED(s.e); | |
2665 | EXPECT_POISONED(s.f); | |
2666 | } | |
2667 | ||
2668 | NOINLINE void StructByValTestFunc1(struct StructByVal s) { | |
2669 | StructByValTestFunc(s); | |
2670 | } | |
2671 | ||
2672 | NOINLINE void StructByValTestFunc2(int z, struct StructByVal s) { | |
2673 | StructByValTestFunc(s); | |
2674 | } | |
2675 | ||
2676 | TEST(MemorySanitizer, StructByVal) { | |
2677 | // Large aggregates are passed as "byval" pointer argument in LLVM. | |
2678 | struct StructByVal s; | |
2679 | s.a = 1; | |
2680 | s.b = *GetPoisoned<int>(); | |
2681 | s.c = 2; | |
2682 | s.d = *GetPoisoned<int>(); | |
2683 | s.e = 3; | |
2684 | s.f = *GetPoisoned<int>(); | |
2685 | StructByValTestFunc(s); | |
2686 | StructByValTestFunc1(s); | |
2687 | StructByValTestFunc2(0, s); | |
2688 | } | |
2689 | ||
2690 | ||
2691 | #if MSAN_HAS_M128 | |
2692 | NOINLINE __m128i m128Eq(__m128i *a, __m128i *b) { return _mm_cmpeq_epi16(*a, *b); } | |
2693 | NOINLINE __m128i m128Lt(__m128i *a, __m128i *b) { return _mm_cmplt_epi16(*a, *b); } | |
2694 | TEST(MemorySanitizer, m128) { | |
2695 | __m128i a = _mm_set1_epi16(0x1234); | |
2696 | __m128i b = _mm_set1_epi16(0x7890); | |
2697 | EXPECT_NOT_POISONED(m128Eq(&a, &b)); | |
2698 | EXPECT_NOT_POISONED(m128Lt(&a, &b)); | |
2699 | } | |
2700 | // FIXME: add more tests for __m128i. | |
2701 | #endif // MSAN_HAS_M128 | |
2702 | ||
2703 | // We should not complain when copying this poisoned hole. | |
2704 | struct StructWithHole { | |
2705 | U4 a; | |
2706 | // 4-byte hole. | |
2707 | U8 b; | |
2708 | }; | |
2709 | ||
2710 | NOINLINE StructWithHole ReturnStructWithHole() { | |
2711 | StructWithHole res; | |
2712 | __msan_poison(&res, sizeof(res)); | |
2713 | res.a = 1; | |
2714 | res.b = 2; | |
2715 | return res; | |
2716 | } | |
2717 | ||
2718 | TEST(MemorySanitizer, StructWithHole) { | |
2719 | StructWithHole a = ReturnStructWithHole(); | |
2720 | break_optimization(&a); | |
2721 | } | |
2722 | ||
2723 | template <class T> | |
2724 | NOINLINE T ReturnStruct() { | |
2725 | T res; | |
2726 | __msan_poison(&res, sizeof(res)); | |
2727 | res.a = 1; | |
2728 | return res; | |
2729 | } | |
2730 | ||
2731 | template <class T> | |
2732 | NOINLINE void TestReturnStruct() { | |
2733 | T s1 = ReturnStruct<T>(); | |
2734 | EXPECT_NOT_POISONED(s1.a); | |
2735 | EXPECT_POISONED(s1.b); | |
2736 | } | |
2737 | ||
2738 | struct SSS1 { | |
2739 | int a, b, c; | |
2740 | }; | |
2741 | struct SSS2 { | |
2742 | int b, a, c; | |
2743 | }; | |
2744 | struct SSS3 { | |
2745 | int b, c, a; | |
2746 | }; | |
2747 | struct SSS4 { | |
2748 | int c, b, a; | |
2749 | }; | |
2750 | ||
2751 | struct SSS5 { | |
2752 | int a; | |
2753 | float b; | |
2754 | }; | |
2755 | struct SSS6 { | |
2756 | int a; | |
2757 | double b; | |
2758 | }; | |
2759 | struct SSS7 { | |
2760 | S8 b; | |
2761 | int a; | |
2762 | }; | |
2763 | struct SSS8 { | |
2764 | S2 b; | |
2765 | S8 a; | |
2766 | }; | |
2767 | ||
2768 | TEST(MemorySanitizer, IntStruct3) { | |
2769 | TestReturnStruct<SSS1>(); | |
2770 | TestReturnStruct<SSS2>(); | |
2771 | TestReturnStruct<SSS3>(); | |
2772 | TestReturnStruct<SSS4>(); | |
2773 | TestReturnStruct<SSS5>(); | |
2774 | TestReturnStruct<SSS6>(); | |
2775 | TestReturnStruct<SSS7>(); | |
2776 | TestReturnStruct<SSS8>(); | |
2777 | } | |
2778 | ||
2779 | struct LongStruct { | |
2780 | U1 a1, b1; | |
2781 | U2 a2, b2; | |
2782 | U4 a4, b4; | |
2783 | U8 a8, b8; | |
2784 | }; | |
2785 | ||
2786 | NOINLINE LongStruct ReturnLongStruct1() { | |
2787 | LongStruct res; | |
2788 | __msan_poison(&res, sizeof(res)); | |
2789 | res.a1 = res.a2 = res.a4 = res.a8 = 111; | |
2790 | // leaves b1, .., b8 poisoned. | |
2791 | return res; | |
2792 | } | |
2793 | ||
2794 | NOINLINE LongStruct ReturnLongStruct2() { | |
2795 | LongStruct res; | |
2796 | __msan_poison(&res, sizeof(res)); | |
2797 | res.b1 = res.b2 = res.b4 = res.b8 = 111; | |
2798 | // leaves a1, .., a8 poisoned. | |
2799 | return res; | |
2800 | } | |
2801 | ||
2802 | TEST(MemorySanitizer, LongStruct) { | |
2803 | LongStruct s1 = ReturnLongStruct1(); | |
2804 | __msan_print_shadow(&s1, sizeof(s1)); | |
2805 | EXPECT_NOT_POISONED(s1.a1); | |
2806 | EXPECT_NOT_POISONED(s1.a2); | |
2807 | EXPECT_NOT_POISONED(s1.a4); | |
2808 | EXPECT_NOT_POISONED(s1.a8); | |
2809 | ||
2810 | EXPECT_POISONED(s1.b1); | |
2811 | EXPECT_POISONED(s1.b2); | |
2812 | EXPECT_POISONED(s1.b4); | |
2813 | EXPECT_POISONED(s1.b8); | |
2814 | ||
2815 | LongStruct s2 = ReturnLongStruct2(); | |
2816 | __msan_print_shadow(&s2, sizeof(s2)); | |
2817 | EXPECT_NOT_POISONED(s2.b1); | |
2818 | EXPECT_NOT_POISONED(s2.b2); | |
2819 | EXPECT_NOT_POISONED(s2.b4); | |
2820 | EXPECT_NOT_POISONED(s2.b8); | |
2821 | ||
2822 | EXPECT_POISONED(s2.a1); | |
2823 | EXPECT_POISONED(s2.a2); | |
2824 | EXPECT_POISONED(s2.a4); | |
2825 | EXPECT_POISONED(s2.a8); | |
2826 | } | |
2827 | ||
2828 | TEST(MemorySanitizer, getrlimit) { | |
2829 | struct rlimit limit; | |
2830 | __msan_poison(&limit, sizeof(limit)); | |
2831 | int result = getrlimit(RLIMIT_DATA, &limit); | |
2832 | ASSERT_EQ(result, 0); | |
2833 | EXPECT_NOT_POISONED(limit.rlim_cur); | |
2834 | EXPECT_NOT_POISONED(limit.rlim_max); | |
5bcae85e SL |
2835 | |
2836 | struct rlimit limit2; | |
2837 | __msan_poison(&limit2, sizeof(limit2)); | |
2838 | result = prlimit(getpid(), RLIMIT_DATA, &limit, &limit2); | |
2839 | ASSERT_EQ(result, 0); | |
2840 | EXPECT_NOT_POISONED(limit2.rlim_cur); | |
2841 | EXPECT_NOT_POISONED(limit2.rlim_max); | |
2842 | ||
2843 | __msan_poison(&limit, sizeof(limit)); | |
2844 | result = prlimit(getpid(), RLIMIT_DATA, nullptr, &limit); | |
2845 | ASSERT_EQ(result, 0); | |
2846 | EXPECT_NOT_POISONED(limit.rlim_cur); | |
2847 | EXPECT_NOT_POISONED(limit.rlim_max); | |
2848 | ||
2849 | result = prlimit(getpid(), RLIMIT_DATA, &limit, nullptr); | |
2850 | ASSERT_EQ(result, 0); | |
1a4d82fc JJ |
2851 | } |
2852 | ||
2853 | TEST(MemorySanitizer, getrusage) { | |
2854 | struct rusage usage; | |
2855 | __msan_poison(&usage, sizeof(usage)); | |
2856 | int result = getrusage(RUSAGE_SELF, &usage); | |
2857 | ASSERT_EQ(result, 0); | |
2858 | EXPECT_NOT_POISONED(usage.ru_utime.tv_sec); | |
2859 | EXPECT_NOT_POISONED(usage.ru_utime.tv_usec); | |
2860 | EXPECT_NOT_POISONED(usage.ru_stime.tv_sec); | |
2861 | EXPECT_NOT_POISONED(usage.ru_stime.tv_usec); | |
2862 | EXPECT_NOT_POISONED(usage.ru_maxrss); | |
2863 | EXPECT_NOT_POISONED(usage.ru_minflt); | |
2864 | EXPECT_NOT_POISONED(usage.ru_majflt); | |
2865 | EXPECT_NOT_POISONED(usage.ru_inblock); | |
2866 | EXPECT_NOT_POISONED(usage.ru_oublock); | |
2867 | EXPECT_NOT_POISONED(usage.ru_nvcsw); | |
2868 | EXPECT_NOT_POISONED(usage.ru_nivcsw); | |
2869 | } | |
2870 | ||
92a42be0 SL |
2871 | #if defined(__FreeBSD__) |
2872 | static void GetProgramPath(char *buf, size_t sz) { | |
2873 | int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; | |
2874 | int res = sysctl(mib, 4, buf, &sz, NULL, 0); | |
2875 | ASSERT_EQ(0, res); | |
2876 | } | |
2877 | #elif defined(__GLIBC__) | |
2878 | static void GetProgramPath(char *buf, size_t sz) { | |
2879 | extern char *program_invocation_name; | |
2880 | int res = snprintf(buf, sz, "%s", program_invocation_name); | |
2881 | ASSERT_GE(res, 0); | |
2882 | ASSERT_LT((size_t)res, sz); | |
2883 | } | |
2884 | #else | |
1a4d82fc JJ |
2885 | # error "TODO: port this" |
2886 | #endif | |
2887 | ||
2888 | static void dladdr_testfn() {} | |
2889 | ||
2890 | TEST(MemorySanitizer, dladdr) { | |
2891 | Dl_info info; | |
2892 | __msan_poison(&info, sizeof(info)); | |
2893 | int result = dladdr((const void*)dladdr_testfn, &info); | |
2894 | ASSERT_NE(result, 0); | |
2895 | EXPECT_NOT_POISONED((unsigned long)info.dli_fname); | |
2896 | if (info.dli_fname) | |
2897 | EXPECT_NOT_POISONED(strlen(info.dli_fname)); | |
2898 | EXPECT_NOT_POISONED((unsigned long)info.dli_fbase); | |
2899 | EXPECT_NOT_POISONED((unsigned long)info.dli_sname); | |
2900 | if (info.dli_sname) | |
2901 | EXPECT_NOT_POISONED(strlen(info.dli_sname)); | |
2902 | EXPECT_NOT_POISONED((unsigned long)info.dli_saddr); | |
2903 | } | |
2904 | ||
2905 | #ifndef MSAN_TEST_DISABLE_DLOPEN | |
2906 | ||
2907 | static int dl_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) { | |
2908 | (*(int *)data)++; | |
2909 | EXPECT_NOT_POISONED(info->dlpi_addr); | |
2910 | EXPECT_NOT_POISONED(strlen(info->dlpi_name)); | |
2911 | EXPECT_NOT_POISONED(info->dlpi_phnum); | |
2912 | for (int i = 0; i < info->dlpi_phnum; ++i) | |
2913 | EXPECT_NOT_POISONED(info->dlpi_phdr[i]); | |
2914 | return 0; | |
2915 | } | |
2916 | ||
2917 | // Compute the path to our loadable DSO. We assume it's in the same | |
2918 | // directory. Only use string routines that we intercept so far to do this. | |
92a42be0 SL |
2919 | static void GetPathToLoadable(char *buf, size_t sz) { |
2920 | char program_path[kMaxPathLength]; | |
2921 | GetProgramPath(program_path, sizeof(program_path)); | |
2922 | ||
2923 | const char *last_slash = strrchr(program_path, '/'); | |
2924 | ASSERT_NE(nullptr, last_slash); | |
2925 | size_t dir_len = (size_t)(last_slash - program_path); | |
2926 | #if defined(__x86_64__) | |
2927 | static const char basename[] = "libmsan_loadable.x86_64.so"; | |
2928 | #elif defined(__MIPSEB__) || defined(MIPSEB) | |
2929 | static const char basename[] = "libmsan_loadable.mips64.so"; | |
2930 | #elif defined(__mips64) | |
2931 | static const char basename[] = "libmsan_loadable.mips64el.so"; | |
3157f602 XL |
2932 | #elif defined(__aarch64__) |
2933 | static const char basename[] = "libmsan_loadable.aarch64.so"; | |
5bcae85e SL |
2934 | #elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
2935 | static const char basename[] = "libmsan_loadable.powerpc64.so"; | |
2936 | #elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
2937 | static const char basename[] = "libmsan_loadable.powerpc64le.so"; | |
92a42be0 SL |
2938 | #endif |
2939 | int res = snprintf(buf, sz, "%.*s/%s", | |
2940 | (int)dir_len, program_path, basename); | |
2941 | ASSERT_GE(res, 0); | |
2942 | ASSERT_LT((size_t)res, sz); | |
1a4d82fc JJ |
2943 | } |
2944 | ||
2945 | TEST(MemorySanitizer, dl_iterate_phdr) { | |
92a42be0 SL |
2946 | char path[kMaxPathLength]; |
2947 | GetPathToLoadable(path, sizeof(path)); | |
1a4d82fc JJ |
2948 | |
2949 | // Having at least one dlopen'ed library in the process makes this more | |
2950 | // entertaining. | |
2951 | void *lib = dlopen(path, RTLD_LAZY); | |
2952 | ASSERT_NE((void*)0, lib); | |
2953 | ||
2954 | int count = 0; | |
2955 | int result = dl_iterate_phdr(dl_phdr_callback, &count); | |
2956 | ASSERT_GT(count, 0); | |
92a42be0 | 2957 | |
1a4d82fc JJ |
2958 | dlclose(lib); |
2959 | } | |
2960 | ||
1a4d82fc | 2961 | TEST(MemorySanitizer, dlopen) { |
92a42be0 SL |
2962 | char path[kMaxPathLength]; |
2963 | GetPathToLoadable(path, sizeof(path)); | |
1a4d82fc JJ |
2964 | |
2965 | // We need to clear shadow for globals when doing dlopen. In order to test | |
2966 | // this, we have to poison the shadow for the DSO before we load it. In | |
2967 | // general this is difficult, but the loader tends to reload things in the | |
2968 | // same place, so we open, close, and then reopen. The global should always | |
2969 | // start out clean after dlopen. | |
2970 | for (int i = 0; i < 2; i++) { | |
2971 | void *lib = dlopen(path, RTLD_LAZY); | |
2972 | if (lib == NULL) { | |
2973 | printf("dlerror: %s\n", dlerror()); | |
2974 | ASSERT_TRUE(lib != NULL); | |
2975 | } | |
2976 | void **(*get_dso_global)() = (void **(*)())dlsym(lib, "get_dso_global"); | |
2977 | ASSERT_TRUE(get_dso_global != NULL); | |
2978 | void **dso_global = get_dso_global(); | |
2979 | EXPECT_NOT_POISONED(*dso_global); | |
2980 | __msan_poison(dso_global, sizeof(*dso_global)); | |
2981 | EXPECT_POISONED(*dso_global); | |
2982 | dlclose(lib); | |
2983 | } | |
2984 | } | |
2985 | ||
2986 | // Regression test for a crash in dlopen() interceptor. | |
2987 | TEST(MemorySanitizer, dlopenFailed) { | |
92a42be0 | 2988 | const char *path = "/libmsan_loadable_does_not_exist.so"; |
1a4d82fc JJ |
2989 | void *lib = dlopen(path, RTLD_LAZY); |
2990 | ASSERT_TRUE(lib == NULL); | |
2991 | } | |
2992 | ||
2993 | #endif // MSAN_TEST_DISABLE_DLOPEN | |
2994 | ||
92a42be0 SL |
2995 | // There's no sched_getaffinity() on FreeBSD. |
2996 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
2997 | TEST(MemorySanitizer, sched_getaffinity) { |
2998 | cpu_set_t mask; | |
2999 | int res = sched_getaffinity(getpid(), sizeof(mask), &mask); | |
3000 | ASSERT_EQ(0, res); | |
3001 | EXPECT_NOT_POISONED(mask); | |
3002 | } | |
92a42be0 | 3003 | #endif |
1a4d82fc JJ |
3004 | |
3005 | TEST(MemorySanitizer, scanf) { | |
3006 | const char *input = "42 hello"; | |
3007 | int* d = new int; | |
3008 | char* s = new char[7]; | |
3009 | int res = sscanf(input, "%d %5s", d, s); | |
3010 | printf("res %d\n", res); | |
3011 | ASSERT_EQ(res, 2); | |
3012 | EXPECT_NOT_POISONED(*d); | |
3013 | EXPECT_NOT_POISONED(s[0]); | |
3014 | EXPECT_NOT_POISONED(s[1]); | |
3015 | EXPECT_NOT_POISONED(s[2]); | |
3016 | EXPECT_NOT_POISONED(s[3]); | |
3017 | EXPECT_NOT_POISONED(s[4]); | |
3018 | EXPECT_NOT_POISONED(s[5]); | |
3019 | EXPECT_POISONED(s[6]); | |
92a42be0 | 3020 | delete[] s; |
1a4d82fc JJ |
3021 | delete d; |
3022 | } | |
3023 | ||
3024 | static void *SimpleThread_threadfn(void* data) { | |
3025 | return new int; | |
3026 | } | |
3027 | ||
3028 | TEST(MemorySanitizer, SimpleThread) { | |
3029 | pthread_t t; | |
3030 | void *p; | |
3031 | int res = pthread_create(&t, NULL, SimpleThread_threadfn, NULL); | |
3032 | ASSERT_EQ(0, res); | |
3033 | EXPECT_NOT_POISONED(t); | |
3034 | res = pthread_join(t, &p); | |
3035 | ASSERT_EQ(0, res); | |
3036 | EXPECT_NOT_POISONED(p); | |
3037 | delete (int*)p; | |
3038 | } | |
3039 | ||
3040 | static void *SmallStackThread_threadfn(void* data) { | |
3041 | return 0; | |
3042 | } | |
3043 | ||
3157f602 XL |
3044 | #ifdef PTHREAD_STACK_MIN |
3045 | # define SMALLSTACKSIZE PTHREAD_STACK_MIN | |
3046 | # define SMALLPRESTACKSIZE PTHREAD_STACK_MIN | |
3047 | #else | |
3048 | # define SMALLSTACKSIZE 64 * 1024 | |
3049 | # define SMALLPRESTACKSIZE 16 * 1024 | |
3050 | #endif | |
3051 | ||
1a4d82fc JJ |
3052 | TEST(MemorySanitizer, SmallStackThread) { |
3053 | pthread_attr_t attr; | |
3054 | pthread_t t; | |
3055 | void *p; | |
3056 | int res; | |
3057 | res = pthread_attr_init(&attr); | |
3058 | ASSERT_EQ(0, res); | |
3157f602 | 3059 | res = pthread_attr_setstacksize(&attr, SMALLSTACKSIZE); |
1a4d82fc JJ |
3060 | ASSERT_EQ(0, res); |
3061 | res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL); | |
3062 | ASSERT_EQ(0, res); | |
3063 | res = pthread_join(t, &p); | |
3064 | ASSERT_EQ(0, res); | |
3065 | res = pthread_attr_destroy(&attr); | |
3066 | ASSERT_EQ(0, res); | |
3067 | } | |
3068 | ||
3069 | TEST(MemorySanitizer, SmallPreAllocatedStackThread) { | |
3070 | pthread_attr_t attr; | |
3071 | pthread_t t; | |
3072 | int res; | |
3073 | res = pthread_attr_init(&attr); | |
3074 | ASSERT_EQ(0, res); | |
3075 | void *stack; | |
3157f602 | 3076 | const size_t kStackSize = SMALLPRESTACKSIZE; |
1a4d82fc JJ |
3077 | res = posix_memalign(&stack, 4096, kStackSize); |
3078 | ASSERT_EQ(0, res); | |
3079 | res = pthread_attr_setstack(&attr, stack, kStackSize); | |
3080 | ASSERT_EQ(0, res); | |
3081 | res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL); | |
3082 | EXPECT_EQ(0, res); | |
3083 | res = pthread_join(t, NULL); | |
3084 | ASSERT_EQ(0, res); | |
3085 | res = pthread_attr_destroy(&attr); | |
3086 | ASSERT_EQ(0, res); | |
3087 | } | |
3088 | ||
3089 | TEST(MemorySanitizer, pthread_attr_get) { | |
3090 | pthread_attr_t attr; | |
3091 | int res; | |
3092 | res = pthread_attr_init(&attr); | |
3093 | ASSERT_EQ(0, res); | |
3094 | { | |
3095 | int v; | |
3096 | res = pthread_attr_getdetachstate(&attr, &v); | |
3097 | ASSERT_EQ(0, res); | |
3098 | EXPECT_NOT_POISONED(v); | |
3099 | } | |
3100 | { | |
3101 | size_t v; | |
3102 | res = pthread_attr_getguardsize(&attr, &v); | |
3103 | ASSERT_EQ(0, res); | |
3104 | EXPECT_NOT_POISONED(v); | |
3105 | } | |
3106 | { | |
3107 | struct sched_param v; | |
3108 | res = pthread_attr_getschedparam(&attr, &v); | |
3109 | ASSERT_EQ(0, res); | |
3110 | EXPECT_NOT_POISONED(v); | |
3111 | } | |
3112 | { | |
3113 | int v; | |
3114 | res = pthread_attr_getschedpolicy(&attr, &v); | |
3115 | ASSERT_EQ(0, res); | |
3116 | EXPECT_NOT_POISONED(v); | |
3117 | } | |
3118 | { | |
3119 | int v; | |
3120 | res = pthread_attr_getinheritsched(&attr, &v); | |
3121 | ASSERT_EQ(0, res); | |
3122 | EXPECT_NOT_POISONED(v); | |
3123 | } | |
3124 | { | |
3125 | int v; | |
3126 | res = pthread_attr_getscope(&attr, &v); | |
3127 | ASSERT_EQ(0, res); | |
3128 | EXPECT_NOT_POISONED(v); | |
3129 | } | |
3130 | { | |
3131 | size_t v; | |
3132 | res = pthread_attr_getstacksize(&attr, &v); | |
3133 | ASSERT_EQ(0, res); | |
3134 | EXPECT_NOT_POISONED(v); | |
3135 | } | |
3136 | { | |
3137 | void *v; | |
3138 | size_t w; | |
3139 | res = pthread_attr_getstack(&attr, &v, &w); | |
3140 | ASSERT_EQ(0, res); | |
3141 | EXPECT_NOT_POISONED(v); | |
3142 | EXPECT_NOT_POISONED(w); | |
3143 | } | |
3144 | { | |
3145 | cpu_set_t v; | |
3146 | res = pthread_attr_getaffinity_np(&attr, sizeof(v), &v); | |
3147 | ASSERT_EQ(0, res); | |
3148 | EXPECT_NOT_POISONED(v); | |
3149 | } | |
3150 | res = pthread_attr_destroy(&attr); | |
3151 | ASSERT_EQ(0, res); | |
3152 | } | |
3153 | ||
3154 | TEST(MemorySanitizer, pthread_getschedparam) { | |
3155 | int policy; | |
3156 | struct sched_param param; | |
3157 | int res = pthread_getschedparam(pthread_self(), &policy, ¶m); | |
3158 | ASSERT_EQ(0, res); | |
3159 | EXPECT_NOT_POISONED(policy); | |
3160 | EXPECT_NOT_POISONED(param.sched_priority); | |
3161 | } | |
3162 | ||
3163 | TEST(MemorySanitizer, pthread_key_create) { | |
3164 | pthread_key_t key; | |
3165 | int res = pthread_key_create(&key, NULL); | |
3166 | ASSERT_EQ(0, res); | |
3167 | EXPECT_NOT_POISONED(key); | |
3168 | res = pthread_key_delete(key); | |
3169 | ASSERT_EQ(0, res); | |
3170 | } | |
3171 | ||
3172 | namespace { | |
3173 | struct SignalCondArg { | |
3174 | pthread_cond_t* cond; | |
3175 | pthread_mutex_t* mu; | |
3176 | bool broadcast; | |
3177 | }; | |
3178 | ||
3179 | void *SignalCond(void *param) { | |
3180 | SignalCondArg *arg = reinterpret_cast<SignalCondArg *>(param); | |
3181 | pthread_mutex_lock(arg->mu); | |
3182 | if (arg->broadcast) | |
3183 | pthread_cond_broadcast(arg->cond); | |
3184 | else | |
3185 | pthread_cond_signal(arg->cond); | |
3186 | pthread_mutex_unlock(arg->mu); | |
3187 | return 0; | |
3188 | } | |
3189 | } // namespace | |
3190 | ||
3191 | TEST(MemorySanitizer, pthread_cond_wait) { | |
3192 | pthread_cond_t cond; | |
3193 | pthread_mutex_t mu; | |
3194 | SignalCondArg args = {&cond, &mu, false}; | |
3195 | pthread_cond_init(&cond, 0); | |
3196 | pthread_mutex_init(&mu, 0); | |
3197 | pthread_mutex_lock(&mu); | |
3198 | ||
3199 | // signal | |
3200 | pthread_t thr; | |
3201 | pthread_create(&thr, 0, SignalCond, &args); | |
3202 | int res = pthread_cond_wait(&cond, &mu); | |
3203 | ASSERT_EQ(0, res); | |
3204 | pthread_join(thr, 0); | |
3205 | ||
3206 | // broadcast | |
3207 | args.broadcast = true; | |
3208 | pthread_create(&thr, 0, SignalCond, &args); | |
3209 | res = pthread_cond_wait(&cond, &mu); | |
3210 | ASSERT_EQ(0, res); | |
3211 | pthread_join(thr, 0); | |
3212 | ||
3213 | pthread_mutex_unlock(&mu); | |
3214 | pthread_mutex_destroy(&mu); | |
3215 | pthread_cond_destroy(&cond); | |
3216 | } | |
3217 | ||
3218 | TEST(MemorySanitizer, tmpnam) { | |
3219 | char s[L_tmpnam]; | |
3220 | char *res = tmpnam(s); | |
3221 | ASSERT_EQ(s, res); | |
3222 | EXPECT_NOT_POISONED(strlen(res)); | |
3223 | } | |
3224 | ||
3225 | TEST(MemorySanitizer, tempnam) { | |
3226 | char *res = tempnam(NULL, "zzz"); | |
3227 | EXPECT_NOT_POISONED(strlen(res)); | |
3228 | free(res); | |
3229 | } | |
3230 | ||
3231 | TEST(MemorySanitizer, posix_memalign) { | |
3232 | void *p; | |
3233 | EXPECT_POISONED(p); | |
3234 | int res = posix_memalign(&p, 4096, 13); | |
3235 | ASSERT_EQ(0, res); | |
3236 | EXPECT_NOT_POISONED(p); | |
3237 | EXPECT_EQ(0U, (uintptr_t)p % 4096); | |
3238 | free(p); | |
3239 | } | |
3240 | ||
92a42be0 SL |
3241 | // There's no memalign() on FreeBSD. |
3242 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
3243 | TEST(MemorySanitizer, memalign) { |
3244 | void *p = memalign(4096, 13); | |
5bcae85e | 3245 | EXPECT_EQ(0U, (uintptr_t)p % 4096); |
1a4d82fc JJ |
3246 | free(p); |
3247 | } | |
92a42be0 | 3248 | #endif |
1a4d82fc JJ |
3249 | |
3250 | TEST(MemorySanitizer, valloc) { | |
3251 | void *a = valloc(100); | |
5bcae85e SL |
3252 | uintptr_t PageSize = GetPageSize(); |
3253 | EXPECT_EQ(0U, (uintptr_t)a % PageSize); | |
1a4d82fc JJ |
3254 | free(a); |
3255 | } | |
3256 | ||
92a42be0 SL |
3257 | // There's no pvalloc() on FreeBSD. |
3258 | #if !defined(__FreeBSD__) | |
1a4d82fc | 3259 | TEST(MemorySanitizer, pvalloc) { |
5bcae85e SL |
3260 | uintptr_t PageSize = GetPageSize(); |
3261 | void *p = pvalloc(PageSize + 100); | |
3262 | EXPECT_EQ(0U, (uintptr_t)p % PageSize); | |
3263 | EXPECT_EQ(2 * PageSize, __sanitizer_get_allocated_size(p)); | |
1a4d82fc JJ |
3264 | free(p); |
3265 | ||
3266 | p = pvalloc(0); // pvalloc(0) should allocate at least one page. | |
5bcae85e SL |
3267 | EXPECT_EQ(0U, (uintptr_t)p % PageSize); |
3268 | EXPECT_EQ(PageSize, __sanitizer_get_allocated_size(p)); | |
1a4d82fc JJ |
3269 | free(p); |
3270 | } | |
92a42be0 | 3271 | #endif |
1a4d82fc JJ |
3272 | |
3273 | TEST(MemorySanitizer, inet_pton) { | |
3274 | const char *s = "1:0:0:0:0:0:0:8"; | |
3275 | unsigned char buf[sizeof(struct in6_addr)]; | |
3276 | int res = inet_pton(AF_INET6, s, buf); | |
3277 | ASSERT_EQ(1, res); | |
3278 | EXPECT_NOT_POISONED(buf[0]); | |
3279 | EXPECT_NOT_POISONED(buf[sizeof(struct in6_addr) - 1]); | |
3280 | ||
3281 | char s_out[INET6_ADDRSTRLEN]; | |
3282 | EXPECT_POISONED(s_out[3]); | |
3283 | const char *q = inet_ntop(AF_INET6, buf, s_out, INET6_ADDRSTRLEN); | |
3284 | ASSERT_NE((void*)0, q); | |
3285 | EXPECT_NOT_POISONED(s_out[3]); | |
3286 | } | |
3287 | ||
3288 | TEST(MemorySanitizer, inet_aton) { | |
3289 | const char *s = "127.0.0.1"; | |
3290 | struct in_addr in[2]; | |
3291 | int res = inet_aton(s, in); | |
3292 | ASSERT_NE(0, res); | |
3293 | EXPECT_NOT_POISONED(in[0]); | |
3294 | EXPECT_POISONED(*(char *)(in + 1)); | |
3295 | } | |
3296 | ||
3297 | TEST(MemorySanitizer, uname) { | |
3298 | struct utsname u; | |
3299 | int res = uname(&u); | |
3300 | ASSERT_EQ(0, res); | |
3301 | EXPECT_NOT_POISONED(strlen(u.sysname)); | |
3302 | EXPECT_NOT_POISONED(strlen(u.nodename)); | |
3303 | EXPECT_NOT_POISONED(strlen(u.release)); | |
3304 | EXPECT_NOT_POISONED(strlen(u.version)); | |
3305 | EXPECT_NOT_POISONED(strlen(u.machine)); | |
3306 | } | |
3307 | ||
3308 | TEST(MemorySanitizer, gethostname) { | |
3309 | char buf[100]; | |
3310 | int res = gethostname(buf, 100); | |
3311 | ASSERT_EQ(0, res); | |
3312 | EXPECT_NOT_POISONED(strlen(buf)); | |
3313 | } | |
3314 | ||
92a42be0 SL |
3315 | // There's no sysinfo() on FreeBSD. |
3316 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
3317 | TEST(MemorySanitizer, sysinfo) { |
3318 | struct sysinfo info; | |
3319 | int res = sysinfo(&info); | |
3320 | ASSERT_EQ(0, res); | |
3321 | EXPECT_NOT_POISONED(info); | |
3322 | } | |
92a42be0 | 3323 | #endif |
1a4d82fc JJ |
3324 | |
3325 | TEST(MemorySanitizer, getpwuid) { | |
3326 | struct passwd *p = getpwuid(0); // root | |
3327 | ASSERT_TRUE(p != NULL); | |
3328 | EXPECT_NOT_POISONED(p->pw_name); | |
3329 | ASSERT_TRUE(p->pw_name != NULL); | |
3330 | EXPECT_NOT_POISONED(p->pw_name[0]); | |
3331 | EXPECT_NOT_POISONED(p->pw_uid); | |
3332 | ASSERT_EQ(0U, p->pw_uid); | |
3333 | } | |
3334 | ||
3335 | TEST(MemorySanitizer, getpwuid_r) { | |
3336 | struct passwd pwd; | |
3337 | struct passwd *pwdres; | |
3338 | char buf[10000]; | |
3339 | int res = getpwuid_r(0, &pwd, buf, sizeof(buf), &pwdres); | |
3340 | ASSERT_EQ(0, res); | |
3341 | EXPECT_NOT_POISONED(pwd.pw_name); | |
3342 | ASSERT_TRUE(pwd.pw_name != NULL); | |
3343 | EXPECT_NOT_POISONED(pwd.pw_name[0]); | |
3344 | EXPECT_NOT_POISONED(pwd.pw_uid); | |
3345 | ASSERT_EQ(0U, pwd.pw_uid); | |
3346 | EXPECT_NOT_POISONED(pwdres); | |
3347 | } | |
3348 | ||
3349 | TEST(MemorySanitizer, getpwnam_r) { | |
3350 | struct passwd pwd; | |
3351 | struct passwd *pwdres; | |
3352 | char buf[10000]; | |
3353 | int res = getpwnam_r("root", &pwd, buf, sizeof(buf), &pwdres); | |
3354 | ASSERT_EQ(0, res); | |
3355 | EXPECT_NOT_POISONED(pwd.pw_name); | |
3356 | ASSERT_TRUE(pwd.pw_name != NULL); | |
3357 | EXPECT_NOT_POISONED(pwd.pw_name[0]); | |
3358 | EXPECT_NOT_POISONED(pwd.pw_uid); | |
3359 | ASSERT_EQ(0U, pwd.pw_uid); | |
3360 | EXPECT_NOT_POISONED(pwdres); | |
3361 | } | |
3362 | ||
3363 | TEST(MemorySanitizer, getpwnam_r_positive) { | |
3364 | struct passwd pwd; | |
3365 | struct passwd *pwdres; | |
3366 | char s[5]; | |
3367 | strncpy(s, "abcd", 5); | |
3368 | __msan_poison(s, 5); | |
3369 | char buf[10000]; | |
3370 | int res; | |
3371 | EXPECT_UMR(res = getpwnam_r(s, &pwd, buf, sizeof(buf), &pwdres)); | |
3372 | } | |
3373 | ||
3374 | TEST(MemorySanitizer, getgrnam_r) { | |
3375 | struct group grp; | |
3376 | struct group *grpres; | |
3377 | char buf[10000]; | |
92a42be0 | 3378 | int res = getgrnam_r(SUPERUSER_GROUP, &grp, buf, sizeof(buf), &grpres); |
1a4d82fc | 3379 | ASSERT_EQ(0, res); |
92a42be0 SL |
3380 | // Note that getgrnam_r() returns 0 if the matching group is not found. |
3381 | ASSERT_NE(nullptr, grpres); | |
1a4d82fc JJ |
3382 | EXPECT_NOT_POISONED(grp.gr_name); |
3383 | ASSERT_TRUE(grp.gr_name != NULL); | |
3384 | EXPECT_NOT_POISONED(grp.gr_name[0]); | |
3385 | EXPECT_NOT_POISONED(grp.gr_gid); | |
3386 | EXPECT_NOT_POISONED(grpres); | |
3387 | } | |
3388 | ||
3389 | TEST(MemorySanitizer, getpwent) { | |
3390 | setpwent(); | |
3391 | struct passwd *p = getpwent(); | |
3392 | ASSERT_TRUE(p != NULL); | |
3393 | EXPECT_NOT_POISONED(p->pw_name); | |
3394 | ASSERT_TRUE(p->pw_name != NULL); | |
3395 | EXPECT_NOT_POISONED(p->pw_name[0]); | |
3396 | EXPECT_NOT_POISONED(p->pw_uid); | |
3397 | } | |
3398 | ||
3399 | TEST(MemorySanitizer, getpwent_r) { | |
3400 | struct passwd pwd; | |
3401 | struct passwd *pwdres; | |
3402 | char buf[10000]; | |
3403 | setpwent(); | |
3404 | int res = getpwent_r(&pwd, buf, sizeof(buf), &pwdres); | |
3405 | ASSERT_EQ(0, res); | |
3406 | EXPECT_NOT_POISONED(pwd.pw_name); | |
3407 | ASSERT_TRUE(pwd.pw_name != NULL); | |
3408 | EXPECT_NOT_POISONED(pwd.pw_name[0]); | |
3409 | EXPECT_NOT_POISONED(pwd.pw_uid); | |
3410 | EXPECT_NOT_POISONED(pwdres); | |
3411 | } | |
3412 | ||
92a42be0 SL |
3413 | // There's no fgetpwent() on FreeBSD. |
3414 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
3415 | TEST(MemorySanitizer, fgetpwent) { |
3416 | FILE *fp = fopen("/etc/passwd", "r"); | |
3417 | struct passwd *p = fgetpwent(fp); | |
3418 | ASSERT_TRUE(p != NULL); | |
3419 | EXPECT_NOT_POISONED(p->pw_name); | |
3420 | ASSERT_TRUE(p->pw_name != NULL); | |
3421 | EXPECT_NOT_POISONED(p->pw_name[0]); | |
3422 | EXPECT_NOT_POISONED(p->pw_uid); | |
3423 | fclose(fp); | |
3424 | } | |
92a42be0 | 3425 | #endif |
1a4d82fc JJ |
3426 | |
3427 | TEST(MemorySanitizer, getgrent) { | |
3428 | setgrent(); | |
3429 | struct group *p = getgrent(); | |
3430 | ASSERT_TRUE(p != NULL); | |
3431 | EXPECT_NOT_POISONED(p->gr_name); | |
3432 | ASSERT_TRUE(p->gr_name != NULL); | |
3433 | EXPECT_NOT_POISONED(p->gr_name[0]); | |
3434 | EXPECT_NOT_POISONED(p->gr_gid); | |
3435 | } | |
3436 | ||
92a42be0 SL |
3437 | // There's no fgetgrent() on FreeBSD. |
3438 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
3439 | TEST(MemorySanitizer, fgetgrent) { |
3440 | FILE *fp = fopen("/etc/group", "r"); | |
3441 | struct group *grp = fgetgrent(fp); | |
3442 | ASSERT_TRUE(grp != NULL); | |
3443 | EXPECT_NOT_POISONED(grp->gr_name); | |
3444 | ASSERT_TRUE(grp->gr_name != NULL); | |
3445 | EXPECT_NOT_POISONED(grp->gr_name[0]); | |
3446 | EXPECT_NOT_POISONED(grp->gr_gid); | |
3447 | for (char **p = grp->gr_mem; *p; ++p) { | |
3448 | EXPECT_NOT_POISONED((*p)[0]); | |
3449 | EXPECT_TRUE(strlen(*p) > 0); | |
3450 | } | |
3451 | fclose(fp); | |
3452 | } | |
92a42be0 | 3453 | #endif |
1a4d82fc JJ |
3454 | |
3455 | TEST(MemorySanitizer, getgrent_r) { | |
3456 | struct group grp; | |
3457 | struct group *grpres; | |
3458 | char buf[10000]; | |
3459 | setgrent(); | |
3460 | int res = getgrent_r(&grp, buf, sizeof(buf), &grpres); | |
3461 | ASSERT_EQ(0, res); | |
3462 | EXPECT_NOT_POISONED(grp.gr_name); | |
3463 | ASSERT_TRUE(grp.gr_name != NULL); | |
3464 | EXPECT_NOT_POISONED(grp.gr_name[0]); | |
3465 | EXPECT_NOT_POISONED(grp.gr_gid); | |
3466 | EXPECT_NOT_POISONED(grpres); | |
3467 | } | |
3468 | ||
92a42be0 SL |
3469 | // There's no fgetgrent_r() on FreeBSD. |
3470 | #if !defined(__FreeBSD__) | |
1a4d82fc JJ |
3471 | TEST(MemorySanitizer, fgetgrent_r) { |
3472 | FILE *fp = fopen("/etc/group", "r"); | |
3473 | struct group grp; | |
3474 | struct group *grpres; | |
3475 | char buf[10000]; | |
3476 | setgrent(); | |
3477 | int res = fgetgrent_r(fp, &grp, buf, sizeof(buf), &grpres); | |
3478 | ASSERT_EQ(0, res); | |
3479 | EXPECT_NOT_POISONED(grp.gr_name); | |
3480 | ASSERT_TRUE(grp.gr_name != NULL); | |
3481 | EXPECT_NOT_POISONED(grp.gr_name[0]); | |
3482 | EXPECT_NOT_POISONED(grp.gr_gid); | |
3483 | EXPECT_NOT_POISONED(grpres); | |
3484 | fclose(fp); | |
3485 | } | |
92a42be0 | 3486 | #endif |
1a4d82fc JJ |
3487 | |
3488 | TEST(MemorySanitizer, getgroups) { | |
3489 | int n = getgroups(0, 0); | |
3490 | gid_t *gids = new gid_t[n]; | |
3491 | int res = getgroups(n, gids); | |
3492 | ASSERT_EQ(n, res); | |
3493 | for (int i = 0; i < n; ++i) | |
3494 | EXPECT_NOT_POISONED(gids[i]); | |
3495 | } | |
3496 | ||
3497 | TEST(MemorySanitizer, wordexp) { | |
3498 | wordexp_t w; | |
3499 | int res = wordexp("a b c", &w, 0); | |
3500 | ASSERT_EQ(0, res); | |
3501 | ASSERT_EQ(3U, w.we_wordc); | |
3502 | ASSERT_STREQ("a", w.we_wordv[0]); | |
3503 | ASSERT_STREQ("b", w.we_wordv[1]); | |
3504 | ASSERT_STREQ("c", w.we_wordv[2]); | |
3505 | } | |
3506 | ||
3507 | template<class T> | |
3508 | static bool applySlt(T value, T shadow) { | |
3509 | __msan_partial_poison(&value, &shadow, sizeof(T)); | |
3510 | volatile bool zzz = true; | |
3511 | // This "|| zzz" trick somehow makes LLVM emit "icmp slt" instead of | |
3512 | // a shift-and-trunc to get at the highest bit. | |
3513 | volatile bool v = value < 0 || zzz; | |
3514 | return v; | |
3515 | } | |
3516 | ||
3517 | TEST(MemorySanitizer, SignedCompareWithZero) { | |
3518 | EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0xF)); | |
3519 | EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0xFF)); | |
3520 | EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0xFFFFFF)); | |
3521 | EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0x7FFFFFF)); | |
3522 | EXPECT_UMR(applySlt<S4>(0xF, 0x80FFFFFF)); | |
3523 | EXPECT_UMR(applySlt<S4>(0xF, 0xFFFFFFFF)); | |
3524 | } | |
3525 | ||
3526 | template <class T, class S> | |
3527 | static T poisoned(T Va, S Sa) { | |
3528 | char SIZE_CHECK1[(ssize_t)sizeof(T) - (ssize_t)sizeof(S)]; | |
3529 | char SIZE_CHECK2[(ssize_t)sizeof(S) - (ssize_t)sizeof(T)]; | |
3530 | T a; | |
3531 | a = Va; | |
3532 | __msan_partial_poison(&a, &Sa, sizeof(T)); | |
3533 | return a; | |
3534 | } | |
3535 | ||
3536 | TEST(MemorySanitizer, ICmpRelational) { | |
3537 | EXPECT_NOT_POISONED(poisoned(0, 0) < poisoned(0, 0)); | |
3538 | EXPECT_NOT_POISONED(poisoned(0U, 0) < poisoned(0U, 0)); | |
3539 | EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) < poisoned(0LL, 0LLU)); | |
3540 | EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) < poisoned(0LLU, 0LLU)); | |
3541 | EXPECT_POISONED(poisoned(0xFF, 0xFF) < poisoned(0xFF, 0xFF)); | |
3542 | EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) < | |
3543 | poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); | |
3544 | EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) < | |
3545 | poisoned(-1, 0xFFFFFFFFU)); | |
3546 | ||
3547 | EXPECT_NOT_POISONED(poisoned(0, 0) <= poisoned(0, 0)); | |
3548 | EXPECT_NOT_POISONED(poisoned(0U, 0) <= poisoned(0U, 0)); | |
3549 | EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) <= poisoned(0LL, 0LLU)); | |
3550 | EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) <= poisoned(0LLU, 0LLU)); | |
3551 | EXPECT_POISONED(poisoned(0xFF, 0xFF) <= poisoned(0xFF, 0xFF)); | |
3552 | EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) <= | |
3553 | poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); | |
3554 | EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) <= | |
3555 | poisoned(-1, 0xFFFFFFFFU)); | |
3556 | ||
3557 | EXPECT_NOT_POISONED(poisoned(0, 0) > poisoned(0, 0)); | |
3558 | EXPECT_NOT_POISONED(poisoned(0U, 0) > poisoned(0U, 0)); | |
3559 | EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) > poisoned(0LL, 0LLU)); | |
3560 | EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) > poisoned(0LLU, 0LLU)); | |
3561 | EXPECT_POISONED(poisoned(0xFF, 0xFF) > poisoned(0xFF, 0xFF)); | |
3562 | EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) > | |
3563 | poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); | |
3564 | EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) > | |
3565 | poisoned(-1, 0xFFFFFFFFU)); | |
3566 | ||
3567 | EXPECT_NOT_POISONED(poisoned(0, 0) >= poisoned(0, 0)); | |
3568 | EXPECT_NOT_POISONED(poisoned(0U, 0) >= poisoned(0U, 0)); | |
3569 | EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) >= poisoned(0LL, 0LLU)); | |
3570 | EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) >= poisoned(0LLU, 0LLU)); | |
3571 | EXPECT_POISONED(poisoned(0xFF, 0xFF) >= poisoned(0xFF, 0xFF)); | |
3572 | EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) >= | |
3573 | poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); | |
3574 | EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) >= | |
3575 | poisoned(-1, 0xFFFFFFFFU)); | |
3576 | ||
3577 | EXPECT_POISONED(poisoned(6, 0xF) > poisoned(7, 0)); | |
3578 | EXPECT_POISONED(poisoned(0xF, 0xF) > poisoned(7, 0)); | |
3579 | ||
3580 | EXPECT_NOT_POISONED(poisoned(-1, 0x80000000U) >= poisoned(-1, 0U)); | |
3581 | } | |
3582 | ||
3583 | #if MSAN_HAS_M128 | |
3584 | TEST(MemorySanitizer, ICmpVectorRelational) { | |
3585 | EXPECT_NOT_POISONED( | |
3586 | _mm_cmplt_epi16(poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0)), | |
3587 | poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0)))); | |
3588 | EXPECT_NOT_POISONED( | |
3589 | _mm_cmplt_epi16(poisoned(_mm_set1_epi32(0), _mm_set1_epi32(0)), | |
3590 | poisoned(_mm_set1_epi32(0), _mm_set1_epi32(0)))); | |
3591 | EXPECT_POISONED( | |
3592 | _mm_cmplt_epi16(poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0xFFFF)), | |
3593 | poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0xFFFF)))); | |
3594 | EXPECT_POISONED(_mm_cmpgt_epi16(poisoned(_mm_set1_epi16(6), _mm_set1_epi16(0xF)), | |
3595 | poisoned(_mm_set1_epi16(7), _mm_set1_epi16(0)))); | |
3596 | } | |
3597 | #endif | |
3598 | ||
3599 | // Volatile bitfield store is implemented as load-mask-store | |
3600 | // Test that we don't warn on the store of (uninitialized) padding. | |
3601 | struct VolatileBitfieldStruct { | |
3602 | volatile unsigned x : 1; | |
3603 | unsigned y : 1; | |
3604 | }; | |
3605 | ||
3606 | TEST(MemorySanitizer, VolatileBitfield) { | |
3607 | VolatileBitfieldStruct *S = new VolatileBitfieldStruct; | |
3608 | S->x = 1; | |
3609 | EXPECT_NOT_POISONED((unsigned)S->x); | |
3610 | EXPECT_POISONED((unsigned)S->y); | |
3611 | } | |
3612 | ||
3613 | TEST(MemorySanitizer, UnalignedLoad) { | |
92a42be0 | 3614 | char x[32] __attribute__((aligned(8))); |
1a4d82fc JJ |
3615 | U4 origin = __LINE__; |
3616 | for (unsigned i = 0; i < sizeof(x) / 4; ++i) | |
3617 | __msan_set_origin(x + 4 * i, 4, origin + i); | |
3618 | ||
3619 | memset(x + 8, 0, 16); | |
3620 | EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 6), origin + 1); | |
3621 | EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 7), origin + 1); | |
3622 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x + 8)); | |
3623 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x + 9)); | |
3624 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x + 22)); | |
3625 | EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 23), origin + 6); | |
3626 | EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 24), origin + 6); | |
3627 | ||
3628 | EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 4), origin + 1); | |
3629 | EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 7), origin + 1); | |
3630 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x + 8)); | |
3631 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x + 9)); | |
3632 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x + 20)); | |
3633 | EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 21), origin + 6); | |
3634 | EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 24), origin + 6); | |
3635 | ||
3636 | EXPECT_POISONED_O(__sanitizer_unaligned_load64(x), origin); | |
3637 | EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 1), origin); | |
3638 | EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 7), origin + 1); | |
3639 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x + 8)); | |
3640 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x + 9)); | |
3641 | EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x + 16)); | |
3642 | EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 17), origin + 6); | |
3643 | EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 21), origin + 6); | |
3644 | EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 24), origin + 6); | |
3645 | } | |
3646 | ||
3647 | TEST(MemorySanitizer, UnalignedStore16) { | |
92a42be0 | 3648 | char x[5] __attribute__((aligned(4))); |
1a4d82fc JJ |
3649 | U2 y2 = 0; |
3650 | U4 origin = __LINE__; | |
3651 | __msan_poison(&y2, 1); | |
3652 | __msan_set_origin(&y2, 1, origin); | |
3653 | ||
3654 | __sanitizer_unaligned_store16(x + 1, y2); | |
3655 | EXPECT_POISONED_O(x[0], origin); | |
3656 | EXPECT_POISONED_O(x[1], origin); | |
3657 | EXPECT_NOT_POISONED(x[2]); | |
3658 | EXPECT_POISONED_O(x[3], origin); | |
1a4d82fc JJ |
3659 | } |
3660 | ||
3661 | TEST(MemorySanitizer, UnalignedStore32) { | |
92a42be0 | 3662 | char x[8] __attribute__((aligned(4))); |
1a4d82fc JJ |
3663 | U4 y4 = 0; |
3664 | U4 origin = __LINE__; | |
3665 | __msan_poison(&y4, 2); | |
3666 | __msan_set_origin(&y4, 2, origin); | |
3667 | ||
3668 | __sanitizer_unaligned_store32(x + 3, y4); | |
3669 | EXPECT_POISONED_O(x[0], origin); | |
3670 | EXPECT_POISONED_O(x[1], origin); | |
3671 | EXPECT_POISONED_O(x[2], origin); | |
3672 | EXPECT_POISONED_O(x[3], origin); | |
3673 | EXPECT_POISONED_O(x[4], origin); | |
3674 | EXPECT_NOT_POISONED(x[5]); | |
3675 | EXPECT_NOT_POISONED(x[6]); | |
3676 | EXPECT_POISONED_O(x[7], origin); | |
3677 | } | |
3678 | ||
3679 | TEST(MemorySanitizer, UnalignedStore64) { | |
92a42be0 | 3680 | char x[16] __attribute__((aligned(8))); |
1a4d82fc JJ |
3681 | U8 y8 = 0; |
3682 | U4 origin = __LINE__; | |
3683 | __msan_poison(&y8, 3); | |
3684 | __msan_poison(((char *)&y8) + sizeof(y8) - 2, 1); | |
3685 | __msan_set_origin(&y8, 8, origin); | |
3686 | ||
3687 | __sanitizer_unaligned_store64(x + 3, y8); | |
3688 | EXPECT_POISONED_O(x[0], origin); | |
3689 | EXPECT_POISONED_O(x[1], origin); | |
3690 | EXPECT_POISONED_O(x[2], origin); | |
3691 | EXPECT_POISONED_O(x[3], origin); | |
3692 | EXPECT_POISONED_O(x[4], origin); | |
3693 | EXPECT_POISONED_O(x[5], origin); | |
3694 | EXPECT_NOT_POISONED(x[6]); | |
3695 | EXPECT_NOT_POISONED(x[7]); | |
3696 | EXPECT_NOT_POISONED(x[8]); | |
3697 | EXPECT_POISONED_O(x[9], origin); | |
3698 | EXPECT_NOT_POISONED(x[10]); | |
3699 | EXPECT_POISONED_O(x[11], origin); | |
3700 | } | |
3701 | ||
3702 | TEST(MemorySanitizer, UnalignedStore16_precise) { | |
92a42be0 | 3703 | char x[8] __attribute__((aligned(4))); |
1a4d82fc JJ |
3704 | U2 y = 0; |
3705 | U4 originx1 = __LINE__; | |
3706 | U4 originx2 = __LINE__; | |
3707 | U4 originy = __LINE__; | |
3708 | __msan_poison(x, sizeof(x)); | |
3709 | __msan_set_origin(x, 4, originx1); | |
3710 | __msan_set_origin(x + 4, 4, originx2); | |
3711 | __msan_poison(((char *)&y) + 1, 1); | |
3712 | __msan_set_origin(&y, sizeof(y), originy); | |
3713 | ||
3714 | __sanitizer_unaligned_store16(x + 3, y); | |
3715 | EXPECT_POISONED_O(x[0], originx1); | |
3716 | EXPECT_POISONED_O(x[1], originx1); | |
3717 | EXPECT_POISONED_O(x[2], originx1); | |
3718 | EXPECT_NOT_POISONED(x[3]); | |
3719 | EXPECT_POISONED_O(x[4], originy); | |
3720 | EXPECT_POISONED_O(x[5], originy); | |
3721 | EXPECT_POISONED_O(x[6], originy); | |
3722 | EXPECT_POISONED_O(x[7], originy); | |
3723 | } | |
3724 | ||
3725 | TEST(MemorySanitizer, UnalignedStore16_precise2) { | |
92a42be0 | 3726 | char x[8] __attribute__((aligned(4))); |
1a4d82fc JJ |
3727 | U2 y = 0; |
3728 | U4 originx1 = __LINE__; | |
3729 | U4 originx2 = __LINE__; | |
3730 | U4 originy = __LINE__; | |
3731 | __msan_poison(x, sizeof(x)); | |
3732 | __msan_set_origin(x, 4, originx1); | |
3733 | __msan_set_origin(x + 4, 4, originx2); | |
3734 | __msan_poison(((char *)&y), 1); | |
3735 | __msan_set_origin(&y, sizeof(y), originy); | |
3736 | ||
3737 | __sanitizer_unaligned_store16(x + 3, y); | |
3738 | EXPECT_POISONED_O(x[0], originy); | |
3739 | EXPECT_POISONED_O(x[1], originy); | |
3740 | EXPECT_POISONED_O(x[2], originy); | |
3741 | EXPECT_POISONED_O(x[3], originy); | |
3742 | EXPECT_NOT_POISONED(x[4]); | |
3743 | EXPECT_POISONED_O(x[5], originx2); | |
3744 | EXPECT_POISONED_O(x[6], originx2); | |
3745 | EXPECT_POISONED_O(x[7], originx2); | |
3746 | } | |
3747 | ||
3748 | TEST(MemorySanitizer, UnalignedStore64_precise) { | |
92a42be0 | 3749 | char x[12] __attribute__((aligned(8))); |
1a4d82fc JJ |
3750 | U8 y = 0; |
3751 | U4 originx1 = __LINE__; | |
3752 | U4 originx2 = __LINE__; | |
3753 | U4 originx3 = __LINE__; | |
3754 | U4 originy = __LINE__; | |
3755 | __msan_poison(x, sizeof(x)); | |
3756 | __msan_set_origin(x, 4, originx1); | |
3757 | __msan_set_origin(x + 4, 4, originx2); | |
3758 | __msan_set_origin(x + 8, 4, originx3); | |
3759 | __msan_poison(((char *)&y) + 1, 1); | |
3760 | __msan_poison(((char *)&y) + 7, 1); | |
3761 | __msan_set_origin(&y, sizeof(y), originy); | |
3762 | ||
3763 | __sanitizer_unaligned_store64(x + 2, y); | |
3764 | EXPECT_POISONED_O(x[0], originy); | |
3765 | EXPECT_POISONED_O(x[1], originy); | |
3766 | EXPECT_NOT_POISONED(x[2]); | |
3767 | EXPECT_POISONED_O(x[3], originy); | |
3768 | ||
3769 | EXPECT_NOT_POISONED(x[4]); | |
3770 | EXPECT_NOT_POISONED(x[5]); | |
3771 | EXPECT_NOT_POISONED(x[6]); | |
3772 | EXPECT_NOT_POISONED(x[7]); | |
3773 | ||
3774 | EXPECT_NOT_POISONED(x[8]); | |
3775 | EXPECT_POISONED_O(x[9], originy); | |
3776 | EXPECT_POISONED_O(x[10], originy); | |
3777 | EXPECT_POISONED_O(x[11], originy); | |
3778 | } | |
3779 | ||
3780 | TEST(MemorySanitizer, UnalignedStore64_precise2) { | |
92a42be0 | 3781 | char x[12] __attribute__((aligned(8))); |
1a4d82fc JJ |
3782 | U8 y = 0; |
3783 | U4 originx1 = __LINE__; | |
3784 | U4 originx2 = __LINE__; | |
3785 | U4 originx3 = __LINE__; | |
3786 | U4 originy = __LINE__; | |
3787 | __msan_poison(x, sizeof(x)); | |
3788 | __msan_set_origin(x, 4, originx1); | |
3789 | __msan_set_origin(x + 4, 4, originx2); | |
3790 | __msan_set_origin(x + 8, 4, originx3); | |
3791 | __msan_poison(((char *)&y) + 3, 3); | |
3792 | __msan_set_origin(&y, sizeof(y), originy); | |
3793 | ||
3794 | __sanitizer_unaligned_store64(x + 2, y); | |
3795 | EXPECT_POISONED_O(x[0], originx1); | |
3796 | EXPECT_POISONED_O(x[1], originx1); | |
3797 | EXPECT_NOT_POISONED(x[2]); | |
3798 | EXPECT_NOT_POISONED(x[3]); | |
3799 | ||
3800 | EXPECT_NOT_POISONED(x[4]); | |
3801 | EXPECT_POISONED_O(x[5], originy); | |
3802 | EXPECT_POISONED_O(x[6], originy); | |
3803 | EXPECT_POISONED_O(x[7], originy); | |
3804 | ||
3805 | EXPECT_NOT_POISONED(x[8]); | |
3806 | EXPECT_NOT_POISONED(x[9]); | |
3807 | EXPECT_POISONED_O(x[10], originx3); | |
3808 | EXPECT_POISONED_O(x[11], originx3); | |
3809 | } | |
3810 | ||
92a42be0 | 3811 | #if (defined(__x86_64__) && defined(__clang__)) |
1a4d82fc | 3812 | namespace { |
92a42be0 | 3813 | typedef U1 V16x8 __attribute__((__vector_size__(16))); |
1a4d82fc JJ |
3814 | typedef U2 V8x16 __attribute__((__vector_size__(16))); |
3815 | typedef U4 V4x32 __attribute__((__vector_size__(16))); | |
3816 | typedef U8 V2x64 __attribute__((__vector_size__(16))); | |
3817 | typedef U4 V8x32 __attribute__((__vector_size__(32))); | |
3818 | typedef U8 V4x64 __attribute__((__vector_size__(32))); | |
92a42be0 SL |
3819 | typedef U4 V2x32 __attribute__((__vector_size__(8))); |
3820 | typedef U2 V4x16 __attribute__((__vector_size__(8))); | |
3821 | typedef U1 V8x8 __attribute__((__vector_size__(8))); | |
1a4d82fc JJ |
3822 | |
3823 | ||
3824 | V8x16 shift_sse2_left_scalar(V8x16 x, U4 y) { | |
3825 | return _mm_slli_epi16(x, y); | |
3826 | } | |
3827 | ||
3828 | V8x16 shift_sse2_left(V8x16 x, V8x16 y) { | |
3829 | return _mm_sll_epi16(x, y); | |
3830 | } | |
3831 | ||
3832 | TEST(VectorShiftTest, sse2_left_scalar) { | |
92a42be0 | 3833 | V8x16 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3, 4, 5, 6, 7}; |
1a4d82fc JJ |
3834 | V8x16 u = shift_sse2_left_scalar(v, 2); |
3835 | EXPECT_POISONED(u[0]); | |
3836 | EXPECT_POISONED(u[1]); | |
92a42be0 SL |
3837 | EXPECT_NOT_POISONED(u[0] | (3U << 2)); |
3838 | EXPECT_NOT_POISONED(u[1] | (7U << 2)); | |
1a4d82fc JJ |
3839 | u[0] = u[1] = 0; |
3840 | EXPECT_NOT_POISONED(u); | |
3841 | } | |
3842 | ||
3843 | TEST(VectorShiftTest, sse2_left_scalar_by_uninit) { | |
3844 | V8x16 v = {0, 1, 2, 3, 4, 5, 6, 7}; | |
92a42be0 | 3845 | V8x16 u = shift_sse2_left_scalar(v, Poisoned<U4>()); |
1a4d82fc JJ |
3846 | EXPECT_POISONED(u[0]); |
3847 | EXPECT_POISONED(u[1]); | |
3848 | EXPECT_POISONED(u[2]); | |
3849 | EXPECT_POISONED(u[3]); | |
3850 | EXPECT_POISONED(u[4]); | |
3851 | EXPECT_POISONED(u[5]); | |
3852 | EXPECT_POISONED(u[6]); | |
3853 | EXPECT_POISONED(u[7]); | |
3854 | } | |
3855 | ||
3856 | TEST(VectorShiftTest, sse2_left) { | |
92a42be0 | 3857 | V8x16 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3, 4, 5, 6, 7}; |
1a4d82fc | 3858 | // Top 64 bits of shift count don't affect the result. |
92a42be0 | 3859 | V2x64 s = {2, Poisoned<U8>()}; |
1a4d82fc JJ |
3860 | V8x16 u = shift_sse2_left(v, s); |
3861 | EXPECT_POISONED(u[0]); | |
3862 | EXPECT_POISONED(u[1]); | |
92a42be0 SL |
3863 | EXPECT_NOT_POISONED(u[0] | (3U << 2)); |
3864 | EXPECT_NOT_POISONED(u[1] | (7U << 2)); | |
1a4d82fc JJ |
3865 | u[0] = u[1] = 0; |
3866 | EXPECT_NOT_POISONED(u); | |
3867 | } | |
3868 | ||
3869 | TEST(VectorShiftTest, sse2_left_by_uninit) { | |
92a42be0 SL |
3870 | V8x16 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3, 4, 5, 6, 7}; |
3871 | V2x64 s = {Poisoned<U8>(), Poisoned<U8>()}; | |
1a4d82fc JJ |
3872 | V8x16 u = shift_sse2_left(v, s); |
3873 | EXPECT_POISONED(u[0]); | |
3874 | EXPECT_POISONED(u[1]); | |
3875 | EXPECT_POISONED(u[2]); | |
3876 | EXPECT_POISONED(u[3]); | |
3877 | EXPECT_POISONED(u[4]); | |
3878 | EXPECT_POISONED(u[5]); | |
3879 | EXPECT_POISONED(u[6]); | |
3880 | EXPECT_POISONED(u[7]); | |
3881 | } | |
3882 | ||
3883 | #ifdef __AVX2__ | |
3884 | V4x32 shift_avx2_left(V4x32 x, V4x32 y) { | |
3885 | return _mm_sllv_epi32(x, y); | |
3886 | } | |
3887 | // This is variable vector shift that's only available starting with AVX2. | |
3888 | // V4x32 shift_avx2_left(V4x32 x, V4x32 y) { | |
3889 | TEST(VectorShiftTest, avx2_left) { | |
92a42be0 SL |
3890 | V4x32 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3}; |
3891 | V4x32 s = {2, Poisoned<U4>(), 3, Poisoned<U4>()}; | |
1a4d82fc JJ |
3892 | V4x32 u = shift_avx2_left(v, s); |
3893 | EXPECT_POISONED(u[0]); | |
3894 | EXPECT_NOT_POISONED(u[0] | (~7U)); | |
3895 | EXPECT_POISONED(u[1]); | |
3896 | EXPECT_POISONED(u[1] | (~31U)); | |
3897 | EXPECT_NOT_POISONED(u[2]); | |
3898 | EXPECT_POISONED(u[3]); | |
3899 | EXPECT_POISONED(u[3] | (~31U)); | |
3900 | } | |
3901 | #endif // __AVX2__ | |
3902 | } // namespace | |
3903 | ||
92a42be0 SL |
3904 | TEST(VectorPackTest, sse2_packssdw_128) { |
3905 | const unsigned S2_max = (1 << 15) - 1; | |
3906 | V4x32 a = {Poisoned<U4>(0, 0xFF0000), Poisoned<U4>(0, 0xFFFF0000), | |
3907 | S2_max + 100, 4}; | |
3908 | V4x32 b = {Poisoned<U4>(0, 0xFF), S2_max + 10000, Poisoned<U4>(0, 0xFF00), | |
3909 | S2_max}; | |
1a4d82fc | 3910 | |
92a42be0 | 3911 | V8x16 c = _mm_packs_epi32(a, b); |
1a4d82fc | 3912 | |
92a42be0 SL |
3913 | EXPECT_POISONED(c[0]); |
3914 | EXPECT_POISONED(c[1]); | |
3915 | EXPECT_NOT_POISONED(c[2]); | |
3916 | EXPECT_NOT_POISONED(c[3]); | |
3917 | EXPECT_POISONED(c[4]); | |
3918 | EXPECT_NOT_POISONED(c[5]); | |
3919 | EXPECT_POISONED(c[6]); | |
3920 | EXPECT_NOT_POISONED(c[7]); | |
1a4d82fc | 3921 | |
92a42be0 SL |
3922 | EXPECT_EQ(c[2], S2_max); |
3923 | EXPECT_EQ(c[3], 4); | |
3924 | EXPECT_EQ(c[5], S2_max); | |
3925 | EXPECT_EQ(c[7], S2_max); | |
1a4d82fc JJ |
3926 | } |
3927 | ||
92a42be0 SL |
3928 | TEST(VectorPackTest, mmx_packuswb) { |
3929 | const unsigned U1_max = (1 << 8) - 1; | |
3930 | V4x16 a = {Poisoned<U2>(0, 0xFF00), Poisoned<U2>(0, 0xF000U), U1_max + 100, | |
3931 | 4}; | |
3932 | V4x16 b = {Poisoned<U2>(0, 0xFF), U1_max - 1, Poisoned<U2>(0, 0xF), U1_max}; | |
3933 | V8x8 c = _mm_packs_pu16(a, b); | |
1a4d82fc | 3934 | |
92a42be0 SL |
3935 | EXPECT_POISONED(c[0]); |
3936 | EXPECT_POISONED(c[1]); | |
3937 | EXPECT_NOT_POISONED(c[2]); | |
3938 | EXPECT_NOT_POISONED(c[3]); | |
3939 | EXPECT_POISONED(c[4]); | |
3940 | EXPECT_NOT_POISONED(c[5]); | |
3941 | EXPECT_POISONED(c[6]); | |
3942 | EXPECT_NOT_POISONED(c[7]); | |
1a4d82fc | 3943 | |
92a42be0 SL |
3944 | EXPECT_EQ(c[2], U1_max); |
3945 | EXPECT_EQ(c[3], 4); | |
3946 | EXPECT_EQ(c[5], U1_max - 1); | |
3947 | EXPECT_EQ(c[7], U1_max); | |
1a4d82fc JJ |
3948 | } |
3949 | ||
92a42be0 SL |
3950 | TEST(VectorSadTest, sse2_psad_bw) { |
3951 | V16x8 a = {Poisoned<U1>(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; | |
3952 | V16x8 b = {100, 101, 102, 103, 104, 105, 106, 107, | |
3953 | 108, 109, 110, 111, 112, 113, 114, 115}; | |
3954 | V2x64 c = _mm_sad_epu8(a, b); | |
3955 | ||
3956 | EXPECT_POISONED(c[0]); | |
3957 | EXPECT_NOT_POISONED(c[1]); | |
3958 | ||
3959 | EXPECT_EQ(800U, c[1]); | |
1a4d82fc JJ |
3960 | } |
3961 | ||
92a42be0 SL |
3962 | TEST(VectorMaddTest, mmx_pmadd_wd) { |
3963 | V4x16 a = {Poisoned<U2>(), 1, 2, 3}; | |
3964 | V4x16 b = {100, 101, 102, 103}; | |
3965 | V2x32 c = _mm_madd_pi16(a, b); | |
3966 | ||
3967 | EXPECT_POISONED(c[0]); | |
3968 | EXPECT_NOT_POISONED(c[1]); | |
3969 | ||
3970 | EXPECT_EQ((unsigned)(2 * 102 + 3 * 103), c[1]); | |
1a4d82fc | 3971 | } |
5bcae85e SL |
3972 | |
3973 | TEST(VectorCmpTest, mm_cmpneq_ps) { | |
3974 | V4x32 c; | |
3975 | c = _mm_cmpneq_ps(V4x32{Poisoned<U4>(), 1, 2, 3}, V4x32{4, 5, Poisoned<U4>(), 6}); | |
3976 | EXPECT_POISONED(c[0]); | |
3977 | EXPECT_NOT_POISONED(c[1]); | |
3978 | EXPECT_POISONED(c[2]); | |
3979 | EXPECT_NOT_POISONED(c[3]); | |
3980 | ||
3981 | c = _mm_cmpneq_ps(V4x32{0, 1, 2, 3}, V4x32{4, 5, 6, 7}); | |
3982 | EXPECT_NOT_POISONED(c); | |
3983 | } | |
3984 | ||
3985 | TEST(VectorCmpTest, mm_cmpneq_sd) { | |
3986 | V2x64 c; | |
3987 | c = _mm_cmpneq_sd(V2x64{Poisoned<U8>(), 1}, V2x64{2, 3}); | |
3988 | EXPECT_POISONED(c[0]); | |
3989 | c = _mm_cmpneq_sd(V2x64{1, 2}, V2x64{Poisoned<U8>(), 3}); | |
3990 | EXPECT_POISONED(c[0]); | |
3991 | c = _mm_cmpneq_sd(V2x64{1, 2}, V2x64{3, 4}); | |
3992 | EXPECT_NOT_POISONED(c[0]); | |
3993 | c = _mm_cmpneq_sd(V2x64{1, Poisoned<U8>()}, V2x64{2, Poisoned<U8>()}); | |
3994 | EXPECT_NOT_POISONED(c[0]); | |
3995 | c = _mm_cmpneq_sd(V2x64{1, Poisoned<U8>()}, V2x64{1, Poisoned<U8>()}); | |
3996 | EXPECT_NOT_POISONED(c[0]); | |
3997 | } | |
3998 | ||
3999 | TEST(VectorCmpTest, builtin_ia32_ucomisdlt) { | |
4000 | U4 c; | |
4001 | c = __builtin_ia32_ucomisdlt(V2x64{Poisoned<U8>(), 1}, V2x64{2, 3}); | |
4002 | EXPECT_POISONED(c); | |
4003 | c = __builtin_ia32_ucomisdlt(V2x64{1, 2}, V2x64{Poisoned<U8>(), 3}); | |
4004 | EXPECT_POISONED(c); | |
4005 | c = __builtin_ia32_ucomisdlt(V2x64{1, 2}, V2x64{3, 4}); | |
4006 | EXPECT_NOT_POISONED(c); | |
4007 | c = __builtin_ia32_ucomisdlt(V2x64{1, Poisoned<U8>()}, V2x64{2, Poisoned<U8>()}); | |
4008 | EXPECT_NOT_POISONED(c); | |
4009 | c = __builtin_ia32_ucomisdlt(V2x64{1, Poisoned<U8>()}, V2x64{1, Poisoned<U8>()}); | |
4010 | EXPECT_NOT_POISONED(c); | |
4011 | } | |
4012 | ||
4013 | #endif // defined(__x86_64__) && defined(__clang__) | |
1a4d82fc JJ |
4014 | |
4015 | TEST(MemorySanitizerOrigins, SetGet) { | |
92a42be0 | 4016 | EXPECT_EQ(TrackingOrigins(), !!__msan_get_track_origins()); |
1a4d82fc JJ |
4017 | if (!TrackingOrigins()) return; |
4018 | int x; | |
4019 | __msan_set_origin(&x, sizeof(x), 1234); | |
92a42be0 | 4020 | EXPECT_ORIGIN(1234U, __msan_get_origin(&x)); |
1a4d82fc | 4021 | __msan_set_origin(&x, sizeof(x), 5678); |
92a42be0 | 4022 | EXPECT_ORIGIN(5678U, __msan_get_origin(&x)); |
1a4d82fc | 4023 | __msan_set_origin(&x, sizeof(x), 0); |
92a42be0 | 4024 | EXPECT_ORIGIN(0U, __msan_get_origin(&x)); |
1a4d82fc JJ |
4025 | } |
4026 | ||
4027 | namespace { | |
4028 | struct S { | |
4029 | U4 dummy; | |
4030 | U2 a; | |
4031 | U2 b; | |
4032 | }; | |
4033 | ||
92a42be0 | 4034 | TEST(MemorySanitizerOrigins, InitializedStoreDoesNotChangeOrigin) { |
1a4d82fc JJ |
4035 | if (!TrackingOrigins()) return; |
4036 | ||
4037 | S s; | |
4038 | U4 origin = rand(); // NOLINT | |
4039 | s.a = *GetPoisonedO<U2>(0, origin); | |
92a42be0 SL |
4040 | EXPECT_ORIGIN(origin, __msan_get_origin(&s.a)); |
4041 | EXPECT_ORIGIN(origin, __msan_get_origin(&s.b)); | |
1a4d82fc JJ |
4042 | |
4043 | s.b = 42; | |
92a42be0 SL |
4044 | EXPECT_ORIGIN(origin, __msan_get_origin(&s.a)); |
4045 | EXPECT_ORIGIN(origin, __msan_get_origin(&s.b)); | |
1a4d82fc JJ |
4046 | } |
4047 | } // namespace | |
4048 | ||
4049 | template<class T, class BinaryOp> | |
4050 | INLINE | |
4051 | void BinaryOpOriginTest(BinaryOp op) { | |
4052 | U4 ox = rand(); //NOLINT | |
4053 | U4 oy = rand(); //NOLINT | |
4054 | T *x = GetPoisonedO<T>(0, ox, 0); | |
4055 | T *y = GetPoisonedO<T>(1, oy, 0); | |
4056 | T *z = GetPoisonedO<T>(2, 0, 0); | |
4057 | ||
4058 | *z = op(*x, *y); | |
4059 | U4 origin = __msan_get_origin(z); | |
4060 | EXPECT_POISONED_O(*z, origin); | |
92a42be0 SL |
4061 | EXPECT_EQ(true, __msan_origin_is_descendant_or_same(origin, ox) || |
4062 | __msan_origin_is_descendant_or_same(origin, oy)); | |
1a4d82fc JJ |
4063 | |
4064 | // y is poisoned, x is not. | |
4065 | *x = 10101; | |
4066 | *y = *GetPoisonedO<T>(1, oy); | |
4067 | break_optimization(x); | |
4068 | __msan_set_origin(z, sizeof(*z), 0); | |
4069 | *z = op(*x, *y); | |
4070 | EXPECT_POISONED_O(*z, oy); | |
92a42be0 | 4071 | EXPECT_ORIGIN(oy, __msan_get_origin(z)); |
1a4d82fc JJ |
4072 | |
4073 | // x is poisoned, y is not. | |
4074 | *x = *GetPoisonedO<T>(0, ox); | |
4075 | *y = 10101010; | |
4076 | break_optimization(y); | |
4077 | __msan_set_origin(z, sizeof(*z), 0); | |
4078 | *z = op(*x, *y); | |
4079 | EXPECT_POISONED_O(*z, ox); | |
92a42be0 | 4080 | EXPECT_ORIGIN(ox, __msan_get_origin(z)); |
1a4d82fc JJ |
4081 | } |
4082 | ||
4083 | template<class T> INLINE T XOR(const T &a, const T&b) { return a ^ b; } | |
4084 | template<class T> INLINE T ADD(const T &a, const T&b) { return a + b; } | |
4085 | template<class T> INLINE T SUB(const T &a, const T&b) { return a - b; } | |
4086 | template<class T> INLINE T MUL(const T &a, const T&b) { return a * b; } | |
4087 | template<class T> INLINE T AND(const T &a, const T&b) { return a & b; } | |
4088 | template<class T> INLINE T OR (const T &a, const T&b) { return a | b; } | |
4089 | ||
4090 | TEST(MemorySanitizerOrigins, BinaryOp) { | |
4091 | if (!TrackingOrigins()) return; | |
4092 | BinaryOpOriginTest<S8>(XOR<S8>); | |
4093 | BinaryOpOriginTest<U8>(ADD<U8>); | |
4094 | BinaryOpOriginTest<S4>(SUB<S4>); | |
4095 | BinaryOpOriginTest<S4>(MUL<S4>); | |
4096 | BinaryOpOriginTest<U4>(OR<U4>); | |
4097 | BinaryOpOriginTest<U4>(AND<U4>); | |
4098 | BinaryOpOriginTest<double>(ADD<U4>); | |
4099 | BinaryOpOriginTest<float>(ADD<S4>); | |
4100 | BinaryOpOriginTest<double>(ADD<double>); | |
4101 | BinaryOpOriginTest<float>(ADD<double>); | |
4102 | } | |
4103 | ||
4104 | TEST(MemorySanitizerOrigins, Unary) { | |
4105 | if (!TrackingOrigins()) return; | |
4106 | EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4107 | EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4108 | EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4109 | EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4110 | ||
4111 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4112 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4113 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4114 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4115 | ||
4116 | EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); | |
4117 | EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); | |
4118 | EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); | |
4119 | EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); | |
4120 | ||
4121 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4122 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4123 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4124 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4125 | ||
4126 | EXPECT_POISONED_O((void*)*GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4127 | EXPECT_POISONED_O((U8)*GetPoisonedO<void*>(0, __LINE__), __LINE__); | |
4128 | } | |
4129 | ||
4130 | TEST(MemorySanitizerOrigins, EQ) { | |
4131 | if (!TrackingOrigins()) return; | |
4132 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__) <= 11, __LINE__); | |
4133 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__) == 11, __LINE__); | |
4134 | EXPECT_POISONED_O(*GetPoisonedO<float>(0, __LINE__) == 1.1, __LINE__); | |
4135 | } | |
4136 | ||
4137 | TEST(MemorySanitizerOrigins, DIV) { | |
4138 | if (!TrackingOrigins()) return; | |
4139 | EXPECT_POISONED_O(*GetPoisonedO<U8>(0, __LINE__) / 100, __LINE__); | |
4140 | unsigned o = __LINE__; | |
4141 | EXPECT_UMR_O(volatile unsigned y = 100 / *GetPoisonedO<S4>(0, o, 1), o); | |
4142 | } | |
4143 | ||
4144 | TEST(MemorySanitizerOrigins, SHIFT) { | |
4145 | if (!TrackingOrigins()) return; | |
4146 | EXPECT_POISONED_O(*GetPoisonedO<U8>(0, __LINE__) >> 10, __LINE__); | |
4147 | EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__) >> 10, __LINE__); | |
4148 | EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__) << 10, __LINE__); | |
4149 | EXPECT_POISONED_O(10U << *GetPoisonedO<U8>(0, __LINE__), __LINE__); | |
4150 | EXPECT_POISONED_O(-10 >> *GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4151 | EXPECT_POISONED_O(-10 << *GetPoisonedO<S8>(0, __LINE__), __LINE__); | |
4152 | } | |
4153 | ||
4154 | template<class T, int N> | |
4155 | void MemCpyTest() { | |
4156 | int ox = __LINE__; | |
4157 | T *x = new T[N]; | |
4158 | T *y = new T[N]; | |
4159 | T *z = new T[N]; | |
4160 | T *q = new T[N]; | |
4161 | __msan_poison(x, N * sizeof(T)); | |
4162 | __msan_set_origin(x, N * sizeof(T), ox); | |
4163 | __msan_set_origin(y, N * sizeof(T), 777777); | |
4164 | __msan_set_origin(z, N * sizeof(T), 888888); | |
4165 | EXPECT_NOT_POISONED(x); | |
4166 | memcpy(y, x, N * sizeof(T)); | |
4167 | EXPECT_POISONED_O(y[0], ox); | |
4168 | EXPECT_POISONED_O(y[N/2], ox); | |
4169 | EXPECT_POISONED_O(y[N-1], ox); | |
4170 | EXPECT_NOT_POISONED(x); | |
4171 | void *res = mempcpy(q, x, N * sizeof(T)); | |
4172 | ASSERT_EQ(q + N, res); | |
4173 | EXPECT_POISONED_O(q[0], ox); | |
4174 | EXPECT_POISONED_O(q[N/2], ox); | |
4175 | EXPECT_POISONED_O(q[N-1], ox); | |
4176 | EXPECT_NOT_POISONED(x); | |
4177 | memmove(z, x, N * sizeof(T)); | |
4178 | EXPECT_POISONED_O(z[0], ox); | |
4179 | EXPECT_POISONED_O(z[N/2], ox); | |
4180 | EXPECT_POISONED_O(z[N-1], ox); | |
4181 | } | |
4182 | ||
4183 | TEST(MemorySanitizerOrigins, LargeMemCpy) { | |
4184 | if (!TrackingOrigins()) return; | |
4185 | MemCpyTest<U1, 10000>(); | |
4186 | MemCpyTest<U8, 10000>(); | |
4187 | } | |
4188 | ||
4189 | TEST(MemorySanitizerOrigins, SmallMemCpy) { | |
4190 | if (!TrackingOrigins()) return; | |
4191 | MemCpyTest<U8, 1>(); | |
4192 | MemCpyTest<U8, 2>(); | |
4193 | MemCpyTest<U8, 3>(); | |
4194 | } | |
4195 | ||
4196 | TEST(MemorySanitizerOrigins, Select) { | |
4197 | if (!TrackingOrigins()) return; | |
4198 | EXPECT_NOT_POISONED(g_one ? 1 : *GetPoisonedO<S4>(0, __LINE__)); | |
4199 | EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4200 | S4 x; | |
4201 | break_optimization(&x); | |
4202 | x = g_1 ? *GetPoisonedO<S4>(0, __LINE__) : 0; | |
4203 | ||
4204 | EXPECT_POISONED_O(g_1 ? *GetPoisonedO<S4>(0, __LINE__) : 1, __LINE__); | |
4205 | EXPECT_POISONED_O(g_0 ? 1 : *GetPoisonedO<S4>(0, __LINE__), __LINE__); | |
4206 | } | |
4207 | ||
1a4d82fc JJ |
4208 | NOINLINE int RetvalOriginTest(U4 origin) { |
4209 | int *a = new int; | |
4210 | break_optimization(a); | |
4211 | __msan_set_origin(a, sizeof(*a), origin); | |
4212 | int res = *a; | |
4213 | delete a; | |
4214 | return res; | |
4215 | } | |
4216 | ||
4217 | TEST(MemorySanitizerOrigins, Retval) { | |
4218 | if (!TrackingOrigins()) return; | |
4219 | EXPECT_POISONED_O(RetvalOriginTest(__LINE__), __LINE__); | |
4220 | } | |
4221 | ||
4222 | NOINLINE void ParamOriginTest(int param, U4 origin) { | |
4223 | EXPECT_POISONED_O(param, origin); | |
4224 | } | |
4225 | ||
4226 | TEST(MemorySanitizerOrigins, Param) { | |
4227 | if (!TrackingOrigins()) return; | |
4228 | int *a = new int; | |
4229 | U4 origin = __LINE__; | |
4230 | break_optimization(a); | |
4231 | __msan_set_origin(a, sizeof(*a), origin); | |
4232 | ParamOriginTest(*a, origin); | |
4233 | delete a; | |
4234 | } | |
4235 | ||
4236 | TEST(MemorySanitizerOrigins, Invoke) { | |
4237 | if (!TrackingOrigins()) return; | |
4238 | StructWithDtor s; // Will cause the calls to become invokes. | |
4239 | EXPECT_POISONED_O(RetvalOriginTest(__LINE__), __LINE__); | |
4240 | } | |
4241 | ||
4242 | TEST(MemorySanitizerOrigins, strlen) { | |
4243 | S8 alignment; | |
4244 | break_optimization(&alignment); | |
4245 | char x[4] = {'a', 'b', 0, 0}; | |
4246 | __msan_poison(&x[2], 1); | |
4247 | U4 origin = __LINE__; | |
4248 | __msan_set_origin(x, sizeof(x), origin); | |
4249 | EXPECT_UMR_O(volatile unsigned y = strlen(x), origin); | |
4250 | } | |
4251 | ||
4252 | TEST(MemorySanitizerOrigins, wcslen) { | |
4253 | wchar_t w[3] = {'a', 'b', 0}; | |
4254 | U4 origin = __LINE__; | |
4255 | __msan_set_origin(w, sizeof(w), origin); | |
4256 | __msan_poison(&w[2], sizeof(wchar_t)); | |
4257 | EXPECT_UMR_O(volatile unsigned y = wcslen(w), origin); | |
4258 | } | |
4259 | ||
4260 | #if MSAN_HAS_M128 | |
4261 | TEST(MemorySanitizerOrigins, StoreIntrinsic) { | |
4262 | __m128 x, y; | |
4263 | U4 origin = __LINE__; | |
4264 | __msan_set_origin(&x, sizeof(x), origin); | |
4265 | __msan_poison(&x, sizeof(x)); | |
5bcae85e | 4266 | _mm_storeu_ps((float*)&y, x); |
1a4d82fc JJ |
4267 | EXPECT_POISONED_O(y, origin); |
4268 | } | |
4269 | #endif | |
4270 | ||
4271 | NOINLINE void RecursiveMalloc(int depth) { | |
4272 | static int count; | |
4273 | count++; | |
4274 | if ((count % (1024 * 1024)) == 0) | |
4275 | printf("RecursiveMalloc: %d\n", count); | |
4276 | int *x1 = new int; | |
4277 | int *x2 = new int; | |
4278 | break_optimization(x1); | |
4279 | break_optimization(x2); | |
4280 | if (depth > 0) { | |
4281 | RecursiveMalloc(depth-1); | |
4282 | RecursiveMalloc(depth-1); | |
4283 | } | |
4284 | delete x1; | |
4285 | delete x2; | |
4286 | } | |
4287 | ||
4288 | TEST(MemorySanitizer, Select) { | |
4289 | int x; | |
4290 | int volatile* p = &x; | |
4291 | int z = *p ? 1 : 0; | |
4292 | EXPECT_POISONED(z); | |
4293 | } | |
4294 | ||
4295 | TEST(MemorySanitizer, SelectPartial) { | |
4296 | // Precise instrumentation of select. | |
4297 | // Some bits of the result do not depend on select condition, and must stay | |
4298 | // initialized even if select condition is not. These are the bits that are | |
4299 | // equal and initialized in both left and right select arguments. | |
4300 | U4 x = 0xFFFFABCDU; | |
4301 | U4 x_s = 0xFFFF0000U; | |
4302 | __msan_partial_poison(&x, &x_s, sizeof(x)); | |
4303 | U4 y = 0xAB00U; | |
4304 | U1 cond = true; | |
4305 | __msan_poison(&cond, sizeof(cond)); | |
4306 | U4 z = cond ? x : y; | |
4307 | __msan_print_shadow(&z, sizeof(z)); | |
4308 | EXPECT_POISONED(z & 0xFFU); | |
4309 | EXPECT_NOT_POISONED(z & 0xFF00U); | |
4310 | EXPECT_POISONED(z & 0xFF0000U); | |
4311 | EXPECT_POISONED(z & 0xFF000000U); | |
4312 | EXPECT_EQ(0xAB00U, z & 0xFF00U); | |
4313 | } | |
4314 | ||
4315 | TEST(MemorySanitizerStress, DISABLED_MallocStackTrace) { | |
4316 | RecursiveMalloc(22); | |
4317 | } | |
4318 | ||
4319 | TEST(MemorySanitizerAllocator, get_estimated_allocated_size) { | |
4320 | size_t sizes[] = {0, 20, 5000, 1<<20}; | |
4321 | for (size_t i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i) { | |
92a42be0 | 4322 | size_t alloc_size = __sanitizer_get_estimated_allocated_size(sizes[i]); |
1a4d82fc JJ |
4323 | EXPECT_EQ(alloc_size, sizes[i]); |
4324 | } | |
4325 | } | |
4326 | ||
4327 | TEST(MemorySanitizerAllocator, get_allocated_size_and_ownership) { | |
4328 | char *array = reinterpret_cast<char*>(malloc(100)); | |
4329 | int *int_ptr = new int; | |
4330 | ||
92a42be0 SL |
4331 | EXPECT_TRUE(__sanitizer_get_ownership(array)); |
4332 | EXPECT_EQ(100U, __sanitizer_get_allocated_size(array)); | |
1a4d82fc | 4333 | |
92a42be0 SL |
4334 | EXPECT_TRUE(__sanitizer_get_ownership(int_ptr)); |
4335 | EXPECT_EQ(sizeof(*int_ptr), __sanitizer_get_allocated_size(int_ptr)); | |
1a4d82fc JJ |
4336 | |
4337 | void *wild_addr = reinterpret_cast<void*>(0x1); | |
92a42be0 SL |
4338 | EXPECT_FALSE(__sanitizer_get_ownership(wild_addr)); |
4339 | EXPECT_EQ(0U, __sanitizer_get_allocated_size(wild_addr)); | |
4340 | ||
4341 | EXPECT_FALSE(__sanitizer_get_ownership(array + 50)); | |
4342 | EXPECT_EQ(0U, __sanitizer_get_allocated_size(array + 50)); | |
1a4d82fc | 4343 | |
92a42be0 SL |
4344 | // NULL is a valid argument for GetAllocatedSize but is not owned. |
4345 | EXPECT_FALSE(__sanitizer_get_ownership(NULL)); | |
4346 | EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL)); | |
1a4d82fc | 4347 | |
1a4d82fc | 4348 | free(array); |
92a42be0 SL |
4349 | EXPECT_FALSE(__sanitizer_get_ownership(array)); |
4350 | EXPECT_EQ(0U, __sanitizer_get_allocated_size(array)); | |
1a4d82fc JJ |
4351 | |
4352 | delete int_ptr; | |
4353 | } | |
4354 | ||
4355 | TEST(MemorySanitizer, MlockTest) { | |
4356 | EXPECT_EQ(0, mlockall(MCL_CURRENT)); | |
4357 | EXPECT_EQ(0, mlock((void*)0x12345, 0x5678)); | |
4358 | EXPECT_EQ(0, munlockall()); | |
4359 | EXPECT_EQ(0, munlock((void*)0x987, 0x654)); | |
4360 | } | |
4361 | ||
4362 | // Test that LargeAllocator unpoisons memory before releasing it to the OS. | |
4363 | TEST(MemorySanitizer, LargeAllocatorUnpoisonsOnFree) { | |
4364 | void *p = malloc(1024 * 1024); | |
4365 | free(p); | |
4366 | ||
4367 | typedef void *(*mmap_fn)(void *, size_t, int, int, int, off_t); | |
4368 | mmap_fn real_mmap = (mmap_fn)dlsym(RTLD_NEXT, "mmap"); | |
4369 | ||
4370 | // Allocate the page that was released to the OS in free() with the real mmap, | |
4371 | // bypassing the interceptor. | |
92a42be0 SL |
4372 | char *q = (char *)real_mmap(p, 4096, PROT_READ | PROT_WRITE, |
4373 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
1a4d82fc JJ |
4374 | ASSERT_NE((char *)0, q); |
4375 | ||
4376 | ASSERT_TRUE(q <= p); | |
4377 | ASSERT_TRUE(q + 4096 > p); | |
4378 | ||
4379 | EXPECT_NOT_POISONED(q[0]); | |
4380 | EXPECT_NOT_POISONED(q[10]); | |
4381 | EXPECT_NOT_POISONED(q[100]); | |
4382 | ||
4383 | munmap(q, 4096); | |
4384 | } | |
4385 | ||
4386 | #if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE | |
4387 | TEST(MemorySanitizer, MallocUsableSizeTest) { | |
4388 | const size_t kArraySize = 100; | |
4389 | char *array = Ident((char*)malloc(kArraySize)); | |
4390 | int *int_ptr = Ident(new int); | |
4391 | EXPECT_EQ(0U, malloc_usable_size(NULL)); | |
4392 | EXPECT_EQ(kArraySize, malloc_usable_size(array)); | |
4393 | EXPECT_EQ(sizeof(int), malloc_usable_size(int_ptr)); | |
4394 | free(array); | |
4395 | delete int_ptr; | |
4396 | } | |
4397 | #endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE |