• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- msan_interceptors.cc ----------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of MemorySanitizer.
11 //
12 // Interceptors for standard library functions.
13 //
14 // FIXME: move as many interceptors as possible into
15 // sanitizer_common/sanitizer_common_interceptors.h
16 //===----------------------------------------------------------------------===//
17 
18 #include "interception/interception.h"
19 #include "msan.h"
20 #include "msan_chained_origin_depot.h"
21 #include "msan_origin.h"
22 #include "msan_thread.h"
23 #include "msan_poisoning.h"
24 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
25 #include "sanitizer_common/sanitizer_allocator.h"
26 #include "sanitizer_common/sanitizer_allocator_interface.h"
27 #include "sanitizer_common/sanitizer_allocator_internal.h"
28 #include "sanitizer_common/sanitizer_atomic.h"
29 #include "sanitizer_common/sanitizer_common.h"
30 #include "sanitizer_common/sanitizer_stackdepot.h"
31 #include "sanitizer_common/sanitizer_libc.h"
32 #include "sanitizer_common/sanitizer_linux.h"
33 #include "sanitizer_common/sanitizer_tls_get_addr.h"
34 
35 #include <stdarg.h>
36 // ACHTUNG! No other system header includes in this file.
37 // Ideally, we should get rid of stdarg.h as well.
38 
39 using namespace __msan;
40 
41 using __sanitizer::memory_order;
42 using __sanitizer::atomic_load;
43 using __sanitizer::atomic_store;
44 using __sanitizer::atomic_uintptr_t;
45 
46 DECLARE_REAL(SIZE_T, strlen, const char *s)
47 DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
48 
49 #if SANITIZER_FREEBSD
50 #define __errno_location __error
51 #endif
52 
53 // True if this is a nested interceptor.
54 static THREADLOCAL int in_interceptor_scope;
55 
56 extern "C" int *__errno_location(void);
57 
58 struct InterceptorScope {
InterceptorScopeInterceptorScope59   InterceptorScope() { ++in_interceptor_scope; }
~InterceptorScopeInterceptorScope60   ~InterceptorScope() { --in_interceptor_scope; }
61 };
62 
IsInInterceptorScope()63 bool IsInInterceptorScope() {
64   return in_interceptor_scope;
65 }
66 
67 #define ENSURE_MSAN_INITED() do { \
68   CHECK(!msan_init_is_running); \
69   if (!msan_inited) { \
70     __msan_init(); \
71   } \
72 } while (0)
73 
74 // Check that [x, x+n) range is unpoisoned.
75 #define CHECK_UNPOISONED_0(x, n)                                               \
76   do {                                                                         \
77     sptr offset = __msan_test_shadow(x, n);                                    \
78     if (__msan::IsInSymbolizer())                                              \
79       break;                                                                   \
80     if (offset >= 0 && __msan::flags()->report_umrs) {                         \
81       GET_CALLER_PC_BP_SP;                                                     \
82       (void) sp;                                                               \
83       ReportUMRInsideAddressRange(__func__, x, n, offset);                     \
84       __msan::PrintWarningWithOrigin(                                          \
85           pc, bp, __msan_get_origin((const char *)x + offset));                \
86       if (__msan::flags()->halt_on_error) {                                    \
87         Printf("Exiting\n");                                                   \
88         Die();                                                                 \
89       }                                                                        \
90     }                                                                          \
91   } while (0)
92 
93 // Check that [x, x+n) range is unpoisoned unless we are in a nested
94 // interceptor.
95 #define CHECK_UNPOISONED(x, n)                             \
96   do {                                                     \
97     if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
98   } while (0);
99 
100 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n)               \
101   CHECK_UNPOISONED((x),                                         \
102     common_flags()->strict_string_checks ? (len) + 1 : (n) )
103 
104 #define CHECK_UNPOISONED_STRING(x, n)                           \
105     CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
106 
INTERCEPTOR(SIZE_T,fread,void * ptr,SIZE_T size,SIZE_T nmemb,void * file)107 INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
108   ENSURE_MSAN_INITED();
109   SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
110   if (res > 0)
111     __msan_unpoison(ptr, res *size);
112   return res;
113 }
114 
115 #if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T,fread_unlocked,void * ptr,SIZE_T size,SIZE_T nmemb,void * file)116 INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
117             void *file) {
118   ENSURE_MSAN_INITED();
119   SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
120   if (res > 0)
121     __msan_unpoison(ptr, res *size);
122   return res;
123 }
124 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
125 #else
126 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
127 #endif
128 
INTERCEPTOR(SSIZE_T,readlink,const char * path,char * buf,SIZE_T bufsiz)129 INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
130   ENSURE_MSAN_INITED();
131   CHECK_UNPOISONED_STRING(path, 0)
132   SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
133   if (res > 0)
134     __msan_unpoison(buf, res);
135   return res;
136 }
137 
INTERCEPTOR(void *,memcpy,void * dest,const void * src,SIZE_T n)138 INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) {
139   return __msan_memcpy(dest, src, n);
140 }
141 
INTERCEPTOR(void *,mempcpy,void * dest,const void * src,SIZE_T n)142 INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
143   return (char *)__msan_memcpy(dest, src, n) + n;
144 }
145 
INTERCEPTOR(void *,memccpy,void * dest,const void * src,int c,SIZE_T n)146 INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
147   ENSURE_MSAN_INITED();
148   void *res = REAL(memccpy)(dest, src, c, n);
149   CHECK(!res || (res >= dest && res <= (char *)dest + n));
150   SIZE_T sz = res ? (char *)res - (char *)dest : n;
151   CHECK_UNPOISONED(src, sz);
152   __msan_unpoison(dest, sz);
153   return res;
154 }
155 
INTERCEPTOR(void *,memmove,void * dest,const void * src,SIZE_T n)156 INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
157   return __msan_memmove(dest, src, n);
158 }
159 
INTERCEPTOR(void *,memset,void * s,int c,SIZE_T n)160 INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
161   return __msan_memset(s, c, n);
162 }
163 
INTERCEPTOR(void *,bcopy,const void * src,void * dest,SIZE_T n)164 INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
165   return __msan_memmove(dest, src, n);
166 }
167 
INTERCEPTOR(int,posix_memalign,void ** memptr,SIZE_T alignment,SIZE_T size)168 INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
169   GET_MALLOC_STACK_TRACE;
170   CHECK_EQ(alignment & (alignment - 1), 0);
171   CHECK_NE(memptr, 0);
172   *memptr = MsanReallocate(&stack, nullptr, size, alignment, false);
173   CHECK_NE(*memptr, 0);
174   __msan_unpoison(memptr, sizeof(*memptr));
175   return 0;
176 }
177 
178 #if !SANITIZER_FREEBSD
INTERCEPTOR(void *,memalign,SIZE_T boundary,SIZE_T size)179 INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) {
180   GET_MALLOC_STACK_TRACE;
181   CHECK_EQ(boundary & (boundary - 1), 0);
182   void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
183   return ptr;
184 }
185 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
186 #else
187 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
188 #endif
189 
INTERCEPTOR(void *,aligned_alloc,SIZE_T boundary,SIZE_T size)190 INTERCEPTOR(void *, aligned_alloc, SIZE_T boundary, SIZE_T size) {
191   GET_MALLOC_STACK_TRACE;
192   CHECK_EQ(boundary & (boundary - 1), 0);
193   void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
194   return ptr;
195 }
196 
INTERCEPTOR(void *,__libc_memalign,SIZE_T boundary,SIZE_T size)197 INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) {
198   GET_MALLOC_STACK_TRACE;
199   CHECK_EQ(boundary & (boundary - 1), 0);
200   void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
201   DTLS_on_libc_memalign(ptr, size);
202   return ptr;
203 }
204 
INTERCEPTOR(void *,valloc,SIZE_T size)205 INTERCEPTOR(void *, valloc, SIZE_T size) {
206   GET_MALLOC_STACK_TRACE;
207   void *ptr = MsanReallocate(&stack, nullptr, size, GetPageSizeCached(), false);
208   return ptr;
209 }
210 
211 #if !SANITIZER_FREEBSD
INTERCEPTOR(void *,pvalloc,SIZE_T size)212 INTERCEPTOR(void *, pvalloc, SIZE_T size) {
213   GET_MALLOC_STACK_TRACE;
214   uptr PageSize = GetPageSizeCached();
215   size = RoundUpTo(size, PageSize);
216   if (size == 0) {
217     // pvalloc(0) should allocate one page.
218     size = PageSize;
219   }
220   void *ptr = MsanReallocate(&stack, nullptr, size, PageSize, false);
221   return ptr;
222 }
223 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
224 #else
225 #define MSAN_MAYBE_INTERCEPT_PVALLOC
226 #endif
227 
INTERCEPTOR(void,free,void * ptr)228 INTERCEPTOR(void, free, void *ptr) {
229   GET_MALLOC_STACK_TRACE;
230   if (!ptr) return;
231   MsanDeallocate(&stack, ptr);
232 }
233 
234 #if !SANITIZER_FREEBSD
INTERCEPTOR(void,cfree,void * ptr)235 INTERCEPTOR(void, cfree, void *ptr) {
236   GET_MALLOC_STACK_TRACE;
237   if (!ptr) return;
238   MsanDeallocate(&stack, ptr);
239 }
240 #define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
241 #else
242 #define MSAN_MAYBE_INTERCEPT_CFREE
243 #endif
244 
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)245 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
246   return __sanitizer_get_allocated_size(ptr);
247 }
248 
249 #if !SANITIZER_FREEBSD
250 // This function actually returns a struct by value, but we can't unpoison a
251 // temporary! The following is equivalent on all supported platforms but
252 // aarch64 (which uses a different register for sret value).  We have a test
253 // to confirm that.
INTERCEPTOR(void,mallinfo,__sanitizer_mallinfo * sret)254 INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) {
255 #ifdef __aarch64__
256   uptr r8;
257   asm volatile("mov %0,x8" : "=r" (r8));
258   sret = reinterpret_cast<__sanitizer_mallinfo*>(r8);
259 #endif
260   REAL(memset)(sret, 0, sizeof(*sret));
261   __msan_unpoison(sret, sizeof(*sret));
262 }
263 #define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
264 #else
265 #define MSAN_MAYBE_INTERCEPT_MALLINFO
266 #endif
267 
268 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,mallopt,int cmd,int value)269 INTERCEPTOR(int, mallopt, int cmd, int value) {
270   return -1;
271 }
272 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
273 #else
274 #define MSAN_MAYBE_INTERCEPT_MALLOPT
275 #endif
276 
277 #if !SANITIZER_FREEBSD
INTERCEPTOR(void,malloc_stats,void)278 INTERCEPTOR(void, malloc_stats, void) {
279   // FIXME: implement, but don't call REAL(malloc_stats)!
280 }
281 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
282 #else
283 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
284 #endif
285 
INTERCEPTOR(char *,strcpy,char * dest,const char * src)286 INTERCEPTOR(char *, strcpy, char *dest, const char *src) {  // NOLINT
287   ENSURE_MSAN_INITED();
288   GET_STORE_STACK_TRACE;
289   SIZE_T n = REAL(strlen)(src);
290   CHECK_UNPOISONED_STRING(src + n, 0);
291   char *res = REAL(strcpy)(dest, src);  // NOLINT
292   CopyShadowAndOrigin(dest, src, n + 1, &stack);
293   return res;
294 }
295 
INTERCEPTOR(char *,strncpy,char * dest,const char * src,SIZE_T n)296 INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {  // NOLINT
297   ENSURE_MSAN_INITED();
298   GET_STORE_STACK_TRACE;
299   SIZE_T copy_size = REAL(strnlen)(src, n);
300   if (copy_size < n)
301     copy_size++;  // trailing \0
302   char *res = REAL(strncpy)(dest, src, n);  // NOLINT
303   CopyShadowAndOrigin(dest, src, copy_size, &stack);
304   __msan_unpoison(dest + copy_size, n - copy_size);
305   return res;
306 }
307 
INTERCEPTOR(char *,stpcpy,char * dest,const char * src)308 INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {  // NOLINT
309   ENSURE_MSAN_INITED();
310   GET_STORE_STACK_TRACE;
311   SIZE_T n = REAL(strlen)(src);
312   CHECK_UNPOISONED_STRING(src + n, 0);
313   char *res = REAL(stpcpy)(dest, src);  // NOLINT
314   CopyShadowAndOrigin(dest, src, n + 1, &stack);
315   return res;
316 }
317 
INTERCEPTOR(char *,strdup,char * src)318 INTERCEPTOR(char *, strdup, char *src) {
319   ENSURE_MSAN_INITED();
320   GET_STORE_STACK_TRACE;
321   // On FreeBSD strdup() leverages strlen().
322   InterceptorScope interceptor_scope;
323   SIZE_T n = REAL(strlen)(src);
324   CHECK_UNPOISONED_STRING(src + n, 0);
325   char *res = REAL(strdup)(src);
326   CopyShadowAndOrigin(res, src, n + 1, &stack);
327   return res;
328 }
329 
330 #if !SANITIZER_FREEBSD
INTERCEPTOR(char *,__strdup,char * src)331 INTERCEPTOR(char *, __strdup, char *src) {
332   ENSURE_MSAN_INITED();
333   GET_STORE_STACK_TRACE;
334   SIZE_T n = REAL(strlen)(src);
335   CHECK_UNPOISONED_STRING(src + n, 0);
336   char *res = REAL(__strdup)(src);
337   CopyShadowAndOrigin(res, src, n + 1, &stack);
338   return res;
339 }
340 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
341 #else
342 #define MSAN_MAYBE_INTERCEPT___STRDUP
343 #endif
344 
INTERCEPTOR(char *,strndup,char * src,SIZE_T n)345 INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
346   ENSURE_MSAN_INITED();
347   GET_STORE_STACK_TRACE;
348   // On FreeBSD strndup() leverages strnlen().
349   InterceptorScope interceptor_scope;
350   SIZE_T copy_size = REAL(strnlen)(src, n);
351   char *res = REAL(strndup)(src, n);
352   CopyShadowAndOrigin(res, src, copy_size, &stack);
353   __msan_unpoison(res + copy_size, 1); // \0
354   return res;
355 }
356 
357 #if !SANITIZER_FREEBSD
INTERCEPTOR(char *,__strndup,char * src,SIZE_T n)358 INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
359   ENSURE_MSAN_INITED();
360   GET_STORE_STACK_TRACE;
361   SIZE_T copy_size = REAL(strnlen)(src, n);
362   char *res = REAL(__strndup)(src, n);
363   CopyShadowAndOrigin(res, src, copy_size, &stack);
364   __msan_unpoison(res + copy_size, 1); // \0
365   return res;
366 }
367 #define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup)
368 #else
369 #define MSAN_MAYBE_INTERCEPT___STRNDUP
370 #endif
371 
INTERCEPTOR(char *,gcvt,double number,SIZE_T ndigit,char * buf)372 INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
373   ENSURE_MSAN_INITED();
374   char *res = REAL(gcvt)(number, ndigit, buf);
375   SIZE_T n = REAL(strlen)(buf);
376   __msan_unpoison(buf, n + 1);
377   return res;
378 }
379 
INTERCEPTOR(char *,strcat,char * dest,const char * src)380 INTERCEPTOR(char *, strcat, char *dest, const char *src) {  // NOLINT
381   ENSURE_MSAN_INITED();
382   GET_STORE_STACK_TRACE;
383   SIZE_T src_size = REAL(strlen)(src);
384   SIZE_T dest_size = REAL(strlen)(dest);
385   CHECK_UNPOISONED_STRING(src + src_size, 0);
386   CHECK_UNPOISONED_STRING(dest + dest_size, 0);
387   char *res = REAL(strcat)(dest, src);  // NOLINT
388   CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
389   return res;
390 }
391 
INTERCEPTOR(char *,strncat,char * dest,const char * src,SIZE_T n)392 INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {  // NOLINT
393   ENSURE_MSAN_INITED();
394   GET_STORE_STACK_TRACE;
395   SIZE_T dest_size = REAL(strlen)(dest);
396   SIZE_T copy_size = REAL(strnlen)(src, n);
397   CHECK_UNPOISONED_STRING(dest + dest_size, 0);
398   char *res = REAL(strncat)(dest, src, n);  // NOLINT
399   CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
400   __msan_unpoison(dest + dest_size + copy_size, 1); // \0
401   return res;
402 }
403 
404 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
405 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
406 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
407   ENSURE_MSAN_INITED();                             \
408   ret_type res = REAL(func)(__VA_ARGS__);           \
409   __msan_unpoison(endptr, sizeof(*endptr));         \
410   return res;
411 
412 #define INTERCEPTOR_STRTO(ret_type, func, char_type)                       \
413   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
414     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr);                  \
415   }
416 
417 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)                \
418   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
419               int base) {                                                \
420     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base);          \
421   }
422 
423 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type)                 \
424   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
425               void *loc) {                                               \
426     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc);           \
427   }
428 
429 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type)            \
430   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
431               int base, void *loc) {                                     \
432     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc);     \
433   }
434 
435 #define INTERCEPTORS_STRTO(ret_type, func, char_type)      \
436   INTERCEPTOR_STRTO(ret_type, func, char_type)             \
437   INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)     \
438   INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
439   INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
440 
441 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type)      \
442   INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)             \
443   INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)     \
444   INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
445   INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
446 
INTERCEPTORS_STRTO(double,strtod,char)447 INTERCEPTORS_STRTO(double, strtod, char)                     // NOLINT
448 INTERCEPTORS_STRTO(float, strtof, char)                      // NOLINT
449 INTERCEPTORS_STRTO(long double, strtold, char)               // NOLINT
450 INTERCEPTORS_STRTO_BASE(long, strtol, char)                  // NOLINT
451 INTERCEPTORS_STRTO_BASE(long long, strtoll, char)            // NOLINT
452 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)        // NOLINT
453 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)  // NOLINT
454 
455 INTERCEPTORS_STRTO(double, wcstod, wchar_t)                     // NOLINT
456 INTERCEPTORS_STRTO(float, wcstof, wchar_t)                      // NOLINT
457 INTERCEPTORS_STRTO(long double, wcstold, wchar_t)               // NOLINT
458 INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)                  // NOLINT
459 INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)            // NOLINT
460 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)        // NOLINT
461 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)  // NOLINT
462 
463 #define INTERCEPT_STRTO(func) \
464   INTERCEPT_FUNCTION(func); \
465   INTERCEPT_FUNCTION(func##_l); \
466   INTERCEPT_FUNCTION(__##func##_l); \
467   INTERCEPT_FUNCTION(__##func##_internal);
468 
469 
470 // FIXME: support *wprintf in common format interceptors.
471 INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
472   ENSURE_MSAN_INITED();
473   int res = REAL(vswprintf)(str, size, format, ap);
474   if (res >= 0) {
475     __msan_unpoison(str, 4 * (res + 1));
476   }
477   return res;
478 }
479 
INTERCEPTOR(int,swprintf,void * str,uptr size,void * format,...)480 INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
481   ENSURE_MSAN_INITED();
482   va_list ap;
483   va_start(ap, format);
484   int res = vswprintf(str, size, format, ap);
485   va_end(ap);
486   return res;
487 }
488 
INTERCEPTOR(SIZE_T,strxfrm,char * dest,const char * src,SIZE_T n)489 INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T n) {
490   ENSURE_MSAN_INITED();
491   CHECK_UNPOISONED(src, REAL(strlen)(src) + 1);
492   SIZE_T res = REAL(strxfrm)(dest, src, n);
493   if (res < n) __msan_unpoison(dest, res + 1);
494   return res;
495 }
496 
INTERCEPTOR(SIZE_T,strxfrm_l,char * dest,const char * src,SIZE_T n,void * loc)497 INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T n,
498             void *loc) {
499   ENSURE_MSAN_INITED();
500   CHECK_UNPOISONED(src, REAL(strlen)(src) + 1);
501   SIZE_T res = REAL(strxfrm_l)(dest, src, n, loc);
502   if (res < n) __msan_unpoison(dest, res + 1);
503   return res;
504 }
505 
506 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
507   ENSURE_MSAN_INITED();                                              \
508   ret_type res = REAL(func)(s, __VA_ARGS__);                         \
509   if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1));          \
510   return res;
511 
INTERCEPTOR(SIZE_T,strftime,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm)512 INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
513             __sanitizer_tm *tm) {
514   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
515 }
516 
INTERCEPTOR(SIZE_T,strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)517 INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
518             __sanitizer_tm *tm, void *loc) {
519   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
520 }
521 
522 #if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T,__strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)523 INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
524             __sanitizer_tm *tm, void *loc) {
525   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
526                             loc);
527 }
528 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
529 #else
530 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
531 #endif
532 
INTERCEPTOR(SIZE_T,wcsftime,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm)533 INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
534             __sanitizer_tm *tm) {
535   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
536 }
537 
INTERCEPTOR(SIZE_T,wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)538 INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
539             __sanitizer_tm *tm, void *loc) {
540   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
541                             loc);
542 }
543 
544 #if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T,__wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)545 INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
546             __sanitizer_tm *tm, void *loc) {
547   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
548                             loc);
549 }
550 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
551 #else
552 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
553 #endif
554 
INTERCEPTOR(int,mbtowc,wchar_t * dest,const char * src,SIZE_T n)555 INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
556   ENSURE_MSAN_INITED();
557   int res = REAL(mbtowc)(dest, src, n);
558   if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
559   return res;
560 }
561 
INTERCEPTOR(int,mbrtowc,wchar_t * dest,const char * src,SIZE_T n,void * ps)562 INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) {
563   ENSURE_MSAN_INITED();
564   SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
565   if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
566   return res;
567 }
568 
INTERCEPTOR(SIZE_T,wcslen,const wchar_t * s)569 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
570   ENSURE_MSAN_INITED();
571   SIZE_T res = REAL(wcslen)(s);
572   CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
573   return res;
574 }
575 
576 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *,wcschr,void * s,wchar_t wc,void * ps)577 INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
578   ENSURE_MSAN_INITED();
579   wchar_t *res = REAL(wcschr)(s, wc, ps);
580   return res;
581 }
582 
583 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *,wcscpy,wchar_t * dest,const wchar_t * src)584 INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
585   ENSURE_MSAN_INITED();
586   GET_STORE_STACK_TRACE;
587   wchar_t *res = REAL(wcscpy)(dest, src);
588   CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1),
589                       &stack);
590   return res;
591 }
592 
593 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
INTERCEPTOR(wchar_t *,wmemcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)594 INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
595   ENSURE_MSAN_INITED();
596   GET_STORE_STACK_TRACE;
597   wchar_t *res = REAL(wmemcpy)(dest, src, n);
598   CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
599   return res;
600 }
601 
INTERCEPTOR(wchar_t *,wmempcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)602 INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
603   ENSURE_MSAN_INITED();
604   GET_STORE_STACK_TRACE;
605   wchar_t *res = REAL(wmempcpy)(dest, src, n);
606   CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
607   return res;
608 }
609 
INTERCEPTOR(wchar_t *,wmemset,wchar_t * s,wchar_t c,SIZE_T n)610 INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
611   CHECK(MEM_IS_APP(s));
612   ENSURE_MSAN_INITED();
613   wchar_t *res = REAL(wmemset)(s, c, n);
614   __msan_unpoison(s, n * sizeof(wchar_t));
615   return res;
616 }
617 
INTERCEPTOR(wchar_t *,wmemmove,wchar_t * dest,const wchar_t * src,SIZE_T n)618 INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
619   ENSURE_MSAN_INITED();
620   GET_STORE_STACK_TRACE;
621   wchar_t *res = REAL(wmemmove)(dest, src, n);
622   MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
623   return res;
624 }
625 
INTERCEPTOR(int,wcscmp,const wchar_t * s1,const wchar_t * s2)626 INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
627   ENSURE_MSAN_INITED();
628   int res = REAL(wcscmp)(s1, s2);
629   return res;
630 }
631 
INTERCEPTOR(int,gettimeofday,void * tv,void * tz)632 INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
633   ENSURE_MSAN_INITED();
634   int res = REAL(gettimeofday)(tv, tz);
635   if (tv)
636     __msan_unpoison(tv, 16);
637   if (tz)
638     __msan_unpoison(tz, 8);
639   return res;
640 }
641 
INTERCEPTOR(char *,fcvt,double x,int a,int * b,int * c)642 INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
643   ENSURE_MSAN_INITED();
644   char *res = REAL(fcvt)(x, a, b, c);
645   __msan_unpoison(b, sizeof(*b));
646   __msan_unpoison(c, sizeof(*c));
647   if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
648   return res;
649 }
650 
INTERCEPTOR(char *,getenv,char * name)651 INTERCEPTOR(char *, getenv, char *name) {
652   if (msan_init_is_running)
653     return REAL(getenv)(name);
654   ENSURE_MSAN_INITED();
655   char *res = REAL(getenv)(name);
656   if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
657   return res;
658 }
659 
660 extern char **environ;
661 
UnpoisonEnviron()662 static void UnpoisonEnviron() {
663   char **envp = environ;
664   for (; *envp; ++envp) {
665     __msan_unpoison(envp, sizeof(*envp));
666     __msan_unpoison(*envp, REAL(strlen)(*envp) + 1);
667   }
668   // Trailing NULL pointer.
669   __msan_unpoison(envp, sizeof(*envp));
670 }
671 
INTERCEPTOR(int,setenv,const char * name,const char * value,int overwrite)672 INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
673   ENSURE_MSAN_INITED();
674   CHECK_UNPOISONED_STRING(name, 0)
675   int res = REAL(setenv)(name, value, overwrite);
676   if (!res) UnpoisonEnviron();
677   return res;
678 }
679 
INTERCEPTOR(int,putenv,char * string)680 INTERCEPTOR(int, putenv, char *string) {
681   ENSURE_MSAN_INITED();
682   int res = REAL(putenv)(string);
683   if (!res) UnpoisonEnviron();
684   return res;
685 }
686 
687 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,__fxstat,int magic,int fd,void * buf)688 INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
689   ENSURE_MSAN_INITED();
690   int res = REAL(__fxstat)(magic, fd, buf);
691   if (!res)
692     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
693   return res;
694 }
695 #define MSAN_MAYBE_INTERCEPT___FXSTAT INTERCEPT_FUNCTION(__fxstat)
696 #else
697 #define MSAN_MAYBE_INTERCEPT___FXSTAT
698 #endif
699 
700 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,__fxstat64,int magic,int fd,void * buf)701 INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
702   ENSURE_MSAN_INITED();
703   int res = REAL(__fxstat64)(magic, fd, buf);
704   if (!res)
705     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
706   return res;
707 }
708 #define MSAN_MAYBE_INTERCEPT___FXSTAT64 INTERCEPT_FUNCTION(__fxstat64)
709 #else
710 #define MSAN_MAYBE_INTERCEPT___FXSTAT64
711 #endif
712 
713 #if SANITIZER_FREEBSD
INTERCEPTOR(int,fstatat,int fd,char * pathname,void * buf,int flags)714 INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
715   ENSURE_MSAN_INITED();
716   int res = REAL(fstatat)(fd, pathname, buf, flags);
717   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
718   return res;
719 }
720 # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(fstatat)
721 #else
INTERCEPTOR(int,__fxstatat,int magic,int fd,char * pathname,void * buf,int flags)722 INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
723             int flags) {
724   ENSURE_MSAN_INITED();
725   int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
726   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
727   return res;
728 }
729 # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat)
730 #endif
731 
732 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,__fxstatat64,int magic,int fd,char * pathname,void * buf,int flags)733 INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
734             int flags) {
735   ENSURE_MSAN_INITED();
736   int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
737   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
738   return res;
739 }
740 #define MSAN_MAYBE_INTERCEPT___FXSTATAT64 INTERCEPT_FUNCTION(__fxstatat64)
741 #else
742 #define MSAN_MAYBE_INTERCEPT___FXSTATAT64
743 #endif
744 
INTERCEPTOR(int,pipe,int pipefd[2])745 INTERCEPTOR(int, pipe, int pipefd[2]) {
746   if (msan_init_is_running)
747     return REAL(pipe)(pipefd);
748   ENSURE_MSAN_INITED();
749   int res = REAL(pipe)(pipefd);
750   if (!res)
751     __msan_unpoison(pipefd, sizeof(int[2]));
752   return res;
753 }
754 
INTERCEPTOR(int,pipe2,int pipefd[2],int flags)755 INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
756   ENSURE_MSAN_INITED();
757   int res = REAL(pipe2)(pipefd, flags);
758   if (!res)
759     __msan_unpoison(pipefd, sizeof(int[2]));
760   return res;
761 }
762 
INTERCEPTOR(int,socketpair,int domain,int type,int protocol,int sv[2])763 INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
764   ENSURE_MSAN_INITED();
765   int res = REAL(socketpair)(domain, type, protocol, sv);
766   if (!res)
767     __msan_unpoison(sv, sizeof(int[2]));
768   return res;
769 }
770 
INTERCEPTOR(char *,fgets,char * s,int size,void * stream)771 INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
772   ENSURE_MSAN_INITED();
773   char *res = REAL(fgets)(s, size, stream);
774   if (res)
775     __msan_unpoison(s, REAL(strlen)(s) + 1);
776   return res;
777 }
778 
779 #if !SANITIZER_FREEBSD
INTERCEPTOR(char *,fgets_unlocked,char * s,int size,void * stream)780 INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
781   ENSURE_MSAN_INITED();
782   char *res = REAL(fgets_unlocked)(s, size, stream);
783   if (res)
784     __msan_unpoison(s, REAL(strlen)(s) + 1);
785   return res;
786 }
787 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
788 #else
789 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
790 #endif
791 
INTERCEPTOR(int,getrlimit,int resource,void * rlim)792 INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
793   if (msan_init_is_running)
794     return REAL(getrlimit)(resource, rlim);
795   ENSURE_MSAN_INITED();
796   int res = REAL(getrlimit)(resource, rlim);
797   if (!res)
798     __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
799   return res;
800 }
801 
802 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,getrlimit64,int resource,void * rlim)803 INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
804   if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
805   ENSURE_MSAN_INITED();
806   int res = REAL(getrlimit64)(resource, rlim);
807   if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
808   return res;
809 }
810 
INTERCEPTOR(int,prlimit,int pid,int resource,void * new_rlimit,void * old_rlimit)811 INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
812             void *old_rlimit) {
813   if (msan_init_is_running)
814     return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
815   ENSURE_MSAN_INITED();
816   CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
817   int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
818   if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
819   return res;
820 }
821 
INTERCEPTOR(int,prlimit64,int pid,int resource,void * new_rlimit,void * old_rlimit)822 INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
823             void *old_rlimit) {
824   if (msan_init_is_running)
825     return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
826   ENSURE_MSAN_INITED();
827   CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
828   int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
829   if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
830   return res;
831 }
832 
833 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
834 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
835 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
836 #else
837 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
838 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
839 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
840 #endif
841 
842 #if SANITIZER_FREEBSD
843 // FreeBSD's <sys/utsname.h> define uname() as
844 // static __inline int uname(struct utsname *name) {
845 //   return __xuname(SYS_NMLN, (void*)name);
846 // }
INTERCEPTOR(int,__xuname,int size,void * utsname)847 INTERCEPTOR(int, __xuname, int size, void *utsname) {
848   ENSURE_MSAN_INITED();
849   int res = REAL(__xuname)(size, utsname);
850   if (!res)
851     __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
852   return res;
853 }
854 #define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(__xuname)
855 #else
INTERCEPTOR(int,uname,struct utsname * utsname)856 INTERCEPTOR(int, uname, struct utsname *utsname) {
857   ENSURE_MSAN_INITED();
858   int res = REAL(uname)(utsname);
859   if (!res)
860     __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
861   return res;
862 }
863 #define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(uname)
864 #endif
865 
INTERCEPTOR(int,gethostname,char * name,SIZE_T len)866 INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
867   ENSURE_MSAN_INITED();
868   int res = REAL(gethostname)(name, len);
869   if (!res) {
870     SIZE_T real_len = REAL(strnlen)(name, len);
871     if (real_len < len)
872       ++real_len;
873     __msan_unpoison(name, real_len);
874   }
875   return res;
876 }
877 
878 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,epoll_wait,int epfd,void * events,int maxevents,int timeout)879 INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
880     int timeout) {
881   ENSURE_MSAN_INITED();
882   int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
883   if (res > 0) {
884     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
885   }
886   return res;
887 }
888 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
889 #else
890 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
891 #endif
892 
893 #if !SANITIZER_FREEBSD
INTERCEPTOR(int,epoll_pwait,int epfd,void * events,int maxevents,int timeout,void * sigmask)894 INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
895     int timeout, void *sigmask) {
896   ENSURE_MSAN_INITED();
897   int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
898   if (res > 0) {
899     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
900   }
901   return res;
902 }
903 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
904 #else
905 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
906 #endif
907 
INTERCEPTOR(void *,calloc,SIZE_T nmemb,SIZE_T size)908 INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
909   GET_MALLOC_STACK_TRACE;
910   if (UNLIKELY(!msan_inited)) {
911     // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
912     const SIZE_T kCallocPoolSize = 1024;
913     static uptr calloc_memory_for_dlsym[kCallocPoolSize];
914     static SIZE_T allocated;
915     SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
916     void *mem = (void*)&calloc_memory_for_dlsym[allocated];
917     allocated += size_in_words;
918     CHECK(allocated < kCallocPoolSize);
919     return mem;
920   }
921   return MsanCalloc(&stack, nmemb, size);
922 }
923 
INTERCEPTOR(void *,realloc,void * ptr,SIZE_T size)924 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
925   GET_MALLOC_STACK_TRACE;
926   return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
927 }
928 
INTERCEPTOR(void *,malloc,SIZE_T size)929 INTERCEPTOR(void *, malloc, SIZE_T size) {
930   GET_MALLOC_STACK_TRACE;
931   return MsanReallocate(&stack, nullptr, size, sizeof(u64), false);
932 }
933 
__msan_allocated_memory(const void * data,uptr size)934 void __msan_allocated_memory(const void *data, uptr size) {
935   GET_MALLOC_STACK_TRACE;
936   if (flags()->poison_in_malloc) {
937     stack.tag = STACK_TRACE_TAG_POISON;
938     PoisonMemory(data, size, &stack);
939   }
940 }
941 
__msan_copy_shadow(void * dest,const void * src,uptr n)942 void __msan_copy_shadow(void *dest, const void *src, uptr n) {
943   GET_STORE_STACK_TRACE;
944   MoveShadowAndOrigin(dest, src, n, &stack);
945 }
946 
__sanitizer_dtor_callback(const void * data,uptr size)947 void __sanitizer_dtor_callback(const void *data, uptr size) {
948   GET_MALLOC_STACK_TRACE;
949   if (flags()->poison_in_dtor) {
950     stack.tag = STACK_TRACE_TAG_POISON;
951     PoisonMemory(data, size, &stack);
952   }
953 }
954 
INTERCEPTOR(void *,mmap,void * addr,SIZE_T length,int prot,int flags,int fd,OFF_T offset)955 INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
956             int fd, OFF_T offset) {
957   if (msan_init_is_running)
958     return REAL(mmap)(addr, length, prot, flags, fd, offset);
959   ENSURE_MSAN_INITED();
960   if (addr && !MEM_IS_APP(addr)) {
961     if (flags & map_fixed) {
962       *__errno_location() = errno_EINVAL;
963       return (void *)-1;
964     } else {
965       addr = nullptr;
966     }
967   }
968   void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
969   if (res != (void*)-1)
970     __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
971   return res;
972 }
973 
974 #if !SANITIZER_FREEBSD
INTERCEPTOR(void *,mmap64,void * addr,SIZE_T length,int prot,int flags,int fd,OFF64_T offset)975 INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
976             int fd, OFF64_T offset) {
977   ENSURE_MSAN_INITED();
978   if (addr && !MEM_IS_APP(addr)) {
979     if (flags & map_fixed) {
980       *__errno_location() = errno_EINVAL;
981       return (void *)-1;
982     } else {
983       addr = nullptr;
984     }
985   }
986   void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
987   if (res != (void*)-1)
988     __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
989   return res;
990 }
991 #define MSAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
992 #else
993 #define MSAN_MAYBE_INTERCEPT_MMAP64
994 #endif
995 
INTERCEPTOR(int,getrusage,int who,void * usage)996 INTERCEPTOR(int, getrusage, int who, void *usage) {
997   ENSURE_MSAN_INITED();
998   int res = REAL(getrusage)(who, usage);
999   if (res == 0) {
1000     __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
1001   }
1002   return res;
1003 }
1004 
1005 class SignalHandlerScope {
1006  public:
SignalHandlerScope()1007   SignalHandlerScope() {
1008     if (MsanThread *t = GetCurrentThread())
1009       t->EnterSignalHandler();
1010   }
~SignalHandlerScope()1011   ~SignalHandlerScope() {
1012     if (MsanThread *t = GetCurrentThread())
1013       t->LeaveSignalHandler();
1014   }
1015 };
1016 
1017 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1018 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1019 // the signal handler.
1020 const int kMaxSignals = 1024;
1021 static atomic_uintptr_t sigactions[kMaxSignals];
1022 static StaticSpinMutex sigactions_mu;
1023 
SignalHandler(int signo)1024 static void SignalHandler(int signo) {
1025   SignalHandlerScope signal_handler_scope;
1026   ScopedThreadLocalStateBackup stlsb;
1027   UnpoisonParam(1);
1028 
1029   typedef void (*signal_cb)(int x);
1030   signal_cb cb =
1031       (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1032   cb(signo);
1033 }
1034 
SignalAction(int signo,void * si,void * uc)1035 static void SignalAction(int signo, void *si, void *uc) {
1036   SignalHandlerScope signal_handler_scope;
1037   ScopedThreadLocalStateBackup stlsb;
1038   UnpoisonParam(3);
1039   __msan_unpoison(si, sizeof(__sanitizer_sigaction));
1040   __msan_unpoison(uc, __sanitizer::ucontext_t_sz);
1041 
1042   typedef void (*sigaction_cb)(int, void *, void *);
1043   sigaction_cb cb =
1044       (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1045   cb(signo, si, uc);
1046 }
1047 
INTERCEPTOR(int,sigaction,int signo,const __sanitizer_sigaction * act,__sanitizer_sigaction * oldact)1048 INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
1049             __sanitizer_sigaction *oldact) {
1050   ENSURE_MSAN_INITED();
1051   // FIXME: check that *act is unpoisoned.
1052   // That requires intercepting all of sigemptyset, sigfillset, etc.
1053   int res;
1054   if (flags()->wrap_signals) {
1055     SpinMutexLock lock(&sigactions_mu);
1056     CHECK_LT(signo, kMaxSignals);
1057     uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
1058     __sanitizer_sigaction new_act;
1059     __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
1060     if (act) {
1061       REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
1062       uptr cb = (uptr)pnew_act->sigaction;
1063       uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
1064                         ? (uptr)SignalAction
1065                         : (uptr)SignalHandler;
1066       if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1067         atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1068         pnew_act->sigaction = (void (*)(int, void *, void *))new_cb;
1069       }
1070     }
1071     res = REAL(sigaction)(signo, pnew_act, oldact);
1072     if (res == 0 && oldact) {
1073       uptr cb = (uptr)oldact->sigaction;
1074       if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1075         oldact->sigaction = (void (*)(int, void *, void *))old_cb;
1076       }
1077     }
1078   } else {
1079     res = REAL(sigaction)(signo, act, oldact);
1080   }
1081 
1082   if (res == 0 && oldact) {
1083     __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
1084   }
1085   return res;
1086 }
1087 
INTERCEPTOR(int,signal,int signo,uptr cb)1088 INTERCEPTOR(int, signal, int signo, uptr cb) {
1089   ENSURE_MSAN_INITED();
1090   if (flags()->wrap_signals) {
1091     CHECK_LT(signo, kMaxSignals);
1092     SpinMutexLock lock(&sigactions_mu);
1093     if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1094       atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1095       cb = (uptr) SignalHandler;
1096     }
1097     return REAL(signal)(signo, cb);
1098   } else {
1099     return REAL(signal)(signo, cb);
1100   }
1101 }
1102 
1103 extern "C" int pthread_attr_init(void *attr);
1104 extern "C" int pthread_attr_destroy(void *attr);
1105 
MsanThreadStartFunc(void * arg)1106 static void *MsanThreadStartFunc(void *arg) {
1107   MsanThread *t = (MsanThread *)arg;
1108   SetCurrentThread(t);
1109   return t->ThreadStart();
1110 }
1111 
INTERCEPTOR(int,pthread_create,void * th,void * attr,void * (* callback)(void *),void * param)1112 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
1113             void * param) {
1114   ENSURE_MSAN_INITED(); // for GetTlsSize()
1115   __sanitizer_pthread_attr_t myattr;
1116   if (!attr) {
1117     pthread_attr_init(&myattr);
1118     attr = &myattr;
1119   }
1120 
1121   AdjustStackSize(attr);
1122 
1123   MsanThread *t = MsanThread::Create(callback, param);
1124 
1125   int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
1126 
1127   if (attr == &myattr)
1128     pthread_attr_destroy(&myattr);
1129   if (!res) {
1130     __msan_unpoison(th, __sanitizer::pthread_t_sz);
1131   }
1132   return res;
1133 }
1134 
INTERCEPTOR(int,pthread_key_create,__sanitizer_pthread_key_t * key,void (* dtor)(void * value))1135 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
1136             void (*dtor)(void *value)) {
1137   if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
1138   ENSURE_MSAN_INITED();
1139   int res = REAL(pthread_key_create)(key, dtor);
1140   if (!res && key)
1141     __msan_unpoison(key, sizeof(*key));
1142   return res;
1143 }
1144 
INTERCEPTOR(int,pthread_join,void * th,void ** retval)1145 INTERCEPTOR(int, pthread_join, void *th, void **retval) {
1146   ENSURE_MSAN_INITED();
1147   int res = REAL(pthread_join)(th, retval);
1148   if (!res && retval)
1149     __msan_unpoison(retval, sizeof(*retval));
1150   return res;
1151 }
1152 
1153 extern char *tzname[2];
1154 
INTERCEPTOR(void,tzset,int fake)1155 INTERCEPTOR(void, tzset, int fake) {
1156   ENSURE_MSAN_INITED();
1157   REAL(tzset)(fake);
1158   if (tzname[0])
1159     __msan_unpoison(tzname[0], REAL(strlen)(tzname[0]) + 1);
1160   if (tzname[1])
1161     __msan_unpoison(tzname[1], REAL(strlen)(tzname[1]) + 1);
1162   return;
1163 }
1164 
1165 struct MSanAtExitRecord {
1166   void (*func)(void *arg);
1167   void *arg;
1168 };
1169 
MSanAtExitWrapper(void * arg)1170 void MSanAtExitWrapper(void *arg) {
1171   UnpoisonParam(1);
1172   MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
1173   r->func(r->arg);
1174   InternalFree(r);
1175 }
1176 
1177 // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)1178 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
1179             void *dso_handle) {
1180   if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
1181   ENSURE_MSAN_INITED();
1182   MSanAtExitRecord *r =
1183       (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
1184   r->func = func;
1185   r->arg = arg;
1186   return REAL(__cxa_atexit)(MSanAtExitWrapper, r, dso_handle);
1187 }
1188 
DECLARE_REAL(int,shmctl,int shmid,int cmd,void * buf)1189 DECLARE_REAL(int, shmctl, int shmid, int cmd, void *buf)
1190 
1191 INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
1192   ENSURE_MSAN_INITED();
1193   void *p = REAL(shmat)(shmid, shmaddr, shmflg);
1194   if (p != (void *)-1) {
1195     __sanitizer_shmid_ds ds;
1196     int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
1197     if (!res) {
1198       __msan_unpoison(p, ds.shm_segsz);
1199     }
1200   }
1201   return p;
1202 }
1203 
BeforeFork()1204 static void BeforeFork() {
1205   StackDepotLockAll();
1206   ChainedOriginDepotLockAll();
1207 }
1208 
AfterFork()1209 static void AfterFork() {
1210   ChainedOriginDepotUnlockAll();
1211   StackDepotUnlockAll();
1212 }
1213 
INTERCEPTOR(int,fork,void)1214 INTERCEPTOR(int, fork, void) {
1215   ENSURE_MSAN_INITED();
1216   BeforeFork();
1217   int pid = REAL(fork)();
1218   AfterFork();
1219   return pid;
1220 }
1221 
INTERCEPTOR(int,openpty,int * amaster,int * aslave,char * name,const void * termp,const void * winp)1222 INTERCEPTOR(int, openpty, int *amaster, int *aslave, char *name,
1223             const void *termp, const void *winp) {
1224   ENSURE_MSAN_INITED();
1225   InterceptorScope interceptor_scope;
1226   int res = REAL(openpty)(amaster, aslave, name, termp, winp);
1227   if (!res) {
1228     __msan_unpoison(amaster, sizeof(*amaster));
1229     __msan_unpoison(aslave, sizeof(*aslave));
1230   }
1231   return res;
1232 }
1233 
INTERCEPTOR(int,forkpty,int * amaster,char * name,const void * termp,const void * winp)1234 INTERCEPTOR(int, forkpty, int *amaster, char *name, const void *termp,
1235             const void *winp) {
1236   ENSURE_MSAN_INITED();
1237   InterceptorScope interceptor_scope;
1238   int res = REAL(forkpty)(amaster, name, termp, winp);
1239   if (res != -1)
1240     __msan_unpoison(amaster, sizeof(*amaster));
1241   return res;
1242 }
1243 
1244 struct MSanInterceptorContext {
1245   bool in_interceptor_scope;
1246 };
1247 
1248 namespace __msan {
1249 
OnExit()1250 int OnExit() {
1251   // FIXME: ask frontend whether we need to return failure.
1252   return 0;
1253 }
1254 
1255 } // namespace __msan
1256 
1257 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1258 // interceptors.
1259 #define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
1260   do {                                                          \
1261     if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1262       CHECK_UNPOISONED_0(x, n);                                 \
1263   } while (0)
1264 
1265 #define MSAN_INTERCEPT_FUNC(name)                                       \
1266   do {                                                                  \
1267     if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                     \
1268       VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \
1269   } while (0)
1270 
1271 #define MSAN_INTERCEPT_FUNC_VER(name, ver)                                    \
1272   do {                                                                        \
1273     if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name)))                  \
1274       VReport(                                                                \
1275           1, "MemorySanitizer: failed to intercept '" #name "@@" #ver "'\n"); \
1276   } while (0)
1277 
1278 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1279 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
1280   MSAN_INTERCEPT_FUNC_VER(name, ver)
1281 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count)  \
1282   UnpoisonParam(count)
1283 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1284   __msan_unpoison(ptr, size)
1285 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1286   CHECK_UNPOISONED_CTX(ctx, ptr, size)
1287 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1288   __msan_unpoison(ptr, size)
1289 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                  \
1290   if (msan_init_is_running) return REAL(func)(__VA_ARGS__);       \
1291   ENSURE_MSAN_INITED();                                           \
1292   MSanInterceptorContext msan_ctx = {IsInInterceptorScope()};     \
1293   ctx = (void *)&msan_ctx;                                        \
1294   (void)ctx;                                                      \
1295   InterceptorScope interceptor_scope;                             \
1296   __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */
1297 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1298   do {                                            \
1299   } while (false)
1300 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1301   do {                                         \
1302   } while (false)
1303 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1304   do {                                         \
1305   } while (false)
1306 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1307   do {                                                      \
1308   } while (false)
1309 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1310   do {                                                \
1311   } while (false)  // FIXME
1312 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1313   do {                                                         \
1314   } while (false)  // FIXME
1315 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1316 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1317 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)                    \
1318   do {                                                                         \
1319     link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle));                   \
1320     if (filename && map)                                                       \
1321       ForEachMappedRegion(map, __msan_unpoison);                               \
1322   } while (false)
1323 
1324 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
1325   if (MsanThread *t = GetCurrentThread()) {                                    \
1326     *begin = t->tls_begin();                                                   \
1327     *end = t->tls_end();                                                       \
1328   } else {                                                                     \
1329     *begin = *end = 0;                                                         \
1330   }
1331 
1332 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1333 // Msan needs custom handling of these:
1334 #undef SANITIZER_INTERCEPT_MEMSET
1335 #undef SANITIZER_INTERCEPT_MEMMOVE
1336 #undef SANITIZER_INTERCEPT_MEMCPY
1337 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1338 
1339 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1340 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1341   do {                                       \
1342   } while (false)
1343 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1344   do {                                       \
1345   } while (false)
1346 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1347 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1348 
1349 struct dlinfo {
1350   char *dli_fname;
1351   void *dli_fbase;
1352   char *dli_sname;
1353   void *dli_saddr;
1354 };
1355 
INTERCEPTOR(int,dladdr,void * addr,dlinfo * info)1356 INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
1357   void *ctx;
1358   COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
1359   int res = REAL(dladdr)(addr, info);
1360   if (res != 0) {
1361     __msan_unpoison(info, sizeof(*info));
1362     if (info->dli_fname)
1363       __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
1364     if (info->dli_sname)
1365       __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
1366   }
1367   return res;
1368 }
1369 
INTERCEPTOR(char *,dlerror,int fake)1370 INTERCEPTOR(char *, dlerror, int fake) {
1371   void *ctx;
1372   COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
1373   char *res = REAL(dlerror)(fake);
1374   if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
1375   return res;
1376 }
1377 
1378 typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
1379                                   void *data);
1380 struct dl_iterate_phdr_data {
1381   dl_iterate_phdr_cb callback;
1382   void *data;
1383 };
1384 
msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info * info,SIZE_T size,void * data)1385 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
1386                                    void *data) {
1387   if (info) {
1388     __msan_unpoison(info, size);
1389     if (info->dlpi_phdr && info->dlpi_phnum)
1390       __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
1391     if (info->dlpi_name)
1392       __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1);
1393   }
1394   dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
1395   UnpoisonParam(3);
1396   return cbdata->callback(info, size, cbdata->data);
1397 }
1398 
INTERCEPTOR(int,dl_iterate_phdr,dl_iterate_phdr_cb callback,void * data)1399 INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
1400   void *ctx;
1401   COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
1402   dl_iterate_phdr_data cbdata;
1403   cbdata.callback = callback;
1404   cbdata.data = data;
1405   int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
1406   return res;
1407 }
1408 
1409 // These interface functions reside here so that they can use
1410 // REAL(memset), etc.
__msan_unpoison(const void * a,uptr size)1411 void __msan_unpoison(const void *a, uptr size) {
1412   if (!MEM_IS_APP(a)) return;
1413   SetShadow(a, size, 0);
1414 }
1415 
__msan_poison(const void * a,uptr size)1416 void __msan_poison(const void *a, uptr size) {
1417   if (!MEM_IS_APP(a)) return;
1418   SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
1419 }
1420 
__msan_poison_stack(void * a,uptr size)1421 void __msan_poison_stack(void *a, uptr size) {
1422   if (!MEM_IS_APP(a)) return;
1423   SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
1424 }
1425 
__msan_clear_and_unpoison(void * a,uptr size)1426 void __msan_clear_and_unpoison(void *a, uptr size) {
1427   REAL(memset)(a, 0, size);
1428   SetShadow(a, size, 0);
1429 }
1430 
__msan_memcpy(void * dest,const void * src,SIZE_T n)1431 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1432   if (!msan_inited) return internal_memcpy(dest, src, n);
1433   if (msan_init_is_running || __msan::IsInSymbolizer())
1434     return REAL(memcpy)(dest, src, n);
1435   ENSURE_MSAN_INITED();
1436   GET_STORE_STACK_TRACE;
1437   void *res = REAL(memcpy)(dest, src, n);
1438   CopyShadowAndOrigin(dest, src, n, &stack);
1439   return res;
1440 }
1441 
__msan_memset(void * s,int c,SIZE_T n)1442 void *__msan_memset(void *s, int c, SIZE_T n) {
1443   if (!msan_inited) return internal_memset(s, c, n);
1444   if (msan_init_is_running) return REAL(memset)(s, c, n);
1445   ENSURE_MSAN_INITED();
1446   void *res = REAL(memset)(s, c, n);
1447   __msan_unpoison(s, n);
1448   return res;
1449 }
1450 
__msan_memmove(void * dest,const void * src,SIZE_T n)1451 void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1452   if (!msan_inited) return internal_memmove(dest, src, n);
1453   if (msan_init_is_running) return REAL(memmove)(dest, src, n);
1454   ENSURE_MSAN_INITED();
1455   GET_STORE_STACK_TRACE;
1456   void *res = REAL(memmove)(dest, src, n);
1457   MoveShadowAndOrigin(dest, src, n, &stack);
1458   return res;
1459 }
1460 
__msan_unpoison_string(const char * s)1461 void __msan_unpoison_string(const char* s) {
1462   if (!MEM_IS_APP(s)) return;
1463   __msan_unpoison(s, REAL(strlen)(s) + 1);
1464 }
1465 
1466 namespace __msan {
1467 
InitializeInterceptors()1468 void InitializeInterceptors() {
1469   static int inited = 0;
1470   CHECK_EQ(inited, 0);
1471   InitializeCommonInterceptors();
1472 
1473   INTERCEPT_FUNCTION(mmap);
1474   MSAN_MAYBE_INTERCEPT_MMAP64;
1475   INTERCEPT_FUNCTION(posix_memalign);
1476   MSAN_MAYBE_INTERCEPT_MEMALIGN;
1477   INTERCEPT_FUNCTION(__libc_memalign);
1478   INTERCEPT_FUNCTION(valloc);
1479   MSAN_MAYBE_INTERCEPT_PVALLOC;
1480   INTERCEPT_FUNCTION(malloc);
1481   INTERCEPT_FUNCTION(calloc);
1482   INTERCEPT_FUNCTION(realloc);
1483   INTERCEPT_FUNCTION(free);
1484   MSAN_MAYBE_INTERCEPT_CFREE;
1485   INTERCEPT_FUNCTION(malloc_usable_size);
1486   MSAN_MAYBE_INTERCEPT_MALLINFO;
1487   MSAN_MAYBE_INTERCEPT_MALLOPT;
1488   MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
1489   INTERCEPT_FUNCTION(fread);
1490   MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
1491   INTERCEPT_FUNCTION(readlink);
1492   INTERCEPT_FUNCTION(memcpy);
1493   INTERCEPT_FUNCTION(memccpy);
1494   INTERCEPT_FUNCTION(mempcpy);
1495   INTERCEPT_FUNCTION(memset);
1496   INTERCEPT_FUNCTION(memmove);
1497   INTERCEPT_FUNCTION(bcopy);
1498   INTERCEPT_FUNCTION(wmemset);
1499   INTERCEPT_FUNCTION(wmemcpy);
1500   INTERCEPT_FUNCTION(wmempcpy);
1501   INTERCEPT_FUNCTION(wmemmove);
1502   INTERCEPT_FUNCTION(strcpy);  // NOLINT
1503   INTERCEPT_FUNCTION(stpcpy);  // NOLINT
1504   INTERCEPT_FUNCTION(strdup);
1505   MSAN_MAYBE_INTERCEPT___STRDUP;
1506   INTERCEPT_FUNCTION(strndup);
1507   MSAN_MAYBE_INTERCEPT___STRNDUP;
1508   INTERCEPT_FUNCTION(strncpy);  // NOLINT
1509   INTERCEPT_FUNCTION(gcvt);
1510   INTERCEPT_FUNCTION(strcat);  // NOLINT
1511   INTERCEPT_FUNCTION(strncat);  // NOLINT
1512   INTERCEPT_STRTO(strtod);
1513   INTERCEPT_STRTO(strtof);
1514   INTERCEPT_STRTO(strtold);
1515   INTERCEPT_STRTO(strtol);
1516   INTERCEPT_STRTO(strtoul);
1517   INTERCEPT_STRTO(strtoll);
1518   INTERCEPT_STRTO(strtoull);
1519   INTERCEPT_STRTO(wcstod);
1520   INTERCEPT_STRTO(wcstof);
1521   INTERCEPT_STRTO(wcstold);
1522   INTERCEPT_STRTO(wcstol);
1523   INTERCEPT_STRTO(wcstoul);
1524   INTERCEPT_STRTO(wcstoll);
1525   INTERCEPT_STRTO(wcstoull);
1526 #ifdef SANITIZER_NLDBL_VERSION
1527   INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
1528   INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
1529 #else
1530   INTERCEPT_FUNCTION(vswprintf);
1531   INTERCEPT_FUNCTION(swprintf);
1532 #endif
1533   INTERCEPT_FUNCTION(strxfrm);
1534   INTERCEPT_FUNCTION(strxfrm_l);
1535   INTERCEPT_FUNCTION(strftime);
1536   INTERCEPT_FUNCTION(strftime_l);
1537   MSAN_MAYBE_INTERCEPT___STRFTIME_L;
1538   INTERCEPT_FUNCTION(wcsftime);
1539   INTERCEPT_FUNCTION(wcsftime_l);
1540   MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
1541   INTERCEPT_FUNCTION(mbtowc);
1542   INTERCEPT_FUNCTION(mbrtowc);
1543   INTERCEPT_FUNCTION(wcslen);
1544   INTERCEPT_FUNCTION(wcschr);
1545   INTERCEPT_FUNCTION(wcscpy);
1546   INTERCEPT_FUNCTION(wcscmp);
1547   INTERCEPT_FUNCTION(getenv);
1548   INTERCEPT_FUNCTION(setenv);
1549   INTERCEPT_FUNCTION(putenv);
1550   INTERCEPT_FUNCTION(gettimeofday);
1551   INTERCEPT_FUNCTION(fcvt);
1552   MSAN_MAYBE_INTERCEPT___FXSTAT;
1553   MSAN_INTERCEPT_FSTATAT;
1554   MSAN_MAYBE_INTERCEPT___FXSTAT64;
1555   MSAN_MAYBE_INTERCEPT___FXSTATAT64;
1556   INTERCEPT_FUNCTION(pipe);
1557   INTERCEPT_FUNCTION(pipe2);
1558   INTERCEPT_FUNCTION(socketpair);
1559   INTERCEPT_FUNCTION(fgets);
1560   MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
1561   INTERCEPT_FUNCTION(getrlimit);
1562   MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
1563   MSAN_MAYBE_INTERCEPT_PRLIMIT;
1564   MSAN_MAYBE_INTERCEPT_PRLIMIT64;
1565   MSAN_INTERCEPT_UNAME;
1566   INTERCEPT_FUNCTION(gethostname);
1567   MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1568   MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1569   INTERCEPT_FUNCTION(dladdr);
1570   INTERCEPT_FUNCTION(dlerror);
1571   INTERCEPT_FUNCTION(dl_iterate_phdr);
1572   INTERCEPT_FUNCTION(getrusage);
1573   INTERCEPT_FUNCTION(sigaction);
1574   INTERCEPT_FUNCTION(signal);
1575 #if defined(__mips__)
1576   INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
1577 #else
1578   INTERCEPT_FUNCTION(pthread_create);
1579 #endif
1580   INTERCEPT_FUNCTION(pthread_key_create);
1581   INTERCEPT_FUNCTION(pthread_join);
1582   INTERCEPT_FUNCTION(tzset);
1583   INTERCEPT_FUNCTION(__cxa_atexit);
1584   INTERCEPT_FUNCTION(shmat);
1585   INTERCEPT_FUNCTION(fork);
1586   INTERCEPT_FUNCTION(openpty);
1587   INTERCEPT_FUNCTION(forkpty);
1588 
1589   inited = 1;
1590 }
1591 } // namespace __msan
1592