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