msan_interceptors.cc revision 801448950d645813efb398575bbc62b48e5b1dfc
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 "sanitizer_common/sanitizer_platform_limits_posix.h"
21#include "sanitizer_common/sanitizer_allocator.h"
22#include "sanitizer_common/sanitizer_common.h"
23#include "sanitizer_common/sanitizer_stackdepot.h"
24#include "sanitizer_common/sanitizer_libc.h"
25#include "sanitizer_common/sanitizer_linux.h"
26
27#include <stdarg.h>
28// ACHTUNG! No other system header includes in this file.
29// Ideally, we should get rid of stdarg.h as well.
30
31using namespace __msan;
32
33// True if this is a nested interceptor.
34static THREADLOCAL int in_interceptor_scope;
35
36struct InterceptorScope {
37  InterceptorScope() { ++in_interceptor_scope; }
38  ~InterceptorScope() { --in_interceptor_scope; }
39};
40
41bool IsInInterceptorScope() {
42  return in_interceptor_scope;
43}
44
45#define ENSURE_MSAN_INITED() do { \
46  CHECK(!msan_init_is_running); \
47  if (!msan_inited) { \
48    __msan_init(); \
49  } \
50} while (0)
51
52// Check that [x, x+n) range is unpoisoned.
53#define CHECK_UNPOISONED_0(x, n)                                             \
54  do {                                                                       \
55    sptr offset = __msan_test_shadow(x, n);                                  \
56    if (__msan::IsInSymbolizer()) break;                                     \
57    if (offset >= 0 && __msan::flags()->report_umrs) {                       \
58      GET_CALLER_PC_BP_SP;                                                   \
59      (void) sp;                                                             \
60      Printf("UMR in %s at offset %d inside [%p, +%d) \n", __FUNCTION__,     \
61             offset, x, n);                                                  \
62      __msan::PrintWarningWithOrigin(pc, bp,                                 \
63                                     __msan_get_origin((char *)x + offset)); \
64      if (!__msan::flags()->keep_going) {                                    \
65        Printf("Exiting\n");                                                 \
66        Die();                                                               \
67      }                                                                      \
68    }                                                                        \
69  } while (0)
70
71// Check that [x, x+n) range is unpoisoned unless we are in a nested
72// interceptor.
73#define CHECK_UNPOISONED(x, n)                             \
74  do {                                                     \
75    if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
76  } while (0);
77
78static void *fast_memset(void *ptr, int c, SIZE_T n);
79static void *fast_memcpy(void *dst, const void *src, SIZE_T n);
80
81INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
82  ENSURE_MSAN_INITED();
83  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
84  if (res > 0)
85    __msan_unpoison(ptr, res *size);
86  return res;
87}
88
89INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
90            void *file) {
91  ENSURE_MSAN_INITED();
92  SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
93  if (res > 0)
94    __msan_unpoison(ptr, res *size);
95  return res;
96}
97
98INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
99  ENSURE_MSAN_INITED();
100  SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
101  if (res > 0)
102    __msan_unpoison(buf, res);
103  return res;
104}
105
106INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) {
107  return __msan_memcpy(dest, src, n);
108}
109
110INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
111  return __msan_memmove(dest, src, n);
112}
113
114INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
115  return __msan_memset(s, c, n);
116}
117
118INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
119  GET_MALLOC_STACK_TRACE;
120  CHECK_EQ(alignment & (alignment - 1), 0);
121  CHECK_NE(memptr, 0);
122  *memptr = MsanReallocate(&stack, 0, size, alignment, false);
123  CHECK_NE(*memptr, 0);
124  __msan_unpoison(memptr, sizeof(*memptr));
125  return 0;
126}
127
128INTERCEPTOR(void, free, void *ptr) {
129  ENSURE_MSAN_INITED();
130  if (ptr == 0) return;
131  MsanDeallocate(ptr);
132}
133
134INTERCEPTOR(SIZE_T, strlen, const char *s) {
135  ENSURE_MSAN_INITED();
136  SIZE_T res = REAL(strlen)(s);
137  CHECK_UNPOISONED(s, res + 1);
138  return res;
139}
140
141INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) {
142  ENSURE_MSAN_INITED();
143  SIZE_T res = REAL(strnlen)(s, n);
144  SIZE_T scan_size = (res == n) ? res : res + 1;
145  CHECK_UNPOISONED(s, scan_size);
146  return res;
147}
148
149// FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should
150// check the shadow of the terminating \0 byte).
151
152INTERCEPTOR(char *, strcpy, char *dest, const char *src) {  // NOLINT
153  ENSURE_MSAN_INITED();
154  SIZE_T n = REAL(strlen)(src);
155  char *res = REAL(strcpy)(dest, src);  // NOLINT
156  __msan_copy_poison(dest, src, n + 1);
157  return res;
158}
159
160INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {  // NOLINT
161  ENSURE_MSAN_INITED();
162  SIZE_T copy_size = REAL(strnlen)(src, n);
163  if (copy_size < n)
164    copy_size++;  // trailing \0
165  char *res = REAL(strncpy)(dest, src, n);  // NOLINT
166  __msan_copy_poison(dest, src, copy_size);
167  return res;
168}
169
170INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {  // NOLINT
171  ENSURE_MSAN_INITED();
172  SIZE_T n = REAL(strlen)(src);
173  char *res = REAL(stpcpy)(dest, src);  // NOLINT
174  __msan_copy_poison(dest, src, n + 1);
175  return res;
176}
177
178INTERCEPTOR(char *, strdup, char *src) {
179  ENSURE_MSAN_INITED();
180  SIZE_T n = REAL(strlen)(src);
181  char *res = REAL(strdup)(src);
182  __msan_copy_poison(res, src, n + 1);
183  return res;
184}
185
186INTERCEPTOR(char *, __strdup, char *src) {
187  ENSURE_MSAN_INITED();
188  SIZE_T n = REAL(strlen)(src);
189  char *res = REAL(__strdup)(src);
190  __msan_copy_poison(res, src, n + 1);
191  return res;
192}
193
194INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
195  ENSURE_MSAN_INITED();
196  SIZE_T copy_size = REAL(strnlen)(src, n);
197  char *res = REAL(strndup)(src, n);
198  __msan_copy_poison(res, src, copy_size);
199  __msan_unpoison(res + copy_size, 1); // \0
200  return res;
201}
202
203INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
204  ENSURE_MSAN_INITED();
205  SIZE_T copy_size = REAL(strnlen)(src, n);
206  char *res = REAL(__strndup)(src, n);
207  __msan_copy_poison(res, src, copy_size);
208  __msan_unpoison(res + copy_size, 1); // \0
209  return res;
210}
211
212INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
213  ENSURE_MSAN_INITED();
214  char *res = REAL(gcvt)(number, ndigit, buf);
215  // DynamoRio tool will take care of unpoisoning gcvt result for us.
216  if (!__msan_has_dynamic_component()) {
217    SIZE_T n = REAL(strlen)(buf);
218    __msan_unpoison(buf, n + 1);
219  }
220  return res;
221}
222
223INTERCEPTOR(char *, strcat, char *dest, const char *src) {  // NOLINT
224  ENSURE_MSAN_INITED();
225  SIZE_T src_size = REAL(strlen)(src);
226  SIZE_T dest_size = REAL(strlen)(dest);
227  char *res = REAL(strcat)(dest, src);  // NOLINT
228  __msan_copy_poison(dest + dest_size, src, src_size + 1);
229  return res;
230}
231
232INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {  // NOLINT
233  ENSURE_MSAN_INITED();
234  SIZE_T dest_size = REAL(strlen)(dest);
235  SIZE_T copy_size = REAL(strlen)(src);
236  if (copy_size < n)
237    copy_size++;  // trailing \0
238  char *res = REAL(strncat)(dest, src, n);  // NOLINT
239  __msan_copy_poison(dest + dest_size, src, copy_size);
240  return res;
241}
242
243INTERCEPTOR(long, strtol, const char *nptr, char **endptr,  // NOLINT
244            int base) {
245  ENSURE_MSAN_INITED();
246  long res = REAL(strtol)(nptr, endptr, base);  // NOLINT
247  if (!__msan_has_dynamic_component()) {
248    __msan_unpoison(endptr, sizeof(*endptr));
249  }
250  return res;
251}
252
253INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr,  // NOLINT
254            int base) {
255  ENSURE_MSAN_INITED();
256  long res = REAL(strtoll)(nptr, endptr, base);  //NOLINT
257  if (!__msan_has_dynamic_component()) {
258    __msan_unpoison(endptr, sizeof(*endptr));
259  }
260  return res;
261}
262
263INTERCEPTOR(unsigned long, strtoul, const char *nptr, char **endptr,  // NOLINT
264            int base) {
265  ENSURE_MSAN_INITED();
266  unsigned long res = REAL(strtoul)(nptr, endptr, base);  // NOLINT
267  if (!__msan_has_dynamic_component()) {
268    __msan_unpoison(endptr, sizeof(*endptr));
269  }
270  return res;
271}
272
273INTERCEPTOR(unsigned long long, strtoull, const char *nptr,  // NOLINT
274            char **endptr, int base) {
275  ENSURE_MSAN_INITED();
276  unsigned long res = REAL(strtoull)(nptr, endptr, base);  // NOLINT
277  if (!__msan_has_dynamic_component()) {
278    __msan_unpoison(endptr, sizeof(*endptr));
279  }
280  return res;
281}
282
283INTERCEPTOR(double, strtod, const char *nptr, char **endptr) {  // NOLINT
284  ENSURE_MSAN_INITED();
285  double res = REAL(strtod)(nptr, endptr);  // NOLINT
286  if (!__msan_has_dynamic_component()) {
287    __msan_unpoison(endptr, sizeof(*endptr));
288  }
289  return res;
290}
291
292INTERCEPTOR(float, strtof, const char *nptr, char **endptr) {  // NOLINT
293  ENSURE_MSAN_INITED();
294  float res = REAL(strtof)(nptr, endptr);  // NOLINT
295  if (!__msan_has_dynamic_component()) {
296    __msan_unpoison(endptr, sizeof(*endptr));
297  }
298  return res;
299}
300
301INTERCEPTOR(long double, strtold, const char *nptr, char **endptr) {  // NOLINT
302  ENSURE_MSAN_INITED();
303  long double res = REAL(strtold)(nptr, endptr);  // NOLINT
304  if (!__msan_has_dynamic_component()) {
305    __msan_unpoison(endptr, sizeof(*endptr));
306  }
307  return res;
308}
309
310INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap) {
311  ENSURE_MSAN_INITED();
312  int res = REAL(vasprintf)(strp, format, ap);
313  if (res >= 0 && !__msan_has_dynamic_component()) {
314    __msan_unpoison(strp, sizeof(*strp));
315    __msan_unpoison(*strp, res + 1);
316  }
317  return res;
318}
319
320INTERCEPTOR(int, asprintf, char **strp, const char *format, ...) {  // NOLINT
321  ENSURE_MSAN_INITED();
322  va_list ap;
323  va_start(ap, format);
324  int res = vasprintf(strp, format, ap);  // NOLINT
325  va_end(ap);
326  return res;
327}
328
329INTERCEPTOR(int, vsnprintf, char *str, uptr size,
330            const char *format, va_list ap) {
331  ENSURE_MSAN_INITED();
332  int res = REAL(vsnprintf)(str, size, format, ap);
333  if (res >= 0 && !__msan_has_dynamic_component()) {
334    __msan_unpoison(str, res + 1);
335  }
336  return res;
337}
338
339INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) {
340  ENSURE_MSAN_INITED();
341  int res = REAL(vsprintf)(str, format, ap);
342  if (res >= 0 && !__msan_has_dynamic_component()) {
343    __msan_unpoison(str, res + 1);
344  }
345  return res;
346}
347
348INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
349  ENSURE_MSAN_INITED();
350  int res = REAL(vswprintf)(str, size, format, ap);
351  if (res >= 0 && !__msan_has_dynamic_component()) {
352    __msan_unpoison(str, 4 * (res + 1));
353  }
354  return res;
355}
356
357INTERCEPTOR(int, sprintf, char *str, const char *format, ...) {  // NOLINT
358  ENSURE_MSAN_INITED();
359  va_list ap;
360  va_start(ap, format);
361  int res = vsprintf(str, format, ap);  // NOLINT
362  va_end(ap);
363  return res;
364}
365
366INTERCEPTOR(int, snprintf, char *str, uptr size, const char *format, ...) {
367  ENSURE_MSAN_INITED();
368  va_list ap;
369  va_start(ap, format);
370  int res = vsnprintf(str, size, format, ap);
371  va_end(ap);
372  return res;
373}
374
375INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
376  ENSURE_MSAN_INITED();
377  va_list ap;
378  va_start(ap, format);
379  int res = vswprintf(str, size, format, ap);
380  va_end(ap);
381  return res;
382}
383
384// SIZE_T strftime(char *s, SIZE_T max, const char *format,const struct tm *tm);
385INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
386            void *tm) {
387  ENSURE_MSAN_INITED();
388  SIZE_T res = REAL(strftime)(s, max, format, tm);
389  if (res) __msan_unpoison(s, res + 1);
390  return res;
391}
392
393INTERCEPTOR(SIZE_T, wcstombs, void *dest, void *src, SIZE_T size) {
394  ENSURE_MSAN_INITED();
395  SIZE_T res = REAL(wcstombs)(dest, src, size);
396  if (res != (SIZE_T)-1) __msan_unpoison(dest, res + 1);
397  return res;
398}
399
400// SIZE_T mbstowcs(wchar_t *dest, const char *src, SIZE_T n);
401INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T n) {
402  ENSURE_MSAN_INITED();
403  SIZE_T res = REAL(mbstowcs)(dest, src, n);
404  if (res != (SIZE_T)-1) __msan_unpoison(dest, (res + 1) * sizeof(wchar_t));
405  return res;
406}
407
408INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
409  ENSURE_MSAN_INITED();
410  int res = REAL(mbtowc)(dest, src, n);
411  if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
412  return res;
413}
414
415INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) {
416  ENSURE_MSAN_INITED();
417  SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
418  if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
419  return res;
420}
421
422INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
423  ENSURE_MSAN_INITED();
424  SIZE_T res = REAL(wcslen)(s);
425  CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
426  return res;
427}
428
429// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
430INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
431  ENSURE_MSAN_INITED();
432  wchar_t *res = REAL(wcschr)(s, wc, ps);
433  return res;
434}
435
436// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
437INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
438  ENSURE_MSAN_INITED();
439  wchar_t *res = REAL(wcscpy)(dest, src);
440  __msan_copy_poison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1));
441  return res;
442}
443
444// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
445INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
446  ENSURE_MSAN_INITED();
447  wchar_t *res = REAL(wmemcpy)(dest, src, n);
448  __msan_copy_poison(dest, src, n * sizeof(wchar_t));
449  return res;
450}
451
452INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
453  CHECK(MEM_IS_APP(s));
454  ENSURE_MSAN_INITED();
455  wchar_t *res = (wchar_t *)fast_memset(s, c, n * sizeof(wchar_t));
456  __msan_unpoison(s, n * sizeof(wchar_t));
457  return res;
458}
459
460INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
461  ENSURE_MSAN_INITED();
462  wchar_t *res = REAL(wmemmove)(dest, src, n);
463  __msan_move_poison(dest, src, n * sizeof(wchar_t));
464  return res;
465}
466
467INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
468  ENSURE_MSAN_INITED();
469  int res = REAL(wcscmp)(s1, s2);
470  return res;
471}
472
473INTERCEPTOR(double, wcstod, const wchar_t *nptr, wchar_t **endptr) {
474  ENSURE_MSAN_INITED();
475  double res = REAL(wcstod)(nptr, endptr);
476  __msan_unpoison(endptr, sizeof(*endptr));
477  return res;
478}
479
480// #define UNSUPPORTED(name) \
481//   INTERCEPTOR(void, name, void) {                     \
482//     Printf("MSAN: Unsupported %s\n", __FUNCTION__);   \
483//     Die();                                            \
484//   }
485
486// FIXME: intercept the following functions:
487// Note, they only matter when running without a dynamic tool.
488// UNSUPPORTED(wcscoll_l)
489// UNSUPPORTED(wcsnrtombs)
490// UNSUPPORTED(wcstol)
491// UNSUPPORTED(wcstoll)
492// UNSUPPORTED(wcstold)
493// UNSUPPORTED(wcstoul)
494// UNSUPPORTED(wcstoull)
495// UNSUPPORTED(wcsxfrm_l)
496// UNSUPPORTED(wcsdup)
497// UNSUPPORTED(wcsftime)
498// UNSUPPORTED(wcsstr)
499// UNSUPPORTED(wcsrchr)
500// UNSUPPORTED(wctob)
501
502INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
503  ENSURE_MSAN_INITED();
504  int res = REAL(gettimeofday)(tv, tz);
505  if (tv)
506    __msan_unpoison(tv, 16);
507  if (tz)
508    __msan_unpoison(tz, 8);
509  return res;
510}
511
512INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
513  ENSURE_MSAN_INITED();
514  char *res = REAL(fcvt)(x, a, b, c);
515  if (!__msan_has_dynamic_component()) {
516    __msan_unpoison(b, sizeof(*b));
517    __msan_unpoison(c, sizeof(*c));
518  }
519  return res;
520}
521
522INTERCEPTOR(char *, getenv, char *name) {
523  ENSURE_MSAN_INITED();
524  char *res = REAL(getenv)(name);
525  if (!__msan_has_dynamic_component()) {
526    if (res)
527      __msan_unpoison(res, REAL(strlen)(res) + 1);
528  }
529  return res;
530}
531
532INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
533  ENSURE_MSAN_INITED();
534  int res = REAL(__fxstat)(magic, fd, buf);
535  if (!res)
536    __msan_unpoison(buf, __sanitizer::struct_stat_sz);
537  return res;
538}
539
540INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
541  ENSURE_MSAN_INITED();
542  int res = REAL(__fxstat64)(magic, fd, buf);
543  if (!res)
544    __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
545  return res;
546}
547
548INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) {
549  ENSURE_MSAN_INITED();
550  int res = REAL(__xstat)(magic, path, buf);
551  if (!res)
552    __msan_unpoison(buf, __sanitizer::struct_stat_sz);
553  return res;
554}
555
556INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) {
557  ENSURE_MSAN_INITED();
558  int res = REAL(__xstat64)(magic, path, buf);
559  if (!res)
560    __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
561  return res;
562}
563
564INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) {
565  ENSURE_MSAN_INITED();
566  int res = REAL(__lxstat)(magic, path, buf);
567  if (!res)
568    __msan_unpoison(buf, __sanitizer::struct_stat_sz);
569  return res;
570}
571
572INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) {
573  ENSURE_MSAN_INITED();
574  int res = REAL(__lxstat64)(magic, path, buf);
575  if (!res)
576    __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
577  return res;
578}
579
580INTERCEPTOR(int, pipe, int pipefd[2]) {
581  if (msan_init_is_running)
582    return REAL(pipe)(pipefd);
583  ENSURE_MSAN_INITED();
584  int res = REAL(pipe)(pipefd);
585  if (!res)
586    __msan_unpoison(pipefd, sizeof(int[2]));
587  return res;
588}
589
590INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
591  ENSURE_MSAN_INITED();
592  int res = REAL(pipe2)(pipefd, flags);
593  if (!res)
594    __msan_unpoison(pipefd, sizeof(int[2]));
595  return res;
596}
597
598INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
599  ENSURE_MSAN_INITED();
600  int res = REAL(socketpair)(domain, type, protocol, sv);
601  if (!res)
602    __msan_unpoison(sv, sizeof(int[2]));
603  return res;
604}
605
606INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
607  ENSURE_MSAN_INITED();
608  char *res = REAL(fgets)(s, size, stream);
609  if (res)
610    __msan_unpoison(s, REAL(strlen)(s) + 1);
611  return res;
612}
613
614INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
615  ENSURE_MSAN_INITED();
616  char *res = REAL(fgets_unlocked)(s, size, stream);
617  if (res)
618    __msan_unpoison(s, REAL(strlen)(s) + 1);
619  return res;
620}
621
622INTERCEPTOR(char *, realpath, char *path, char *abspath) {
623  ENSURE_MSAN_INITED();
624  char *res = REAL(realpath)(path, abspath);
625  if (res)
626    __msan_unpoison(abspath, REAL(strlen)(abspath) + 1);
627  return res;
628}
629
630INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
631  if (msan_init_is_running)
632    return REAL(getrlimit)(resource, rlim);
633  ENSURE_MSAN_INITED();
634  int res = REAL(getrlimit)(resource, rlim);
635  if (!res)
636    __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
637  return res;
638}
639
640INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
641  if (msan_init_is_running)
642    return REAL(getrlimit64)(resource, rlim);
643  ENSURE_MSAN_INITED();
644  int res = REAL(getrlimit64)(resource, rlim);
645  if (!res)
646    __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
647  return res;
648}
649
650INTERCEPTOR(int, statfs, const char *s, void *buf) {
651  ENSURE_MSAN_INITED();
652  int res = REAL(statfs)(s, buf);
653  if (!res)
654    __msan_unpoison(buf, __sanitizer::struct_statfs_sz);
655  return res;
656}
657
658INTERCEPTOR(int, fstatfs, int fd, void *buf) {
659  ENSURE_MSAN_INITED();
660  int res = REAL(fstatfs)(fd, buf);
661  if (!res)
662    __msan_unpoison(buf, __sanitizer::struct_statfs_sz);
663  return res;
664}
665
666INTERCEPTOR(int, statfs64, const char *s, void *buf) {
667  ENSURE_MSAN_INITED();
668  int res = REAL(statfs64)(s, buf);
669  if (!res)
670    __msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
671  return res;
672}
673
674INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
675  ENSURE_MSAN_INITED();
676  int res = REAL(fstatfs64)(fd, buf);
677  if (!res)
678    __msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
679  return res;
680}
681
682INTERCEPTOR(int, uname, void *utsname) {
683  ENSURE_MSAN_INITED();
684  int res = REAL(uname)(utsname);
685  if (!res) {
686    __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
687  }
688  return res;
689}
690
691INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
692  ENSURE_MSAN_INITED();
693  int res = REAL(gethostname)(name, len);
694  if (!res) {
695    SIZE_T real_len = REAL(strnlen)(name, len);
696    if (real_len < len)
697      ++real_len;
698    __msan_unpoison(name, real_len);
699  }
700  return res;
701}
702
703INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
704    int timeout) {
705  ENSURE_MSAN_INITED();
706  int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
707  if (res > 0) {
708    __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
709  }
710  return res;
711}
712
713INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
714    int timeout, void *sigmask) {
715  ENSURE_MSAN_INITED();
716  int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
717  if (res > 0) {
718    __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
719  }
720  return res;
721}
722
723INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
724  ENSURE_MSAN_INITED();
725  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
726  if (res > 0)
727    __msan_unpoison(buf, res);
728  return res;
729}
730
731INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
732            void *srcaddr, int *addrlen) {
733  ENSURE_MSAN_INITED();
734  SIZE_T srcaddr_sz;
735  if (srcaddr) srcaddr_sz = *addrlen;
736  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
737  if (res > 0) {
738    __msan_unpoison(buf, res);
739    if (srcaddr) {
740      SIZE_T sz = *addrlen;
741      __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
742    }
743  }
744  return res;
745}
746
747INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
748  if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
749  GET_MALLOC_STACK_TRACE;
750  if (!msan_inited) {
751    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
752    const SIZE_T kCallocPoolSize = 1024;
753    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
754    static SIZE_T allocated;
755    SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
756    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
757    allocated += size_in_words;
758    CHECK(allocated < kCallocPoolSize);
759    return mem;
760  }
761  return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true);
762}
763
764INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
765  GET_MALLOC_STACK_TRACE;
766  return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
767}
768
769INTERCEPTOR(void *, malloc, SIZE_T size) {
770  GET_MALLOC_STACK_TRACE;
771  return MsanReallocate(&stack, 0, size, sizeof(u64), false);
772}
773
774void __msan_allocated_memory(const void* data, uptr size) {
775  GET_MALLOC_STACK_TRACE;
776  if (flags()->poison_in_malloc)
777    __msan_poison(data, size);
778  if (__msan_get_track_origins()) {
779    u32 stack_id = StackDepotPut(stack.trace, stack.size);
780    CHECK(stack_id);
781    CHECK_EQ((stack_id >> 31), 0);  // Higher bit is occupied by stack origins.
782    __msan_set_origin(data, size, stack_id);
783  }
784}
785
786INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
787            int fd, OFF_T offset) {
788  ENSURE_MSAN_INITED();
789  void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
790  if (res != (void*)-1)
791    __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
792  return res;
793}
794
795INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
796            int fd, OFF64_T offset) {
797  ENSURE_MSAN_INITED();
798  void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
799  if (res != (void*)-1)
800    __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
801  return res;
802}
803
804struct dlinfo {
805  char *dli_fname;
806  void *dli_fbase;
807  char *dli_sname;
808  void *dli_saddr;
809};
810
811INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
812  ENSURE_MSAN_INITED();
813  int res = REAL(dladdr)(addr, info);
814  if (res != 0) {
815    __msan_unpoison(info, sizeof(*info));
816    if (info->dli_fname)
817      __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
818    if (info->dli_sname)
819      __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
820  }
821  return res;
822}
823
824// dlopen() ultimately calls mmap() down inside the loader, which generally
825// doesn't participate in dynamic symbol resolution.  Therefore we won't
826// intercept its calls to mmap, and we have to hook it here.  The loader
827// initializes the module before returning, so without the dynamic component, we
828// won't be able to clear the shadow before the initializers.  Fixing this would
829// require putting our own initializer first to clear the shadow.
830INTERCEPTOR(void *, dlopen, const char *filename, int flag) {
831  ENSURE_MSAN_INITED();
832  EnterLoader();
833  link_map *map = (link_map *)REAL(dlopen)(filename, flag);
834  ExitLoader();
835  if (!__msan_has_dynamic_component() && map) {
836    // If msandr didn't clear the shadow before the initializers ran, we do it
837    // ourselves afterwards.
838    UnpoisonMappedDSO(map);
839  }
840  return (void *)map;
841}
842
843typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
844                                  void *data);
845struct dl_iterate_phdr_data {
846  dl_iterate_phdr_cb callback;
847  void *data;
848};
849
850static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
851                                   void *data) {
852  if (info) {
853    __msan_unpoison(info, size);
854    if (info->dlpi_name)
855      __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1);
856  }
857  dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
858  UnpoisonParam(3);
859  return cbdata->callback(info, size, cbdata->data);
860}
861
862INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
863  ENSURE_MSAN_INITED();
864  EnterLoader();
865  dl_iterate_phdr_data cbdata;
866  cbdata.callback = callback;
867  cbdata.data = data;
868  int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
869  ExitLoader();
870  return res;
871}
872
873INTERCEPTOR(int, getrusage, int who, void *usage) {
874  ENSURE_MSAN_INITED();
875  int res = REAL(getrusage)(who, usage);
876  if (res == 0) {
877    __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
878  }
879  return res;
880}
881
882const int kMaxSignals = 1024;
883static uptr sigactions[kMaxSignals];
884static StaticSpinMutex sigactions_mu;
885
886static void SignalHandler(int signo) {
887  typedef void (*signal_cb)(int x);
888  signal_cb cb = (signal_cb)sigactions[signo];
889  cb(signo);
890}
891
892static void SignalAction(int signo, void *si, void *uc) {
893  UnpoisonParam(3);
894  __msan_unpoison(si, __sanitizer::struct_sigaction_sz);
895  __msan_unpoison(uc, __sanitizer::ucontext_t_sz);
896
897  typedef void (*sigaction_cb)(int, void *, void *);
898  sigaction_cb cb = (sigaction_cb)sigactions[signo];
899  cb(signo, si, uc);
900}
901
902INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
903            __sanitizer_sigaction *oldact) {
904  ENSURE_MSAN_INITED();
905  // FIXME: check that *act is unpoisoned.
906  // That requires intercepting all of sigemptyset, sigfillset, etc.
907  int res;
908  if (flags()->wrap_signals) {
909    SpinMutexLock lock(&sigactions_mu);
910    CHECK_LT(signo, kMaxSignals);
911    uptr old_cb = sigactions[signo];
912    __sanitizer_sigaction new_act;
913    __sanitizer_sigaction *pnew_act = act ? &new_act : 0;
914    if (act) {
915      internal_memcpy(pnew_act, act, __sanitizer::struct_sigaction_sz);
916      uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(pnew_act);
917      uptr new_cb =
918          __sanitizer::__sanitizer_get_sigaction_sa_siginfo(pnew_act) ?
919          (uptr)SignalAction : (uptr)SignalHandler;
920      if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
921        sigactions[signo] = cb;
922        __sanitizer::__sanitizer_set_sigaction_sa_sigaction(pnew_act, new_cb);
923      }
924    }
925    res = REAL(sigaction)(signo, pnew_act, oldact);
926    if (res == 0 && oldact) {
927      uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(oldact);
928      if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
929        __sanitizer::__sanitizer_set_sigaction_sa_sigaction(oldact, old_cb);
930      }
931    }
932  } else {
933    res = REAL(sigaction)(signo, act, oldact);
934  }
935
936  if (res == 0 && oldact) {
937    __msan_unpoison(oldact, __sanitizer::struct_sigaction_sz);
938  }
939  return res;
940}
941
942INTERCEPTOR(int, signal, int signo, uptr cb) {
943  ENSURE_MSAN_INITED();
944  if (flags()->wrap_signals) {
945    CHECK_LT(signo, kMaxSignals);
946    SpinMutexLock lock(&sigactions_mu);
947    if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
948      sigactions[signo] = cb;
949      cb = (uptr) SignalHandler;
950    }
951    return REAL(signal)(signo, cb);
952  } else {
953    return REAL(signal)(signo, cb);
954  }
955}
956
957extern "C" int pthread_attr_init(void *attr);
958extern "C" int pthread_attr_destroy(void *attr);
959extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
960extern "C" int pthread_attr_getstack(void *attr, uptr *stack, uptr *stacksize);
961
962INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
963            void * param) {
964  ENSURE_MSAN_INITED(); // for GetTlsSize()
965  __sanitizer_pthread_attr_t myattr;
966  if (attr == 0) {
967    pthread_attr_init(&myattr);
968    attr = &myattr;
969  }
970
971  AdjustStackSizeLinux(attr, flags()->verbosity);
972
973  int res = REAL(pthread_create)(th, attr, callback, param);
974  if (attr == &myattr)
975    pthread_attr_destroy(&myattr);
976  if (!res) {
977    __msan_unpoison(th, __sanitizer::pthread_t_sz);
978  }
979  return res;
980}
981
982struct MSanInterceptorContext {
983  bool in_interceptor_scope;
984};
985
986// A version of CHECK_UNPOISED using a saved scope value. Used in common
987// interceptors.
988#define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
989  do {                                                          \
990    if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
991      CHECK_UNPOISONED_0(x, n);                                 \
992  } while (0)
993
994#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
995  __msan_unpoison(ptr, size)
996#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
997  CHECK_UNPOISONED_CTX(ctx, ptr, size)
998#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
999  if (msan_init_is_running) return REAL(func)(__VA_ARGS__);   \
1000  MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1001  ctx = (void *)&msan_ctx;                                    \
1002  InterceptorScope interceptor_scope;                         \
1003  ENSURE_MSAN_INITED();
1004#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1005  do {                                         \
1006  } while (false)
1007#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1008  do {                                         \
1009  } while (false)
1010#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1011  do {                                                      \
1012  } while (false)
1013#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1014  do {                                                \
1015  } while (false)  // FIXME
1016#include "sanitizer_common/sanitizer_common_interceptors.inc"
1017
1018#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1019#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
1020#define COMMON_SYSCALL_POST_READ_RANGE(p, s)
1021#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1022#include "sanitizer_common/sanitizer_common_syscalls.inc"
1023
1024// static
1025void *fast_memset(void *ptr, int c, SIZE_T n) {
1026  // hack until we have a really fast internal_memset
1027  if (sizeof(uptr) == 8 &&
1028      (n % 8) == 0 &&
1029      ((uptr)ptr % 8) == 0 &&
1030      (c == 0 || c == -1)) {
1031    // Printf("memset %p %zd %x\n", ptr, n, c);
1032    uptr to_store = c ? -1L : 0L;
1033    uptr *p = (uptr*)ptr;
1034    for (SIZE_T i = 0; i < n / 8; i++)
1035      p[i] = to_store;
1036    return ptr;
1037  }
1038  return internal_memset(ptr, c, n);
1039}
1040
1041// static
1042void *fast_memcpy(void *dst, const void *src, SIZE_T n) {
1043  // Same hack as in fast_memset above.
1044  if (sizeof(uptr) == 8 &&
1045      (n % 8) == 0 &&
1046      ((uptr)dst % 8) == 0 &&
1047      ((uptr)src % 8) == 0) {
1048    uptr *d = (uptr*)dst;
1049    uptr *s = (uptr*)src;
1050    for (SIZE_T i = 0; i < n / 8; i++)
1051      d[i] = s[i];
1052    return dst;
1053  }
1054  return internal_memcpy(dst, src, n);
1055}
1056
1057// These interface functions reside here so that they can use
1058// fast_memset, etc.
1059void __msan_unpoison(const void *a, uptr size) {
1060  if (!MEM_IS_APP(a)) return;
1061  fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
1062}
1063
1064void __msan_poison(const void *a, uptr size) {
1065  if (!MEM_IS_APP(a)) return;
1066  fast_memset((void*)MEM_TO_SHADOW((uptr)a),
1067              __msan::flags()->poison_heap_with_zeroes ? 0 : -1, size);
1068}
1069
1070void __msan_poison_stack(void *a, uptr size) {
1071  if (!MEM_IS_APP(a)) return;
1072  fast_memset((void*)MEM_TO_SHADOW((uptr)a),
1073              __msan::flags()->poison_stack_with_zeroes ? 0 : -1, size);
1074}
1075
1076void __msan_clear_and_unpoison(void *a, uptr size) {
1077  fast_memset(a, 0, size);
1078  fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
1079}
1080
1081void __msan_copy_origin(void *dst, const void *src, uptr size) {
1082  if (!__msan_get_track_origins()) return;
1083  if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
1084  uptr d = MEM_TO_ORIGIN(dst);
1085  uptr s = MEM_TO_ORIGIN(src);
1086  uptr beg = d & ~3UL;  // align down.
1087  uptr end = (d + size + 3) & ~3UL;  // align up.
1088  s = s & ~3UL;  // align down.
1089  fast_memcpy((void*)beg, (void*)s, end - beg);
1090}
1091
1092void __msan_copy_poison(void *dst, const void *src, uptr size) {
1093  if (!MEM_IS_APP(dst)) return;
1094  if (!MEM_IS_APP(src)) return;
1095  fast_memcpy((void*)MEM_TO_SHADOW((uptr)dst),
1096              (void*)MEM_TO_SHADOW((uptr)src), size);
1097  __msan_copy_origin(dst, src, size);
1098}
1099
1100void __msan_move_poison(void *dst, const void *src, uptr size) {
1101  if (!MEM_IS_APP(dst)) return;
1102  if (!MEM_IS_APP(src)) return;
1103  internal_memmove((void*)MEM_TO_SHADOW((uptr)dst),
1104         (void*)MEM_TO_SHADOW((uptr)src), size);
1105  __msan_copy_origin(dst, src, size);
1106}
1107
1108void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1109  ENSURE_MSAN_INITED();
1110  void *res = fast_memcpy(dest, src, n);
1111  __msan_copy_poison(dest, src, n);
1112  return res;
1113}
1114
1115void *__msan_memset(void *s, int c, SIZE_T n) {
1116  ENSURE_MSAN_INITED();
1117  void *res = fast_memset(s, c, n);
1118  __msan_unpoison(s, n);
1119  return res;
1120}
1121
1122void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1123  ENSURE_MSAN_INITED();
1124  void *res = REAL(memmove)(dest, src, n);
1125  __msan_move_poison(dest, src, n);
1126  return res;
1127}
1128
1129namespace __msan {
1130void InitializeInterceptors() {
1131  static int inited = 0;
1132  CHECK_EQ(inited, 0);
1133  SANITIZER_COMMON_INTERCEPTORS_INIT;
1134
1135  INTERCEPT_FUNCTION(mmap);
1136  INTERCEPT_FUNCTION(mmap64);
1137  INTERCEPT_FUNCTION(posix_memalign);
1138  INTERCEPT_FUNCTION(malloc);
1139  INTERCEPT_FUNCTION(calloc);
1140  INTERCEPT_FUNCTION(realloc);
1141  INTERCEPT_FUNCTION(free);
1142  INTERCEPT_FUNCTION(fread);
1143  INTERCEPT_FUNCTION(fread_unlocked);
1144  INTERCEPT_FUNCTION(readlink);
1145  INTERCEPT_FUNCTION(memcpy);
1146  INTERCEPT_FUNCTION(memset);
1147  INTERCEPT_FUNCTION(memmove);
1148  INTERCEPT_FUNCTION(wmemset);
1149  INTERCEPT_FUNCTION(wmemcpy);
1150  INTERCEPT_FUNCTION(wmemmove);
1151  INTERCEPT_FUNCTION(strcpy);  // NOLINT
1152  INTERCEPT_FUNCTION(stpcpy);  // NOLINT
1153  INTERCEPT_FUNCTION(strdup);
1154  INTERCEPT_FUNCTION(__strdup);
1155  INTERCEPT_FUNCTION(strndup);
1156  INTERCEPT_FUNCTION(__strndup);
1157  INTERCEPT_FUNCTION(strncpy);  // NOLINT
1158  INTERCEPT_FUNCTION(strlen);
1159  INTERCEPT_FUNCTION(strnlen);
1160  INTERCEPT_FUNCTION(gcvt);
1161  INTERCEPT_FUNCTION(strcat);  // NOLINT
1162  INTERCEPT_FUNCTION(strncat);  // NOLINT
1163  INTERCEPT_FUNCTION(strtol);
1164  INTERCEPT_FUNCTION(strtoll);
1165  INTERCEPT_FUNCTION(strtoul);
1166  INTERCEPT_FUNCTION(strtoull);
1167  INTERCEPT_FUNCTION(strtod);
1168  INTERCEPT_FUNCTION(strtof);
1169  INTERCEPT_FUNCTION(strtold);
1170  INTERCEPT_FUNCTION(vasprintf);
1171  INTERCEPT_FUNCTION(asprintf);
1172  INTERCEPT_FUNCTION(vsprintf);
1173  INTERCEPT_FUNCTION(vsnprintf);
1174  INTERCEPT_FUNCTION(vswprintf);
1175  INTERCEPT_FUNCTION(sprintf);  // NOLINT
1176  INTERCEPT_FUNCTION(snprintf);
1177  INTERCEPT_FUNCTION(swprintf);
1178  INTERCEPT_FUNCTION(strftime);
1179  INTERCEPT_FUNCTION(wcstombs);
1180  INTERCEPT_FUNCTION(mbstowcs);
1181  INTERCEPT_FUNCTION(mbtowc);
1182  INTERCEPT_FUNCTION(mbrtowc);
1183  INTERCEPT_FUNCTION(wcslen);
1184  INTERCEPT_FUNCTION(wcschr);
1185  INTERCEPT_FUNCTION(wcscpy);
1186  INTERCEPT_FUNCTION(wcscmp);
1187  INTERCEPT_FUNCTION(wcstod);
1188  INTERCEPT_FUNCTION(getenv);
1189  INTERCEPT_FUNCTION(gettimeofday);
1190  INTERCEPT_FUNCTION(fcvt);
1191  INTERCEPT_FUNCTION(__fxstat);
1192  INTERCEPT_FUNCTION(__xstat);
1193  INTERCEPT_FUNCTION(__lxstat);
1194  INTERCEPT_FUNCTION(__fxstat64);
1195  INTERCEPT_FUNCTION(__xstat64);
1196  INTERCEPT_FUNCTION(__lxstat64);
1197  INTERCEPT_FUNCTION(pipe);
1198  INTERCEPT_FUNCTION(pipe2);
1199  INTERCEPT_FUNCTION(socketpair);
1200  INTERCEPT_FUNCTION(fgets);
1201  INTERCEPT_FUNCTION(fgets_unlocked);
1202  INTERCEPT_FUNCTION(realpath);
1203  INTERCEPT_FUNCTION(getrlimit);
1204  INTERCEPT_FUNCTION(getrlimit64);
1205  INTERCEPT_FUNCTION(statfs);
1206  INTERCEPT_FUNCTION(fstatfs);
1207  INTERCEPT_FUNCTION(statfs64);
1208  INTERCEPT_FUNCTION(fstatfs64);
1209  INTERCEPT_FUNCTION(uname);
1210  INTERCEPT_FUNCTION(gethostname);
1211  INTERCEPT_FUNCTION(epoll_wait);
1212  INTERCEPT_FUNCTION(epoll_pwait);
1213  INTERCEPT_FUNCTION(recv);
1214  INTERCEPT_FUNCTION(recvfrom);
1215  INTERCEPT_FUNCTION(dladdr);
1216  INTERCEPT_FUNCTION(dlopen);
1217  INTERCEPT_FUNCTION(dl_iterate_phdr);
1218  INTERCEPT_FUNCTION(getrusage);
1219  INTERCEPT_FUNCTION(sigaction);
1220  INTERCEPT_FUNCTION(signal);
1221  INTERCEPT_FUNCTION(pthread_create);
1222  inited = 1;
1223}
1224}  // namespace __msan
1225