xref: /freebsd/contrib/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp (revision f126890ac5386406dadf7c4cfa9566cbb56537c5)
1 //===-- msan_interceptors.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of MemorySanitizer.
10 //
11 // Interceptors for standard library functions.
12 //
13 // FIXME: move as many interceptors as possible into
14 // sanitizer_common/sanitizer_common_interceptors.h
15 //===----------------------------------------------------------------------===//
16 
17 #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
18 
19 #include "interception/interception.h"
20 #include "msan.h"
21 #include "msan_chained_origin_depot.h"
22 #include "msan_dl.h"
23 #include "msan_origin.h"
24 #include "msan_poisoning.h"
25 #include "msan_report.h"
26 #include "msan_thread.h"
27 #include "sanitizer_common/sanitizer_allocator.h"
28 #include "sanitizer_common/sanitizer_allocator_dlsym.h"
29 #include "sanitizer_common/sanitizer_allocator_interface.h"
30 #include "sanitizer_common/sanitizer_atomic.h"
31 #include "sanitizer_common/sanitizer_common.h"
32 #include "sanitizer_common/sanitizer_errno.h"
33 #include "sanitizer_common/sanitizer_errno_codes.h"
34 #include "sanitizer_common/sanitizer_glibc_version.h"
35 #include "sanitizer_common/sanitizer_libc.h"
36 #include "sanitizer_common/sanitizer_linux.h"
37 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
38 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
39 #include "sanitizer_common/sanitizer_stackdepot.h"
40 #include "sanitizer_common/sanitizer_tls_get_addr.h"
41 #include "sanitizer_common/sanitizer_vector.h"
42 
43 #if SANITIZER_NETBSD
44 #define fstat __fstat50
45 #define gettimeofday __gettimeofday50
46 #define getrusage __getrusage50
47 #define tzset __tzset50
48 #endif
49 
50 #include <stdarg.h>
51 // ACHTUNG! No other system header includes in this file.
52 // Ideally, we should get rid of stdarg.h as well.
53 
54 using namespace __msan;
55 
56 using __sanitizer::memory_order;
57 using __sanitizer::atomic_load;
58 using __sanitizer::atomic_store;
59 using __sanitizer::atomic_uintptr_t;
60 
61 DECLARE_REAL(SIZE_T, strlen, const char *s)
62 DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
63 DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n)
64 DECLARE_REAL(void *, memset, void *dest, int c, uptr n)
65 
66 // True if this is a nested interceptor.
67 static THREADLOCAL int in_interceptor_scope;
68 
69 void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope; }
70 void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope; }
71 
72 struct InterceptorScope {
73   InterceptorScope() { ++in_interceptor_scope; }
74   ~InterceptorScope() { --in_interceptor_scope; }
75 };
76 
77 bool IsInInterceptorScope() {
78   return in_interceptor_scope;
79 }
80 
81 struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
82   static bool UseImpl() { return !msan_inited; }
83 };
84 
85 #define ENSURE_MSAN_INITED() do { \
86   CHECK(!msan_init_is_running); \
87   if (!msan_inited) { \
88     __msan_init(); \
89   } \
90 } while (0)
91 
92 // Check that [x, x+n) range is unpoisoned.
93 #define CHECK_UNPOISONED_0(x, n)                                  \
94   do {                                                            \
95     sptr __offset = __msan_test_shadow(x, n);                     \
96     if (__msan::IsInSymbolizerOrUnwider())                        \
97       break;                                                      \
98     if (__offset >= 0 && __msan::flags()->report_umrs) {          \
99       GET_CALLER_PC_BP;                                           \
100       ReportUMRInsideAddressRange(__func__, x, n, __offset);      \
101       __msan::PrintWarningWithOrigin(                             \
102           pc, bp, __msan_get_origin((const char *)x + __offset)); \
103       if (__msan::flags()->halt_on_error) {                       \
104         Printf("Exiting\n");                                      \
105         Die();                                                    \
106       }                                                           \
107     }                                                             \
108   } while (0)
109 
110 // Check that [x, x+n) range is unpoisoned unless we are in a nested
111 // interceptor.
112 #define CHECK_UNPOISONED(x, n)                             \
113   do {                                                     \
114     if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
115   } while (0)
116 
117 #define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n)               \
118   CHECK_UNPOISONED((x),                                         \
119     common_flags()->strict_string_checks ? (len) + 1 : (n) )
120 
121 #define CHECK_UNPOISONED_STRING(x, n)                           \
122     CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
123 
124 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
125 INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
126             void *file) {
127   ENSURE_MSAN_INITED();
128   SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
129   if (res > 0)
130     __msan_unpoison(ptr, res *size);
131   return res;
132 }
133 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
134 #else
135 #define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
136 #endif
137 
138 #if !SANITIZER_NETBSD
139 INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
140   return (char *)__msan_memcpy(dest, src, n) + n;
141 }
142 #define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
143 #else
144 #define MSAN_MAYBE_INTERCEPT_MEMPCPY
145 #endif
146 
147 INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
148   ENSURE_MSAN_INITED();
149   void *res = REAL(memccpy)(dest, src, c, n);
150   CHECK(!res || (res >= dest && res <= (char *)dest + n));
151   SIZE_T sz = res ? (char *)res - (char *)dest : n;
152   CHECK_UNPOISONED(src, sz);
153   __msan_unpoison(dest, sz);
154   return res;
155 }
156 
157 INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
158   return __msan_memmove(dest, src, n);
159 }
160 
161 INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
162   GET_MALLOC_STACK_TRACE;
163   CHECK_NE(memptr, 0);
164   int res = msan_posix_memalign(memptr, alignment, size, &stack);
165   if (!res)
166     __msan_unpoison(memptr, sizeof(*memptr));
167   return res;
168 }
169 
170 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
171 INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) {
172   GET_MALLOC_STACK_TRACE;
173   return msan_memalign(alignment, size, &stack);
174 }
175 #define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
176 #else
177 #define MSAN_MAYBE_INTERCEPT_MEMALIGN
178 #endif
179 
180 INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {
181   GET_MALLOC_STACK_TRACE;
182   return msan_aligned_alloc(alignment, size, &stack);
183 }
184 
185 #if !SANITIZER_NETBSD
186 INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) {
187   GET_MALLOC_STACK_TRACE;
188   void *ptr = msan_memalign(alignment, size, &stack);
189   if (ptr)
190     DTLS_on_libc_memalign(ptr, size);
191   return ptr;
192 }
193 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
194 #else
195 #define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
196 #endif
197 
198 INTERCEPTOR(void *, valloc, SIZE_T size) {
199   GET_MALLOC_STACK_TRACE;
200   return msan_valloc(size, &stack);
201 }
202 
203 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
204 INTERCEPTOR(void *, pvalloc, SIZE_T size) {
205   GET_MALLOC_STACK_TRACE;
206   return msan_pvalloc(size, &stack);
207 }
208 #define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
209 #else
210 #define MSAN_MAYBE_INTERCEPT_PVALLOC
211 #endif
212 
213 INTERCEPTOR(void, free, void *ptr) {
214   if (UNLIKELY(!ptr))
215     return;
216   if (DlsymAlloc::PointerIsMine(ptr))
217     return DlsymAlloc::Free(ptr);
218   GET_MALLOC_STACK_TRACE;
219   MsanDeallocate(&stack, ptr);
220 }
221 
222 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
223 INTERCEPTOR(void, cfree, void *ptr) {
224   if (UNLIKELY(!ptr))
225     return;
226   if (DlsymAlloc::PointerIsMine(ptr))
227     return DlsymAlloc::Free(ptr);
228   GET_MALLOC_STACK_TRACE;
229   MsanDeallocate(&stack, ptr);
230 }
231 #  define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
232 #else
233 #define MSAN_MAYBE_INTERCEPT_CFREE
234 #endif
235 
236 #if !SANITIZER_NETBSD
237 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
238   return __sanitizer_get_allocated_size(ptr);
239 }
240 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
241   INTERCEPT_FUNCTION(malloc_usable_size)
242 #else
243 #define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
244 #endif
245 
246 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
247 // This function actually returns a struct by value, but we can't unpoison a
248 // temporary! The following is equivalent on all supported platforms but
249 // aarch64 (which uses a different register for sret value).  We have a test
250 // to confirm that.
251 INTERCEPTOR(void, mallinfo, __sanitizer_struct_mallinfo *sret) {
252 #ifdef __aarch64__
253   uptr r8;
254   asm volatile("mov %0,x8" : "=r" (r8));
255   sret = reinterpret_cast<__sanitizer_struct_mallinfo*>(r8);
256 #endif
257   REAL(memset)(sret, 0, sizeof(*sret));
258   __msan_unpoison(sret, sizeof(*sret));
259 }
260 #define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
261 #else
262 #define MSAN_MAYBE_INTERCEPT_MALLINFO
263 #endif
264 
265 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
266 INTERCEPTOR(int, mallopt, int cmd, int value) {
267   return 0;
268 }
269 #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
270 #else
271 #define MSAN_MAYBE_INTERCEPT_MALLOPT
272 #endif
273 
274 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
275 INTERCEPTOR(void, malloc_stats, void) {
276   // FIXME: implement, but don't call REAL(malloc_stats)!
277 }
278 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
279 #else
280 #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
281 #endif
282 
283 INTERCEPTOR(char *, strcpy, char *dest, const char *src) {
284   ENSURE_MSAN_INITED();
285   GET_STORE_STACK_TRACE;
286   SIZE_T n = internal_strlen(src);
287   CHECK_UNPOISONED_STRING(src + n, 0);
288   char *res = REAL(strcpy)(dest, src);
289   CopyShadowAndOrigin(dest, src, n + 1, &stack);
290   return res;
291 }
292 
293 INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {
294   ENSURE_MSAN_INITED();
295   GET_STORE_STACK_TRACE;
296   SIZE_T copy_size = internal_strnlen(src, n);
297   if (copy_size < n)
298     copy_size++;  // trailing \0
299   char *res = REAL(strncpy)(dest, src, n);
300   CopyShadowAndOrigin(dest, src, copy_size, &stack);
301   __msan_unpoison(dest + copy_size, n - copy_size);
302   return res;
303 }
304 
305 #if !SANITIZER_NETBSD
306 INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {
307   ENSURE_MSAN_INITED();
308   GET_STORE_STACK_TRACE;
309   SIZE_T n = internal_strlen(src);
310   CHECK_UNPOISONED_STRING(src + n, 0);
311   char *res = REAL(stpcpy)(dest, src);
312   CopyShadowAndOrigin(dest, src, n + 1, &stack);
313   return res;
314 }
315 
316 INTERCEPTOR(char *, stpncpy, char *dest, const char *src, SIZE_T n) {
317   ENSURE_MSAN_INITED();
318   GET_STORE_STACK_TRACE;
319   SIZE_T copy_size = Min(n, internal_strnlen(src, n) + 1);
320   char *res = REAL(stpncpy)(dest, src, n);
321   CopyShadowAndOrigin(dest, src, copy_size, &stack);
322   __msan_unpoison(dest + copy_size, n - copy_size);
323   return res;
324 }
325 #  define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
326 #  define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
327 #else
328 #define MSAN_MAYBE_INTERCEPT_STPCPY
329 #  define MSAN_MAYBE_INTERCEPT_STPNCPY
330 #endif
331 
332 INTERCEPTOR(char *, strdup, char *src) {
333   ENSURE_MSAN_INITED();
334   GET_STORE_STACK_TRACE;
335   // On FreeBSD strdup() leverages strlen().
336   InterceptorScope interceptor_scope;
337   SIZE_T n = internal_strlen(src);
338   CHECK_UNPOISONED_STRING(src + n, 0);
339   char *res = REAL(strdup)(src);
340   CopyShadowAndOrigin(res, src, n + 1, &stack);
341   return res;
342 }
343 
344 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
345 INTERCEPTOR(char *, __strdup, char *src) {
346   ENSURE_MSAN_INITED();
347   GET_STORE_STACK_TRACE;
348   SIZE_T n = internal_strlen(src);
349   CHECK_UNPOISONED_STRING(src + n, 0);
350   char *res = REAL(__strdup)(src);
351   CopyShadowAndOrigin(res, src, n + 1, &stack);
352   return res;
353 }
354 #define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
355 #else
356 #define MSAN_MAYBE_INTERCEPT___STRDUP
357 #endif
358 
359 #if !SANITIZER_NETBSD
360 INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
361   ENSURE_MSAN_INITED();
362   char *res = REAL(gcvt)(number, ndigit, buf);
363   SIZE_T n = internal_strlen(buf);
364   __msan_unpoison(buf, n + 1);
365   return res;
366 }
367 #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
368 #else
369 #define MSAN_MAYBE_INTERCEPT_GCVT
370 #endif
371 
372 INTERCEPTOR(char *, strcat, char *dest, const char *src) {
373   ENSURE_MSAN_INITED();
374   GET_STORE_STACK_TRACE;
375   SIZE_T src_size = internal_strlen(src);
376   SIZE_T dest_size = internal_strlen(dest);
377   CHECK_UNPOISONED_STRING(src + src_size, 0);
378   CHECK_UNPOISONED_STRING(dest + dest_size, 0);
379   char *res = REAL(strcat)(dest, src);
380   CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
381   return res;
382 }
383 
384 INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {
385   ENSURE_MSAN_INITED();
386   GET_STORE_STACK_TRACE;
387   SIZE_T dest_size = internal_strlen(dest);
388   SIZE_T copy_size = internal_strnlen(src, n);
389   CHECK_UNPOISONED_STRING(dest + dest_size, 0);
390   char *res = REAL(strncat)(dest, src, n);
391   CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
392   __msan_unpoison(dest + dest_size + copy_size, 1); // \0
393   return res;
394 }
395 
396 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
397 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
398 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
399   ENSURE_MSAN_INITED();                             \
400   ret_type res = REAL(func)(__VA_ARGS__);           \
401   __msan_unpoison(endptr, sizeof(*endptr));         \
402   return res;
403 
404 #define INTERCEPTOR_STRTO(ret_type, func, char_type)                       \
405   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
406     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr);                  \
407   }
408 
409 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)                \
410   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
411               int base) {                                                \
412     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base);          \
413   }
414 
415 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type)                 \
416   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
417               void *loc) {                                               \
418     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc);           \
419   }
420 
421 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type)            \
422   INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
423               int base, void *loc) {                                     \
424     INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc);     \
425   }
426 
427 #if SANITIZER_NETBSD
428 #define INTERCEPTORS_STRTO(ret_type, func, char_type)      \
429   INTERCEPTOR_STRTO(ret_type, func, char_type)             \
430   INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
431 
432 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type)      \
433   INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)             \
434   INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
435 
436 #else
437 #define INTERCEPTORS_STRTO(ret_type, func, char_type)      \
438   INTERCEPTOR_STRTO(ret_type, func, char_type)             \
439   INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)     \
440   INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
441   INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
442 
443 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type)      \
444   INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)             \
445   INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)     \
446   INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
447   INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
448 #endif
449 
450 INTERCEPTORS_STRTO(double, strtod, char)
451 INTERCEPTORS_STRTO(float, strtof, char)
452 INTERCEPTORS_STRTO(long double, strtold, char)
453 INTERCEPTORS_STRTO_BASE(long, strtol, char)
454 INTERCEPTORS_STRTO_BASE(long long, strtoll, char)
455 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)
456 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)
457 INTERCEPTORS_STRTO_BASE(u64, strtouq, char)
458 
459 INTERCEPTORS_STRTO(double, wcstod, wchar_t)
460 INTERCEPTORS_STRTO(float, wcstof, wchar_t)
461 INTERCEPTORS_STRTO(long double, wcstold, wchar_t)
462 INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)
463 INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)
464 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)
465 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)
466 
467 #if SANITIZER_GLIBC
468 INTERCEPTORS_STRTO(double, __isoc23_strtod, char)
469 INTERCEPTORS_STRTO(float, __isoc23_strtof, char)
470 INTERCEPTORS_STRTO(long double, __isoc23_strtold, char)
471 INTERCEPTORS_STRTO_BASE(long, __isoc23_strtol, char)
472 INTERCEPTORS_STRTO_BASE(long long, __isoc23_strtoll, char)
473 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_strtoul, char)
474 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_strtoull, char)
475 INTERCEPTORS_STRTO_BASE(u64, __isoc23_strtouq, char)
476 
477 INTERCEPTORS_STRTO(double, __isoc23_wcstod, wchar_t)
478 INTERCEPTORS_STRTO(float, __isoc23_wcstof, wchar_t)
479 INTERCEPTORS_STRTO(long double, __isoc23_wcstold, wchar_t)
480 INTERCEPTORS_STRTO_BASE(long, __isoc23_wcstol, wchar_t)
481 INTERCEPTORS_STRTO_BASE(long long, __isoc23_wcstoll, wchar_t)
482 INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_wcstoul, wchar_t)
483 INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_wcstoull, wchar_t)
484 #endif
485 
486 #if SANITIZER_NETBSD
487 #define INTERCEPT_STRTO(func) \
488   INTERCEPT_FUNCTION(func); \
489   INTERCEPT_FUNCTION(func##_l);
490 #else
491 #define INTERCEPT_STRTO(func) \
492   INTERCEPT_FUNCTION(func); \
493   INTERCEPT_FUNCTION(func##_l); \
494   INTERCEPT_FUNCTION(__##func##_l); \
495   INTERCEPT_FUNCTION(__##func##_internal);
496 #endif
497 
498 
499 // FIXME: support *wprintf in common format interceptors.
500 INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
501   ENSURE_MSAN_INITED();
502   int res = REAL(vswprintf)(str, size, format, ap);
503   if (res >= 0) {
504     __msan_unpoison(str, 4 * (res + 1));
505   }
506   return res;
507 }
508 
509 INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
510   ENSURE_MSAN_INITED();
511   va_list ap;
512   va_start(ap, format);
513   int res = vswprintf(str, size, format, ap);
514   va_end(ap);
515   return res;
516 }
517 
518 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
519   ENSURE_MSAN_INITED();                                              \
520   InterceptorScope interceptor_scope;                                \
521   ret_type res = REAL(func)(s, __VA_ARGS__);                         \
522   if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1));          \
523   return res;
524 
525 INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
526             __sanitizer_tm *tm) {
527   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
528 }
529 
530 INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
531             __sanitizer_tm *tm, void *loc) {
532   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
533 }
534 
535 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
536 INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
537             __sanitizer_tm *tm, void *loc) {
538   INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
539                             loc);
540 }
541 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
542 #else
543 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
544 #endif
545 
546 INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
547             __sanitizer_tm *tm) {
548   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
549 }
550 
551 INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
552             __sanitizer_tm *tm, void *loc) {
553   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
554                             loc);
555 }
556 
557 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
558 INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
559             __sanitizer_tm *tm, void *loc) {
560   INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
561                             loc);
562 }
563 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
564 #else
565 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
566 #endif
567 
568 INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
569   ENSURE_MSAN_INITED();
570   int res = REAL(mbtowc)(dest, src, n);
571   if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
572   return res;
573 }
574 
575 INTERCEPTOR(SIZE_T, mbrtowc, wchar_t *dest, const char *src, SIZE_T n,
576             void *ps) {
577   ENSURE_MSAN_INITED();
578   SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
579   if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
580   return res;
581 }
582 
583 // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
584 INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
585   ENSURE_MSAN_INITED();
586   GET_STORE_STACK_TRACE;
587   wchar_t *res = REAL(wmemcpy)(dest, src, n);
588   CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
589   return res;
590 }
591 
592 #if !SANITIZER_NETBSD
593 INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
594   ENSURE_MSAN_INITED();
595   GET_STORE_STACK_TRACE;
596   wchar_t *res = REAL(wmempcpy)(dest, src, n);
597   CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
598   return res;
599 }
600 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
601 #else
602 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
603 #endif
604 
605 INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
606   CHECK(MEM_IS_APP(s));
607   ENSURE_MSAN_INITED();
608   wchar_t *res = REAL(wmemset)(s, c, n);
609   __msan_unpoison(s, n * sizeof(wchar_t));
610   return res;
611 }
612 
613 INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
614   ENSURE_MSAN_INITED();
615   GET_STORE_STACK_TRACE;
616   wchar_t *res = REAL(wmemmove)(dest, src, n);
617   MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
618   return res;
619 }
620 
621 INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
622   ENSURE_MSAN_INITED();
623   int res = REAL(wcscmp)(s1, s2);
624   return res;
625 }
626 
627 INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
628   ENSURE_MSAN_INITED();
629   int res = REAL(gettimeofday)(tv, tz);
630   if (tv)
631     __msan_unpoison(tv, 16);
632   if (tz)
633     __msan_unpoison(tz, 8);
634   return res;
635 }
636 
637 #if !SANITIZER_NETBSD
638 INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
639   ENSURE_MSAN_INITED();
640   char *res = REAL(fcvt)(x, a, b, c);
641   __msan_unpoison(b, sizeof(*b));
642   __msan_unpoison(c, sizeof(*c));
643   if (res)
644     __msan_unpoison(res, internal_strlen(res) + 1);
645   return res;
646 }
647 #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
648 #else
649 #define MSAN_MAYBE_INTERCEPT_FCVT
650 #endif
651 
652 INTERCEPTOR(char *, getenv, char *name) {
653   if (msan_init_is_running)
654     return REAL(getenv)(name);
655   ENSURE_MSAN_INITED();
656   char *res = REAL(getenv)(name);
657   if (res)
658     __msan_unpoison(res, internal_strlen(res) + 1);
659   return res;
660 }
661 
662 extern char **environ;
663 
664 static void UnpoisonEnviron() {
665   char **envp = environ;
666   for (; *envp; ++envp) {
667     __msan_unpoison(envp, sizeof(*envp));
668     __msan_unpoison(*envp, internal_strlen(*envp) + 1);
669   }
670   // Trailing NULL pointer.
671   __msan_unpoison(envp, sizeof(*envp));
672 }
673 
674 INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
675   ENSURE_MSAN_INITED();
676   CHECK_UNPOISONED_STRING(name, 0);
677   int res = REAL(setenv)(name, value, overwrite);
678   if (!res) UnpoisonEnviron();
679   return res;
680 }
681 
682 INTERCEPTOR(int, putenv, char *string) {
683   ENSURE_MSAN_INITED();
684   int res = REAL(putenv)(string);
685   if (!res) UnpoisonEnviron();
686   return res;
687 }
688 
689 #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
690 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
691 INTERCEPTOR(int, fstat, int fd, void *buf) {
692   ENSURE_MSAN_INITED();
693   int res = REAL(fstat)(fd, buf);
694   if (!res)
695     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
696   return res;
697 }
698 #  define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
699 #else
700 #define MSAN_MAYBE_INTERCEPT_FSTAT
701 #endif
702 
703 #if SANITIZER_STAT_LINUX
704 INTERCEPTOR(int, fstat64, int fd, void *buf) {
705   ENSURE_MSAN_INITED();
706   int res = REAL(fstat64)(fd, buf);
707   if (!res)
708     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
709   return res;
710 }
711 #  define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
712 #else
713 #  define MSAN_MAYBE_INTERCEPT_FSTAT64
714 #endif
715 
716 #if SANITIZER_GLIBC
717 INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
718   ENSURE_MSAN_INITED();
719   int res = REAL(__fxstat)(magic, fd, buf);
720   if (!res)
721     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
722   return res;
723 }
724 #  define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
725 #else
726 #define MSAN_MAYBE_INTERCEPT___FXSTAT
727 #endif
728 
729 #if SANITIZER_GLIBC
730 INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
731   ENSURE_MSAN_INITED();
732   int res = REAL(__fxstat64)(magic, fd, buf);
733   if (!res)
734     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
735   return res;
736 }
737 #  define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
738 #else
739 #  define MSAN_MAYBE_INTERCEPT___FXSTAT64
740 #endif
741 
742 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
743 INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
744   ENSURE_MSAN_INITED();
745   int res = REAL(fstatat)(fd, pathname, buf, flags);
746   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
747   return res;
748 }
749 #  define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
750 #else
751 #  define MSAN_MAYBE_INTERCEPT_FSTATAT
752 #endif
753 
754 #if SANITIZER_STAT_LINUX
755 INTERCEPTOR(int, fstatat64, int fd, char *pathname, void *buf, int flags) {
756   ENSURE_MSAN_INITED();
757   int res = REAL(fstatat64)(fd, pathname, buf, flags);
758   if (!res)
759     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
760   return res;
761 }
762 #  define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
763 #else
764 #  define MSAN_MAYBE_INTERCEPT_FSTATAT64
765 #endif
766 
767 #if SANITIZER_GLIBC
768 INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
769             int flags) {
770   ENSURE_MSAN_INITED();
771   int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
772   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
773   return res;
774 }
775 #  define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
776 #else
777 #  define MSAN_MAYBE_INTERCEPT___FXSTATAT
778 #endif
779 
780 #if SANITIZER_GLIBC
781 INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
782             int flags) {
783   ENSURE_MSAN_INITED();
784   int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
785   if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
786   return res;
787 }
788 #  define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
789 #else
790 #  define MSAN_MAYBE_INTERCEPT___FXSTATAT64
791 #endif
792 
793 INTERCEPTOR(int, pipe, int pipefd[2]) {
794   if (msan_init_is_running)
795     return REAL(pipe)(pipefd);
796   ENSURE_MSAN_INITED();
797   int res = REAL(pipe)(pipefd);
798   if (!res)
799     __msan_unpoison(pipefd, sizeof(int[2]));
800   return res;
801 }
802 
803 INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
804   ENSURE_MSAN_INITED();
805   int res = REAL(pipe2)(pipefd, flags);
806   if (!res)
807     __msan_unpoison(pipefd, sizeof(int[2]));
808   return res;
809 }
810 
811 INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
812   ENSURE_MSAN_INITED();
813   int res = REAL(socketpair)(domain, type, protocol, sv);
814   if (!res)
815     __msan_unpoison(sv, sizeof(int[2]));
816   return res;
817 }
818 
819 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
820 INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
821   ENSURE_MSAN_INITED();
822   char *res = REAL(fgets_unlocked)(s, size, stream);
823   if (res)
824     __msan_unpoison(s, internal_strlen(s) + 1);
825   return res;
826 }
827 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
828 #else
829 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
830 #endif
831 
832 #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim)  \
833   if (msan_init_is_running)                               \
834     return REAL(getrlimit)(resource, rlim);               \
835   ENSURE_MSAN_INITED();                                   \
836   int res = REAL(func)(resource, rlim);                   \
837   if (!res)                                               \
838     __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
839   return res
840 
841 INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
842   INTERCEPTOR_GETRLIMIT_BODY(getrlimit, resource, rlim);
843 }
844 
845 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
846 INTERCEPTOR(int, __getrlimit, int resource, void *rlim) {
847   INTERCEPTOR_GETRLIMIT_BODY(__getrlimit, resource, rlim);
848 }
849 
850 INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
851   if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
852   ENSURE_MSAN_INITED();
853   int res = REAL(getrlimit64)(resource, rlim);
854   if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
855   return res;
856 }
857 
858 INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
859             void *old_rlimit) {
860   if (msan_init_is_running)
861     return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
862   ENSURE_MSAN_INITED();
863   CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
864   int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
865   if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
866   return res;
867 }
868 
869 INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
870             void *old_rlimit) {
871   if (msan_init_is_running)
872     return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
873   ENSURE_MSAN_INITED();
874   CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
875   int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
876   if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
877   return res;
878 }
879 
880 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
881 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
882 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
883 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
884 #else
885 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
886 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
887 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
888 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
889 #endif
890 
891 INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
892   ENSURE_MSAN_INITED();
893   int res = REAL(gethostname)(name, len);
894   if (!res || (res == -1 && errno == errno_ENAMETOOLONG)) {
895     SIZE_T real_len = internal_strnlen(name, len);
896     if (real_len < len)
897       ++real_len;
898     __msan_unpoison(name, real_len);
899   }
900   return res;
901 }
902 
903 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
904 INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
905     int timeout) {
906   ENSURE_MSAN_INITED();
907   int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
908   if (res > 0) {
909     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
910   }
911   return res;
912 }
913 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
914 #else
915 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
916 #endif
917 
918 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
919 INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
920     int timeout, void *sigmask) {
921   ENSURE_MSAN_INITED();
922   int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
923   if (res > 0) {
924     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
925   }
926   return res;
927 }
928 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
929 #else
930 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
931 #endif
932 
933 INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
934   GET_MALLOC_STACK_TRACE;
935   if (DlsymAlloc::Use())
936     return DlsymAlloc::Callocate(nmemb, size);
937   return msan_calloc(nmemb, size, &stack);
938 }
939 
940 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
941   if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
942     return DlsymAlloc::Realloc(ptr, size);
943   GET_MALLOC_STACK_TRACE;
944   return msan_realloc(ptr, size, &stack);
945 }
946 
947 INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
948   GET_MALLOC_STACK_TRACE;
949   return msan_reallocarray(ptr, nmemb, size, &stack);
950 }
951 
952 INTERCEPTOR(void *, malloc, SIZE_T size) {
953   if (DlsymAlloc::Use())
954     return DlsymAlloc::Allocate(size);
955   GET_MALLOC_STACK_TRACE;
956   return msan_malloc(size, &stack);
957 }
958 
959 void __msan_allocated_memory(const void *data, uptr size) {
960   if (flags()->poison_in_malloc) {
961     GET_MALLOC_STACK_TRACE;
962     stack.tag = STACK_TRACE_TAG_POISON;
963     PoisonMemory(data, size, &stack);
964   }
965 }
966 
967 void __msan_copy_shadow(void *dest, const void *src, uptr n) {
968   GET_STORE_STACK_TRACE;
969   MoveShadowAndOrigin(dest, src, n, &stack);
970 }
971 
972 void __sanitizer_dtor_callback(const void *data, uptr size) {
973   if (flags()->poison_in_dtor) {
974     GET_MALLOC_STACK_TRACE;
975     stack.tag = STACK_TRACE_TAG_POISON;
976     PoisonMemory(data, size, &stack);
977   }
978 }
979 
980 void __sanitizer_dtor_callback_fields(const void *data, uptr size) {
981   if (flags()->poison_in_dtor) {
982     GET_MALLOC_STACK_TRACE;
983     stack.tag = STACK_TRACE_TAG_FIELDS;
984     PoisonMemory(data, size, &stack);
985   }
986 }
987 
988 void __sanitizer_dtor_callback_vptr(const void *data) {
989   if (flags()->poison_in_dtor) {
990     GET_MALLOC_STACK_TRACE;
991     stack.tag = STACK_TRACE_TAG_VPTR;
992     PoisonMemory(data, sizeof(void *), &stack);
993   }
994 }
995 
996 template <class Mmap>
997 static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
998                               int prot, int flags, int fd, OFF64_T offset) {
999   SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
1000   void *end_addr = (char *)addr + (rounded_length - 1);
1001   if (addr && (!MEM_IS_APP(addr) || !MEM_IS_APP(end_addr))) {
1002     if (flags & map_fixed) {
1003       errno = errno_EINVAL;
1004       return (void *)-1;
1005     } else {
1006       addr = nullptr;
1007     }
1008   }
1009   void *res = real_mmap(addr, length, prot, flags, fd, offset);
1010   if (res != (void *)-1) {
1011     void *end_res = (char *)res + (rounded_length - 1);
1012     if (MEM_IS_APP(res) && MEM_IS_APP(end_res)) {
1013       __msan_unpoison(res, rounded_length);
1014     } else {
1015       // Application has attempted to map more memory than is supported by
1016       // MSAN. Act as if we ran out of memory.
1017       internal_munmap(res, length);
1018       errno = errno_ENOMEM;
1019       return (void *)-1;
1020     }
1021   }
1022   return res;
1023 }
1024 
1025 INTERCEPTOR(int, getrusage, int who, void *usage) {
1026   ENSURE_MSAN_INITED();
1027   int res = REAL(getrusage)(who, usage);
1028   if (res == 0) {
1029     __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
1030   }
1031   return res;
1032 }
1033 
1034 class SignalHandlerScope {
1035  public:
1036   SignalHandlerScope() {
1037     if (MsanThread *t = GetCurrentThread())
1038       t->EnterSignalHandler();
1039   }
1040   ~SignalHandlerScope() {
1041     if (MsanThread *t = GetCurrentThread())
1042       t->LeaveSignalHandler();
1043   }
1044 };
1045 
1046 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1047 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
1048 // the signal handler.
1049 const int kMaxSignals = 1024;
1050 static atomic_uintptr_t sigactions[kMaxSignals];
1051 static StaticSpinMutex sigactions_mu;
1052 
1053 static void SignalHandler(int signo) {
1054   SignalHandlerScope signal_handler_scope;
1055   ScopedThreadLocalStateBackup stlsb;
1056   UnpoisonParam(1);
1057 
1058   typedef void (*signal_cb)(int x);
1059   signal_cb cb =
1060       (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1061   cb(signo);
1062 }
1063 
1064 static void SignalAction(int signo, void *si, void *uc) {
1065   SignalHandlerScope signal_handler_scope;
1066   ScopedThreadLocalStateBackup stlsb;
1067   UnpoisonParam(3);
1068   __msan_unpoison(si, sizeof(__sanitizer_sigaction));
1069   __msan_unpoison(uc, ucontext_t_sz(uc));
1070 
1071   typedef void (*sigaction_cb)(int, void *, void *);
1072   sigaction_cb cb =
1073       (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1074   cb(signo, si, uc);
1075   CHECK_UNPOISONED(uc, ucontext_t_sz(uc));
1076 }
1077 
1078 static void read_sigaction(const __sanitizer_sigaction *act) {
1079   CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags));
1080   if (act->sa_flags & __sanitizer::sa_siginfo)
1081     CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction));
1082   else
1083     CHECK_UNPOISONED(&act->handler, sizeof(act->handler));
1084   CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask));
1085 }
1086 
1087 extern "C" int pthread_attr_init(void *attr);
1088 extern "C" int pthread_attr_destroy(void *attr);
1089 
1090 static void *MsanThreadStartFunc(void *arg) {
1091   MsanThread *t = (MsanThread *)arg;
1092   SetCurrentThread(t);
1093   t->Init();
1094   SetSigProcMask(&t->starting_sigset_, nullptr);
1095   return t->ThreadStart();
1096 }
1097 
1098 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
1099             void * param) {
1100   ENSURE_MSAN_INITED(); // for GetTlsSize()
1101   __sanitizer_pthread_attr_t myattr;
1102   if (!attr) {
1103     pthread_attr_init(&myattr);
1104     attr = &myattr;
1105   }
1106 
1107   AdjustStackSize(attr);
1108 
1109   MsanThread *t = MsanThread::Create(callback, param);
1110   ScopedBlockSignals block(&t->starting_sigset_);
1111   int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
1112 
1113   if (attr == &myattr)
1114     pthread_attr_destroy(&myattr);
1115   if (!res) {
1116     __msan_unpoison(th, __sanitizer::pthread_t_sz);
1117   }
1118   return res;
1119 }
1120 
1121 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
1122             void (*dtor)(void *value)) {
1123   if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
1124   ENSURE_MSAN_INITED();
1125   int res = REAL(pthread_key_create)(key, dtor);
1126   if (!res && key)
1127     __msan_unpoison(key, sizeof(*key));
1128   return res;
1129 }
1130 
1131 #if SANITIZER_NETBSD
1132 INTERCEPTOR(int, __libc_thr_keycreate, __sanitizer_pthread_key_t *m,
1133             void (*dtor)(void *value))
1134 ALIAS(WRAP(pthread_key_create));
1135 #endif
1136 
1137 INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
1138   ENSURE_MSAN_INITED();
1139   int res = REAL(pthread_join)(thread, retval);
1140   if (!res && retval)
1141     __msan_unpoison(retval, sizeof(*retval));
1142   return res;
1143 }
1144 
1145 #if SANITIZER_GLIBC
1146 INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **retval) {
1147   ENSURE_MSAN_INITED();
1148   int res = REAL(pthread_tryjoin_np)(thread, retval);
1149   if (!res && retval)
1150     __msan_unpoison(retval, sizeof(*retval));
1151   return res;
1152 }
1153 
1154 INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **retval,
1155             const struct timespec *abstime) {
1156   int res = REAL(pthread_timedjoin_np)(thread, retval, abstime);
1157   if (!res && retval)
1158     __msan_unpoison(retval, sizeof(*retval));
1159   return res;
1160 }
1161 #endif
1162 
1163 DEFINE_REAL_PTHREAD_FUNCTIONS
1164 
1165 extern char *tzname[2];
1166 
1167 INTERCEPTOR(void, tzset, int fake) {
1168   ENSURE_MSAN_INITED();
1169   InterceptorScope interceptor_scope;
1170   REAL(tzset)(fake);
1171   if (tzname[0])
1172     __msan_unpoison(tzname[0], internal_strlen(tzname[0]) + 1);
1173   if (tzname[1])
1174     __msan_unpoison(tzname[1], internal_strlen(tzname[1]) + 1);
1175   return;
1176 }
1177 
1178 struct MSanAtExitRecord {
1179   void (*func)(void *arg);
1180   void *arg;
1181 };
1182 
1183 struct InterceptorContext {
1184   Mutex atexit_mu;
1185   Vector<struct MSanAtExitRecord *> AtExitStack;
1186 
1187   InterceptorContext()
1188       : AtExitStack() {
1189   }
1190 };
1191 
1192 static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
1193 InterceptorContext *interceptor_ctx() {
1194   return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
1195 }
1196 
1197 void MSanAtExitWrapper() {
1198   MSanAtExitRecord *r;
1199   {
1200     Lock l(&interceptor_ctx()->atexit_mu);
1201 
1202     uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
1203     r = interceptor_ctx()->AtExitStack[element];
1204     interceptor_ctx()->AtExitStack.PopBack();
1205   }
1206 
1207   UnpoisonParam(1);
1208   ((void(*)())r->func)();
1209   InternalFree(r);
1210 }
1211 
1212 void MSanCxaAtExitWrapper(void *arg) {
1213   UnpoisonParam(1);
1214   MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
1215   // libc before 2.27 had race which caused occasional double handler execution
1216   // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
1217   if (!r->func)
1218     return;
1219   r->func(r->arg);
1220   r->func = nullptr;
1221 }
1222 
1223 static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso);
1224 
1225 // Unpoison argument shadow for C++ module destructors.
1226 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
1227             void *dso_handle) {
1228   if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
1229   return setup_at_exit_wrapper((void(*)())func, arg, dso_handle);
1230 }
1231 
1232 // Unpoison argument shadow for C++ module destructors.
1233 INTERCEPTOR(int, atexit, void (*func)()) {
1234   // Avoid calling real atexit as it is unreachable on at least on Linux.
1235   if (msan_init_is_running)
1236     return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0);
1237   return setup_at_exit_wrapper((void(*)())func, 0, 0);
1238 }
1239 
1240 static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) {
1241   ENSURE_MSAN_INITED();
1242   MSanAtExitRecord *r =
1243       (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
1244   r->func = (void(*)(void *a))f;
1245   r->arg = arg;
1246   int res;
1247   if (!dso) {
1248     // NetBSD does not preserve the 2nd argument if dso is equal to 0
1249     // Store ctx in a local stack-like structure
1250 
1251     Lock l(&interceptor_ctx()->atexit_mu);
1252 
1253     res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0);
1254     if (!res) {
1255       interceptor_ctx()->AtExitStack.PushBack(r);
1256     }
1257   } else {
1258     res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso);
1259   }
1260   return res;
1261 }
1262 
1263 static void BeforeFork() {
1264   StackDepotLockAll();
1265   ChainedOriginDepotLockAll();
1266 }
1267 
1268 static void AfterFork() {
1269   ChainedOriginDepotUnlockAll();
1270   StackDepotUnlockAll();
1271 }
1272 
1273 INTERCEPTOR(int, fork, void) {
1274   ENSURE_MSAN_INITED();
1275   BeforeFork();
1276   int pid = REAL(fork)();
1277   AfterFork();
1278   return pid;
1279 }
1280 
1281 // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
1282 // with MSan.
1283 #if SANITIZER_LINUX
1284 INTERCEPTOR(int, openpty, int *aparent, int *aworker, char *name,
1285             const void *termp, const void *winp) {
1286   ENSURE_MSAN_INITED();
1287   InterceptorScope interceptor_scope;
1288   int res = REAL(openpty)(aparent, aworker, name, termp, winp);
1289   if (!res) {
1290     __msan_unpoison(aparent, sizeof(*aparent));
1291     __msan_unpoison(aworker, sizeof(*aworker));
1292   }
1293   return res;
1294 }
1295 #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
1296 #else
1297 #define MSAN_MAYBE_INTERCEPT_OPENPTY
1298 #endif
1299 
1300 // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
1301 // with MSan.
1302 #if SANITIZER_LINUX
1303 INTERCEPTOR(int, forkpty, int *aparent, char *name, const void *termp,
1304             const void *winp) {
1305   ENSURE_MSAN_INITED();
1306   InterceptorScope interceptor_scope;
1307   int res = REAL(forkpty)(aparent, name, termp, winp);
1308   if (res != -1)
1309     __msan_unpoison(aparent, sizeof(*aparent));
1310   return res;
1311 }
1312 #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
1313 #else
1314 #define MSAN_MAYBE_INTERCEPT_FORKPTY
1315 #endif
1316 
1317 struct MSanInterceptorContext {
1318   bool in_interceptor_scope;
1319 };
1320 
1321 namespace __msan {
1322 
1323 int OnExit() {
1324   // FIXME: ask frontend whether we need to return failure.
1325   return 0;
1326 }
1327 
1328 } // namespace __msan
1329 
1330 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1331 // interceptors.
1332 #define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
1333   do {                                                          \
1334     if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1335       CHECK_UNPOISONED_0(x, n);                                 \
1336   } while (0)
1337 
1338 #define MSAN_INTERCEPT_FUNC(name)                                       \
1339   do {                                                                  \
1340     if (!INTERCEPT_FUNCTION(name))                                      \
1341       VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
1342   } while (0)
1343 
1344 #define MSAN_INTERCEPT_FUNC_VER(name, ver)                                 \
1345   do {                                                                     \
1346     if (!INTERCEPT_FUNCTION_VER(name, ver))                                \
1347       VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1348               ver);                                                        \
1349   } while (0)
1350 #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)             \
1351   do {                                                                      \
1352     if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name))    \
1353       VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1354               #name, ver, #name);                                           \
1355   } while (0)
1356 
1357 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1358 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1359   MSAN_INTERCEPT_FUNC_VER(name, ver)
1360 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1361   MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
1362 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count)  \
1363   UnpoisonParam(count)
1364 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1365   __msan_unpoison(ptr, size)
1366 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1367   CHECK_UNPOISONED_CTX(ctx, ptr, size)
1368 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1369   __msan_unpoison(ptr, size)
1370 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
1371   if (msan_init_is_running)                                   \
1372     return REAL(func)(__VA_ARGS__);                           \
1373   ENSURE_MSAN_INITED();                                       \
1374   MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1375   ctx = (void *)&msan_ctx;                                    \
1376   (void)ctx;                                                  \
1377   InterceptorScope interceptor_scope;                         \
1378   __msan_unpoison(__errno_location(), sizeof(int));
1379 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1380   do {                                            \
1381   } while (false)
1382 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1383   do {                                         \
1384   } while (false)
1385 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1386   do {                                         \
1387   } while (false)
1388 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1389   do {                                                      \
1390   } while (false)
1391 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1392   do {                                                \
1393   } while (false)  // FIXME
1394 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1395   do {                                                         \
1396   } while (false)  // FIXME
1397 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1398 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1399 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)                    \
1400   do {                                                                         \
1401     link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle));                   \
1402     if (filename && map)                                                       \
1403       ForEachMappedRegion(map, __msan_unpoison);                               \
1404   } while (false)
1405 
1406 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
1407 
1408 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
1409   if (MsanThread *t = GetCurrentThread()) {                                    \
1410     *begin = t->tls_begin();                                                   \
1411     *end = t->tls_end();                                                       \
1412   } else {                                                                     \
1413     *begin = *end = 0;                                                         \
1414   }
1415 
1416 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
1417   {                                                         \
1418     (void)ctx;                                              \
1419     return __msan_memset(block, c, size);                   \
1420   }
1421 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
1422   {                                                          \
1423     (void)ctx;                                               \
1424     return __msan_memmove(to, from, size);                   \
1425   }
1426 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
1427   {                                                         \
1428     (void)ctx;                                              \
1429     return __msan_memcpy(to, from, size);                   \
1430   }
1431 
1432 #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
1433   do {                                                      \
1434     GET_STORE_STACK_TRACE;                                  \
1435     CopyShadowAndOrigin(to, from, size, &stack);            \
1436     __msan_unpoison(to + size, 1);                          \
1437   } while (false)
1438 
1439 #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
1440                                      offset)                                   \
1441   do {                                                                         \
1442     return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off);       \
1443   } while (false)
1444 
1445 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1446 #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc"
1447 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1448 
1449 static uptr signal_impl(int signo, uptr cb);
1450 static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
1451                           __sanitizer_sigaction *oldact);
1452 
1453 #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
1454   { return sigaction_impl(signo, act, oldact); }
1455 
1456 #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
1457   {                                                          \
1458     handler = signal_impl(signo, handler);                   \
1459     InterceptorScope interceptor_scope;                      \
1460     return REAL(func)(signo, handler);                       \
1461   }
1462 
1463 #define SIGNAL_INTERCEPTOR_ENTER() ENSURE_MSAN_INITED()
1464 
1465 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
1466 
1467 static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
1468                           __sanitizer_sigaction *oldact) {
1469   ENSURE_MSAN_INITED();
1470   if (signo <= 0 || signo >= kMaxSignals) {
1471     errno = errno_EINVAL;
1472     return -1;
1473   }
1474   if (act) read_sigaction(act);
1475   int res;
1476   if (flags()->wrap_signals) {
1477     SpinMutexLock lock(&sigactions_mu);
1478     uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
1479     __sanitizer_sigaction new_act;
1480     __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
1481     if (act) {
1482       REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
1483       uptr cb = (uptr)pnew_act->sigaction;
1484       uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
1485                         ? (uptr)SignalAction
1486                         : (uptr)SignalHandler;
1487       if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1488         atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1489         pnew_act->sigaction = (decltype(pnew_act->sigaction))new_cb;
1490       }
1491     }
1492     res = REAL(SIGACTION_SYMNAME)(signo, pnew_act, oldact);
1493     if (res == 0 && oldact) {
1494       uptr cb = (uptr)oldact->sigaction;
1495       if (cb == (uptr)SignalAction || cb == (uptr)SignalHandler) {
1496         oldact->sigaction = (decltype(oldact->sigaction))old_cb;
1497       }
1498     }
1499   } else {
1500     res = REAL(SIGACTION_SYMNAME)(signo, act, oldact);
1501   }
1502 
1503   if (res == 0 && oldact) {
1504     __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
1505   }
1506   return res;
1507 }
1508 
1509 static uptr signal_impl(int signo, uptr cb) {
1510   ENSURE_MSAN_INITED();
1511   if (signo <= 0 || signo >= kMaxSignals) {
1512     errno = errno_EINVAL;
1513     return -1;
1514   }
1515   if (flags()->wrap_signals) {
1516     SpinMutexLock lock(&sigactions_mu);
1517     if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1518       atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1519       cb = (uptr)&SignalHandler;
1520     }
1521   }
1522   return cb;
1523 }
1524 
1525 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1526 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1527   do {                                       \
1528   } while (false)
1529 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1530   do {                                       \
1531   } while (false)
1532 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1533 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1534 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
1535 
1536 INTERCEPTOR(const char *, strsignal, int sig) {
1537   void *ctx;
1538   COMMON_INTERCEPTOR_ENTER(ctx, strsignal, sig);
1539   const char *res = REAL(strsignal)(sig);
1540   if (res)
1541     __msan_unpoison(res, internal_strlen(res) + 1);
1542   return res;
1543 }
1544 
1545 INTERCEPTOR(int, dladdr, void *addr, void *info) {
1546   void *ctx;
1547   COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
1548   int res = REAL(dladdr)(addr, info);
1549   if (res != 0)
1550     UnpoisonDllAddrInfo(info);
1551   return res;
1552 }
1553 
1554 #if SANITIZER_GLIBC
1555 INTERCEPTOR(int, dladdr1, void *addr, void *info, void **extra_info,
1556             int flags) {
1557   void *ctx;
1558   COMMON_INTERCEPTOR_ENTER(ctx, dladdr1, addr, info, extra_info, flags);
1559   int res = REAL(dladdr1)(addr, info, extra_info, flags);
1560   if (res != 0) {
1561     UnpoisonDllAddrInfo(info);
1562     UnpoisonDllAddr1ExtraInfo(extra_info, flags);
1563   }
1564   return res;
1565 }
1566 #  define MSAN_MAYBE_INTERCEPT_DLADDR1 MSAN_INTERCEPT_FUNC(dladdr1)
1567 #else
1568 #define MSAN_MAYBE_INTERCEPT_DLADDR1
1569 #endif
1570 
1571 INTERCEPTOR(char *, dlerror, int fake) {
1572   void *ctx;
1573   COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
1574   char *res = REAL(dlerror)(fake);
1575   if (res)
1576     __msan_unpoison(res, internal_strlen(res) + 1);
1577   return res;
1578 }
1579 
1580 typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
1581                                   void *data);
1582 struct dl_iterate_phdr_data {
1583   dl_iterate_phdr_cb callback;
1584   void *data;
1585 };
1586 
1587 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
1588                                    void *data) {
1589   if (info) {
1590     __msan_unpoison(info, size);
1591     if (info->dlpi_phdr && info->dlpi_phnum)
1592       __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
1593     if (info->dlpi_name)
1594       __msan_unpoison(info->dlpi_name, internal_strlen(info->dlpi_name) + 1);
1595   }
1596   dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
1597   UnpoisonParam(3);
1598   return cbdata->callback(info, size, cbdata->data);
1599 }
1600 
1601 INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
1602   ENSURE_MSAN_INITED();
1603   void *p = REAL(shmat)(shmid, shmaddr, shmflg);
1604   if (p != (void *)-1) {
1605     __sanitizer_shmid_ds ds;
1606     int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
1607     if (!res) {
1608       __msan_unpoison(p, ds.shm_segsz);
1609     }
1610   }
1611   return p;
1612 }
1613 
1614 INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
1615   void *ctx;
1616   COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
1617   dl_iterate_phdr_data cbdata;
1618   cbdata.callback = callback;
1619   cbdata.data = data;
1620   int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
1621   return res;
1622 }
1623 
1624 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
1625 INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
1626   ENSURE_MSAN_INITED();
1627   wchar_t *res = REAL(wcschr)(s, wc, ps);
1628   return res;
1629 }
1630 
1631 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
1632 INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
1633   ENSURE_MSAN_INITED();
1634   GET_STORE_STACK_TRACE;
1635   wchar_t *res = REAL(wcscpy)(dest, src);
1636   CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (internal_wcslen(src) + 1),
1637                       &stack);
1638   return res;
1639 }
1640 
1641 INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
1642   ENSURE_MSAN_INITED();
1643   GET_STORE_STACK_TRACE;
1644   SIZE_T copy_size = internal_wcsnlen(src, n);
1645   if (copy_size < n) copy_size++;           // trailing \0
1646   wchar_t *res = REAL(wcsncpy)(dest, src, n);
1647   CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
1648   __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
1649   return res;
1650 }
1651 
1652 // These interface functions reside here so that they can use
1653 // REAL(memset), etc.
1654 void __msan_unpoison(const void *a, uptr size) {
1655   if (!MEM_IS_APP(a)) return;
1656   SetShadow(a, size, 0);
1657 }
1658 
1659 void __msan_poison(const void *a, uptr size) {
1660   if (!MEM_IS_APP(a)) return;
1661   SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
1662 }
1663 
1664 void __msan_poison_stack(void *a, uptr size) {
1665   if (!MEM_IS_APP(a)) return;
1666   SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
1667 }
1668 
1669 void __msan_unpoison_param(uptr n) { UnpoisonParam(n); }
1670 
1671 void __msan_clear_and_unpoison(void *a, uptr size) {
1672   REAL(memset)(a, 0, size);
1673   SetShadow(a, size, 0);
1674 }
1675 
1676 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1677   if (!msan_inited) return internal_memcpy(dest, src, n);
1678   if (msan_init_is_running || __msan::IsInSymbolizerOrUnwider())
1679     return REAL(memcpy)(dest, src, n);
1680   ENSURE_MSAN_INITED();
1681   GET_STORE_STACK_TRACE;
1682   void *res = REAL(memcpy)(dest, src, n);
1683   CopyShadowAndOrigin(dest, src, n, &stack);
1684   return res;
1685 }
1686 
1687 void *__msan_memset(void *s, int c, SIZE_T n) {
1688   if (!msan_inited) return internal_memset(s, c, n);
1689   if (msan_init_is_running) return REAL(memset)(s, c, n);
1690   ENSURE_MSAN_INITED();
1691   void *res = REAL(memset)(s, c, n);
1692   __msan_unpoison(s, n);
1693   return res;
1694 }
1695 
1696 void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1697   if (!msan_inited) return internal_memmove(dest, src, n);
1698   if (msan_init_is_running) return REAL(memmove)(dest, src, n);
1699   ENSURE_MSAN_INITED();
1700   GET_STORE_STACK_TRACE;
1701   void *res = REAL(memmove)(dest, src, n);
1702   MoveShadowAndOrigin(dest, src, n, &stack);
1703   return res;
1704 }
1705 
1706 void __msan_unpoison_string(const char* s) {
1707   if (!MEM_IS_APP(s)) return;
1708   __msan_unpoison(s, internal_strlen(s) + 1);
1709 }
1710 
1711 namespace __msan {
1712 
1713 void InitializeInterceptors() {
1714   static int inited = 0;
1715   CHECK_EQ(inited, 0);
1716 
1717   new(interceptor_ctx()) InterceptorContext();
1718 
1719   InitializeCommonInterceptors();
1720   InitializeSignalInterceptors();
1721 
1722   INTERCEPT_FUNCTION(posix_memalign);
1723   MSAN_MAYBE_INTERCEPT_MEMALIGN;
1724   MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
1725   INTERCEPT_FUNCTION(valloc);
1726   MSAN_MAYBE_INTERCEPT_PVALLOC;
1727   INTERCEPT_FUNCTION(malloc);
1728   INTERCEPT_FUNCTION(calloc);
1729   INTERCEPT_FUNCTION(realloc);
1730   INTERCEPT_FUNCTION(reallocarray);
1731   INTERCEPT_FUNCTION(free);
1732   MSAN_MAYBE_INTERCEPT_CFREE;
1733   MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
1734   MSAN_MAYBE_INTERCEPT_MALLINFO;
1735   MSAN_MAYBE_INTERCEPT_MALLOPT;
1736   MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
1737   INTERCEPT_FUNCTION(fread);
1738   MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
1739   INTERCEPT_FUNCTION(memccpy);
1740   MSAN_MAYBE_INTERCEPT_MEMPCPY;
1741   INTERCEPT_FUNCTION(bcopy);
1742   INTERCEPT_FUNCTION(wmemset);
1743   INTERCEPT_FUNCTION(wmemcpy);
1744   MSAN_MAYBE_INTERCEPT_WMEMPCPY;
1745   INTERCEPT_FUNCTION(wmemmove);
1746   INTERCEPT_FUNCTION(strcpy);
1747   MSAN_MAYBE_INTERCEPT_STPCPY;
1748   MSAN_MAYBE_INTERCEPT_STPNCPY;
1749   INTERCEPT_FUNCTION(strdup);
1750   MSAN_MAYBE_INTERCEPT___STRDUP;
1751   INTERCEPT_FUNCTION(strncpy);
1752   MSAN_MAYBE_INTERCEPT_GCVT;
1753   INTERCEPT_FUNCTION(strcat);
1754   INTERCEPT_FUNCTION(strncat);
1755   INTERCEPT_STRTO(strtod);
1756   INTERCEPT_STRTO(strtof);
1757   INTERCEPT_STRTO(strtold);
1758   INTERCEPT_STRTO(strtol);
1759   INTERCEPT_STRTO(strtoul);
1760   INTERCEPT_STRTO(strtoll);
1761   INTERCEPT_STRTO(strtoull);
1762   INTERCEPT_STRTO(strtouq);
1763   INTERCEPT_STRTO(wcstod);
1764   INTERCEPT_STRTO(wcstof);
1765   INTERCEPT_STRTO(wcstold);
1766   INTERCEPT_STRTO(wcstol);
1767   INTERCEPT_STRTO(wcstoul);
1768   INTERCEPT_STRTO(wcstoll);
1769   INTERCEPT_STRTO(wcstoull);
1770 #if SANITIZER_GLIBC
1771   INTERCEPT_STRTO(__isoc23_strtod);
1772   INTERCEPT_STRTO(__isoc23_strtof);
1773   INTERCEPT_STRTO(__isoc23_strtold);
1774   INTERCEPT_STRTO(__isoc23_strtol);
1775   INTERCEPT_STRTO(__isoc23_strtoul);
1776   INTERCEPT_STRTO(__isoc23_strtoll);
1777   INTERCEPT_STRTO(__isoc23_strtoull);
1778   INTERCEPT_STRTO(__isoc23_strtouq);
1779   INTERCEPT_STRTO(__isoc23_wcstod);
1780   INTERCEPT_STRTO(__isoc23_wcstof);
1781   INTERCEPT_STRTO(__isoc23_wcstold);
1782   INTERCEPT_STRTO(__isoc23_wcstol);
1783   INTERCEPT_STRTO(__isoc23_wcstoul);
1784   INTERCEPT_STRTO(__isoc23_wcstoll);
1785   INTERCEPT_STRTO(__isoc23_wcstoull);
1786 #endif
1787 
1788 #ifdef SANITIZER_NLDBL_VERSION
1789   INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
1790   INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
1791 #else
1792   INTERCEPT_FUNCTION(vswprintf);
1793   INTERCEPT_FUNCTION(swprintf);
1794 #endif
1795   INTERCEPT_FUNCTION(strftime);
1796   INTERCEPT_FUNCTION(strftime_l);
1797   MSAN_MAYBE_INTERCEPT___STRFTIME_L;
1798   INTERCEPT_FUNCTION(wcsftime);
1799   INTERCEPT_FUNCTION(wcsftime_l);
1800   MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
1801   INTERCEPT_FUNCTION(mbtowc);
1802   INTERCEPT_FUNCTION(mbrtowc);
1803   INTERCEPT_FUNCTION(wcslen);
1804   INTERCEPT_FUNCTION(wcsnlen);
1805   INTERCEPT_FUNCTION(wcschr);
1806   INTERCEPT_FUNCTION(wcscpy);
1807   INTERCEPT_FUNCTION(wcsncpy);
1808   INTERCEPT_FUNCTION(wcscmp);
1809   INTERCEPT_FUNCTION(getenv);
1810   INTERCEPT_FUNCTION(setenv);
1811   INTERCEPT_FUNCTION(putenv);
1812   INTERCEPT_FUNCTION(gettimeofday);
1813   MSAN_MAYBE_INTERCEPT_FCVT;
1814   MSAN_MAYBE_INTERCEPT_FSTAT;
1815   MSAN_MAYBE_INTERCEPT_FSTAT64;
1816   MSAN_MAYBE_INTERCEPT___FXSTAT;
1817   MSAN_MAYBE_INTERCEPT_FSTATAT;
1818   MSAN_MAYBE_INTERCEPT_FSTATAT64;
1819   MSAN_MAYBE_INTERCEPT___FXSTATAT;
1820   MSAN_MAYBE_INTERCEPT___FXSTAT64;
1821   MSAN_MAYBE_INTERCEPT___FXSTATAT64;
1822   INTERCEPT_FUNCTION(pipe);
1823   INTERCEPT_FUNCTION(pipe2);
1824   INTERCEPT_FUNCTION(socketpair);
1825   MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
1826   INTERCEPT_FUNCTION(getrlimit);
1827   MSAN_MAYBE_INTERCEPT___GETRLIMIT;
1828   MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
1829   MSAN_MAYBE_INTERCEPT_PRLIMIT;
1830   MSAN_MAYBE_INTERCEPT_PRLIMIT64;
1831   INTERCEPT_FUNCTION(gethostname);
1832   MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1833   MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1834   INTERCEPT_FUNCTION(strsignal);
1835   INTERCEPT_FUNCTION(dladdr);
1836   MSAN_MAYBE_INTERCEPT_DLADDR1;
1837   INTERCEPT_FUNCTION(dlerror);
1838   INTERCEPT_FUNCTION(dl_iterate_phdr);
1839   INTERCEPT_FUNCTION(getrusage);
1840 #if defined(__mips__)
1841   INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
1842 #else
1843   INTERCEPT_FUNCTION(pthread_create);
1844 #endif
1845   INTERCEPT_FUNCTION(pthread_join);
1846   INTERCEPT_FUNCTION(pthread_key_create);
1847 #if SANITIZER_GLIBC
1848   INTERCEPT_FUNCTION(pthread_tryjoin_np);
1849   INTERCEPT_FUNCTION(pthread_timedjoin_np);
1850 #endif
1851 
1852 #if SANITIZER_NETBSD
1853   INTERCEPT_FUNCTION(__libc_thr_keycreate);
1854 #endif
1855 
1856   INTERCEPT_FUNCTION(pthread_join);
1857   INTERCEPT_FUNCTION(tzset);
1858   INTERCEPT_FUNCTION(atexit);
1859   INTERCEPT_FUNCTION(__cxa_atexit);
1860   INTERCEPT_FUNCTION(shmat);
1861   INTERCEPT_FUNCTION(fork);
1862   MSAN_MAYBE_INTERCEPT_OPENPTY;
1863   MSAN_MAYBE_INTERCEPT_FORKPTY;
1864 
1865   inited = 1;
1866 }
1867 } // namespace __msan
1868