msan_interceptors.cc revision 6567092b06b37195cd93d57204bcbfe6843b2a48
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 *, mempcpy, void *dest, const void *src, SIZE_T n) {
111  return (char *)__msan_memcpy(dest, src, n) + n;
112}
113
114INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
115  return __msan_memmove(dest, src, n);
116}
117
118INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
119  return __msan_memset(s, c, n);
120}
121
122INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
123  return __msan_memmove(dest, src, n);
124}
125
126INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
127  GET_MALLOC_STACK_TRACE;
128  CHECK_EQ(alignment & (alignment - 1), 0);
129  CHECK_NE(memptr, 0);
130  *memptr = MsanReallocate(&stack, 0, size, alignment, false);
131  CHECK_NE(*memptr, 0);
132  __msan_unpoison(memptr, sizeof(*memptr));
133  return 0;
134}
135
136INTERCEPTOR(void, free, void *ptr) {
137  ENSURE_MSAN_INITED();
138  if (ptr == 0) return;
139  MsanDeallocate(ptr);
140}
141
142INTERCEPTOR(SIZE_T, strlen, const char *s) {
143  ENSURE_MSAN_INITED();
144  SIZE_T res = REAL(strlen)(s);
145  CHECK_UNPOISONED(s, res + 1);
146  return res;
147}
148
149INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) {
150  ENSURE_MSAN_INITED();
151  SIZE_T res = REAL(strnlen)(s, n);
152  SIZE_T scan_size = (res == n) ? res : res + 1;
153  CHECK_UNPOISONED(s, scan_size);
154  return res;
155}
156
157// FIXME: Add stricter shadow checks in str* interceptors (ex.: strcpy should
158// check the shadow of the terminating \0 byte).
159
160INTERCEPTOR(char *, strcpy, char *dest, const char *src) {  // NOLINT
161  ENSURE_MSAN_INITED();
162  SIZE_T n = REAL(strlen)(src);
163  char *res = REAL(strcpy)(dest, src);  // NOLINT
164  __msan_copy_poison(dest, src, n + 1);
165  return res;
166}
167
168INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {  // NOLINT
169  ENSURE_MSAN_INITED();
170  SIZE_T copy_size = REAL(strnlen)(src, n);
171  if (copy_size < n)
172    copy_size++;  // trailing \0
173  char *res = REAL(strncpy)(dest, src, n);  // NOLINT
174  __msan_copy_poison(dest, src, copy_size);
175  return res;
176}
177
178INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {  // NOLINT
179  ENSURE_MSAN_INITED();
180  SIZE_T n = REAL(strlen)(src);
181  char *res = REAL(stpcpy)(dest, src);  // NOLINT
182  __msan_copy_poison(dest, 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 *, __strdup, char *src) {
195  ENSURE_MSAN_INITED();
196  SIZE_T n = REAL(strlen)(src);
197  char *res = REAL(__strdup)(src);
198  __msan_copy_poison(res, src, n + 1);
199  return res;
200}
201
202INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
203  ENSURE_MSAN_INITED();
204  SIZE_T copy_size = REAL(strnlen)(src, n);
205  char *res = REAL(strndup)(src, n);
206  __msan_copy_poison(res, src, copy_size);
207  __msan_unpoison(res + copy_size, 1); // \0
208  return res;
209}
210
211INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
212  ENSURE_MSAN_INITED();
213  SIZE_T copy_size = REAL(strnlen)(src, n);
214  char *res = REAL(__strndup)(src, n);
215  __msan_copy_poison(res, src, copy_size);
216  __msan_unpoison(res + copy_size, 1); // \0
217  return res;
218}
219
220INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
221  ENSURE_MSAN_INITED();
222  char *res = REAL(gcvt)(number, ndigit, buf);
223  // DynamoRio tool will take care of unpoisoning gcvt result for us.
224  if (!__msan_has_dynamic_component()) {
225    SIZE_T n = REAL(strlen)(buf);
226    __msan_unpoison(buf, n + 1);
227  }
228  return res;
229}
230
231INTERCEPTOR(char *, strcat, char *dest, const char *src) {  // NOLINT
232  ENSURE_MSAN_INITED();
233  SIZE_T src_size = REAL(strlen)(src);
234  SIZE_T dest_size = REAL(strlen)(dest);
235  char *res = REAL(strcat)(dest, src);  // NOLINT
236  __msan_copy_poison(dest + dest_size, src, src_size + 1);
237  return res;
238}
239
240INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {  // NOLINT
241  ENSURE_MSAN_INITED();
242  SIZE_T dest_size = REAL(strlen)(dest);
243  SIZE_T copy_size = REAL(strlen)(src);
244  if (copy_size < n)
245    copy_size++;  // trailing \0
246  char *res = REAL(strncat)(dest, src, n);  // NOLINT
247  __msan_copy_poison(dest + dest_size, src, copy_size);
248  return res;
249}
250
251INTERCEPTOR(long, strtol, const char *nptr, char **endptr,  // NOLINT
252            int base) {
253  ENSURE_MSAN_INITED();
254  long res = REAL(strtol)(nptr, endptr, base);  // NOLINT
255  if (!__msan_has_dynamic_component()) {
256    __msan_unpoison(endptr, sizeof(*endptr));
257  }
258  return res;
259}
260
261INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr,  // NOLINT
262            int base) {
263  ENSURE_MSAN_INITED();
264  long res = REAL(strtoll)(nptr, endptr, base);  //NOLINT
265  if (!__msan_has_dynamic_component()) {
266    __msan_unpoison(endptr, sizeof(*endptr));
267  }
268  return res;
269}
270
271INTERCEPTOR(unsigned long, strtoul, const char *nptr, char **endptr,  // NOLINT
272            int base) {
273  ENSURE_MSAN_INITED();
274  unsigned long res = REAL(strtoul)(nptr, endptr, base);  // NOLINT
275  if (!__msan_has_dynamic_component()) {
276    __msan_unpoison(endptr, sizeof(*endptr));
277  }
278  return res;
279}
280
281INTERCEPTOR(unsigned long long, strtoull, const char *nptr,  // NOLINT
282            char **endptr, int base) {
283  ENSURE_MSAN_INITED();
284  unsigned long res = REAL(strtoull)(nptr, endptr, base);  // NOLINT
285  if (!__msan_has_dynamic_component()) {
286    __msan_unpoison(endptr, sizeof(*endptr));
287  }
288  return res;
289}
290
291INTERCEPTOR(double, strtod, const char *nptr, char **endptr) {  // NOLINT
292  ENSURE_MSAN_INITED();
293  double res = REAL(strtod)(nptr, endptr);  // NOLINT
294  if (!__msan_has_dynamic_component()) {
295    __msan_unpoison(endptr, sizeof(*endptr));
296  }
297  return res;
298}
299
300INTERCEPTOR(float, strtof, const char *nptr, char **endptr) {  // NOLINT
301  ENSURE_MSAN_INITED();
302  float res = REAL(strtof)(nptr, endptr);  // NOLINT
303  if (!__msan_has_dynamic_component()) {
304    __msan_unpoison(endptr, sizeof(*endptr));
305  }
306  return res;
307}
308
309INTERCEPTOR(long double, strtold, const char *nptr, char **endptr) {  // NOLINT
310  ENSURE_MSAN_INITED();
311  long double res = REAL(strtold)(nptr, endptr);  // NOLINT
312  if (!__msan_has_dynamic_component()) {
313    __msan_unpoison(endptr, sizeof(*endptr));
314  }
315  return res;
316}
317
318INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap) {
319  ENSURE_MSAN_INITED();
320  int res = REAL(vasprintf)(strp, format, ap);
321  if (res >= 0 && !__msan_has_dynamic_component()) {
322    __msan_unpoison(strp, sizeof(*strp));
323    __msan_unpoison(*strp, res + 1);
324  }
325  return res;
326}
327
328INTERCEPTOR(int, asprintf, char **strp, const char *format, ...) {  // NOLINT
329  ENSURE_MSAN_INITED();
330  va_list ap;
331  va_start(ap, format);
332  int res = vasprintf(strp, format, ap);  // NOLINT
333  va_end(ap);
334  return res;
335}
336
337INTERCEPTOR(int, vsnprintf, char *str, uptr size,
338            const char *format, va_list ap) {
339  ENSURE_MSAN_INITED();
340  int res = REAL(vsnprintf)(str, size, format, ap);
341  if (res >= 0 && !__msan_has_dynamic_component()) {
342    __msan_unpoison(str, res + 1);
343  }
344  return res;
345}
346
347INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) {
348  ENSURE_MSAN_INITED();
349  int res = REAL(vsprintf)(str, format, ap);
350  if (res >= 0 && !__msan_has_dynamic_component()) {
351    __msan_unpoison(str, res + 1);
352  }
353  return res;
354}
355
356INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
357  ENSURE_MSAN_INITED();
358  int res = REAL(vswprintf)(str, size, format, ap);
359  if (res >= 0 && !__msan_has_dynamic_component()) {
360    __msan_unpoison(str, 4 * (res + 1));
361  }
362  return res;
363}
364
365INTERCEPTOR(int, sprintf, char *str, const char *format, ...) {  // NOLINT
366  ENSURE_MSAN_INITED();
367  va_list ap;
368  va_start(ap, format);
369  int res = vsprintf(str, format, ap);  // NOLINT
370  va_end(ap);
371  return res;
372}
373
374INTERCEPTOR(int, snprintf, char *str, uptr size, const char *format, ...) {
375  ENSURE_MSAN_INITED();
376  va_list ap;
377  va_start(ap, format);
378  int res = vsnprintf(str, size, format, ap);
379  va_end(ap);
380  return res;
381}
382
383INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
384  ENSURE_MSAN_INITED();
385  va_list ap;
386  va_start(ap, format);
387  int res = vswprintf(str, size, format, ap);
388  va_end(ap);
389  return res;
390}
391
392// SIZE_T strftime(char *s, SIZE_T max, const char *format,const struct tm *tm);
393INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
394            void *tm) {
395  ENSURE_MSAN_INITED();
396  SIZE_T res = REAL(strftime)(s, max, format, tm);
397  if (res) __msan_unpoison(s, res + 1);
398  return res;
399}
400
401INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
402  ENSURE_MSAN_INITED();
403  int res = REAL(mbtowc)(dest, src, n);
404  if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
405  return res;
406}
407
408INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) {
409  ENSURE_MSAN_INITED();
410  SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
411  if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
412  return res;
413}
414
415INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
416  ENSURE_MSAN_INITED();
417  SIZE_T res = REAL(wcslen)(s);
418  CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
419  return res;
420}
421
422// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
423INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
424  ENSURE_MSAN_INITED();
425  wchar_t *res = REAL(wcschr)(s, wc, ps);
426  return res;
427}
428
429// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
430INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
431  ENSURE_MSAN_INITED();
432  wchar_t *res = REAL(wcscpy)(dest, src);
433  __msan_copy_poison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1));
434  return res;
435}
436
437// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
438INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
439  ENSURE_MSAN_INITED();
440  wchar_t *res = REAL(wmemcpy)(dest, src, n);
441  __msan_copy_poison(dest, src, n * sizeof(wchar_t));
442  return res;
443}
444
445INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
446  ENSURE_MSAN_INITED();
447  wchar_t *res = REAL(wmempcpy)(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(int, getrlimit, int resource, void *rlim) {
623  if (msan_init_is_running)
624    return REAL(getrlimit)(resource, rlim);
625  ENSURE_MSAN_INITED();
626  int res = REAL(getrlimit)(resource, rlim);
627  if (!res)
628    __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
629  return res;
630}
631
632INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
633  if (msan_init_is_running)
634    return REAL(getrlimit64)(resource, rlim);
635  ENSURE_MSAN_INITED();
636  int res = REAL(getrlimit64)(resource, rlim);
637  if (!res)
638    __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
639  return res;
640}
641
642INTERCEPTOR(int, statfs, const char *s, void *buf) {
643  ENSURE_MSAN_INITED();
644  int res = REAL(statfs)(s, buf);
645  if (!res)
646    __msan_unpoison(buf, __sanitizer::struct_statfs_sz);
647  return res;
648}
649
650INTERCEPTOR(int, fstatfs, int fd, void *buf) {
651  ENSURE_MSAN_INITED();
652  int res = REAL(fstatfs)(fd, buf);
653  if (!res)
654    __msan_unpoison(buf, __sanitizer::struct_statfs_sz);
655  return res;
656}
657
658INTERCEPTOR(int, statfs64, const char *s, void *buf) {
659  ENSURE_MSAN_INITED();
660  int res = REAL(statfs64)(s, buf);
661  if (!res)
662    __msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
663  return res;
664}
665
666INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
667  ENSURE_MSAN_INITED();
668  int res = REAL(fstatfs64)(fd, buf);
669  if (!res)
670    __msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
671  return res;
672}
673
674INTERCEPTOR(int, uname, void *utsname) {
675  ENSURE_MSAN_INITED();
676  int res = REAL(uname)(utsname);
677  if (!res) {
678    __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
679  }
680  return res;
681}
682
683INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
684  ENSURE_MSAN_INITED();
685  int res = REAL(gethostname)(name, len);
686  if (!res) {
687    SIZE_T real_len = REAL(strnlen)(name, len);
688    if (real_len < len)
689      ++real_len;
690    __msan_unpoison(name, real_len);
691  }
692  return res;
693}
694
695INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
696    int timeout) {
697  ENSURE_MSAN_INITED();
698  int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
699  if (res > 0) {
700    __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
701  }
702  return res;
703}
704
705INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
706    int timeout, void *sigmask) {
707  ENSURE_MSAN_INITED();
708  int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
709  if (res > 0) {
710    __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
711  }
712  return res;
713}
714
715INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
716  ENSURE_MSAN_INITED();
717  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
718  if (res > 0)
719    __msan_unpoison(buf, res);
720  return res;
721}
722
723INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
724            void *srcaddr, int *addrlen) {
725  ENSURE_MSAN_INITED();
726  SIZE_T srcaddr_sz;
727  if (srcaddr) srcaddr_sz = *addrlen;
728  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
729  if (res > 0) {
730    __msan_unpoison(buf, res);
731    if (srcaddr) {
732      SIZE_T sz = *addrlen;
733      __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
734    }
735  }
736  return res;
737}
738
739INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
740  if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
741  GET_MALLOC_STACK_TRACE;
742  if (!msan_inited) {
743    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
744    const SIZE_T kCallocPoolSize = 1024;
745    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
746    static SIZE_T allocated;
747    SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
748    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
749    allocated += size_in_words;
750    CHECK(allocated < kCallocPoolSize);
751    return mem;
752  }
753  return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true);
754}
755
756INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
757  GET_MALLOC_STACK_TRACE;
758  return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
759}
760
761INTERCEPTOR(void *, malloc, SIZE_T size) {
762  GET_MALLOC_STACK_TRACE;
763  return MsanReallocate(&stack, 0, size, sizeof(u64), false);
764}
765
766void __msan_allocated_memory(const void* data, uptr size) {
767  GET_MALLOC_STACK_TRACE;
768  if (flags()->poison_in_malloc)
769    __msan_poison(data, size);
770  if (__msan_get_track_origins()) {
771    u32 stack_id = StackDepotPut(stack.trace, stack.size);
772    CHECK(stack_id);
773    CHECK_EQ((stack_id >> 31), 0);  // Higher bit is occupied by stack origins.
774    __msan_set_origin(data, size, stack_id);
775  }
776}
777
778INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
779            int fd, OFF_T offset) {
780  ENSURE_MSAN_INITED();
781  void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
782  if (res != (void*)-1)
783    __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
784  return res;
785}
786
787INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
788            int fd, OFF64_T offset) {
789  ENSURE_MSAN_INITED();
790  void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
791  if (res != (void*)-1)
792    __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
793  return res;
794}
795
796struct dlinfo {
797  char *dli_fname;
798  void *dli_fbase;
799  char *dli_sname;
800  void *dli_saddr;
801};
802
803INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
804  ENSURE_MSAN_INITED();
805  int res = REAL(dladdr)(addr, info);
806  if (res != 0) {
807    __msan_unpoison(info, sizeof(*info));
808    if (info->dli_fname)
809      __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
810    if (info->dli_sname)
811      __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
812  }
813  return res;
814}
815
816// dlopen() ultimately calls mmap() down inside the loader, which generally
817// doesn't participate in dynamic symbol resolution.  Therefore we won't
818// intercept its calls to mmap, and we have to hook it here.  The loader
819// initializes the module before returning, so without the dynamic component, we
820// won't be able to clear the shadow before the initializers.  Fixing this would
821// require putting our own initializer first to clear the shadow.
822INTERCEPTOR(void *, dlopen, const char *filename, int flag) {
823  ENSURE_MSAN_INITED();
824  EnterLoader();
825  link_map *map = (link_map *)REAL(dlopen)(filename, flag);
826  ExitLoader();
827  if (!__msan_has_dynamic_component() && map) {
828    // If msandr didn't clear the shadow before the initializers ran, we do it
829    // ourselves afterwards.
830    ForEachMappedRegion(map, __msan_unpoison);
831  }
832  return (void *)map;
833}
834
835typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
836                                  void *data);
837struct dl_iterate_phdr_data {
838  dl_iterate_phdr_cb callback;
839  void *data;
840};
841
842static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
843                                   void *data) {
844  if (info) {
845    __msan_unpoison(info, size);
846    if (info->dlpi_name)
847      __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1);
848  }
849  dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
850  UnpoisonParam(3);
851  return cbdata->callback(info, size, cbdata->data);
852}
853
854INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
855  ENSURE_MSAN_INITED();
856  EnterLoader();
857  dl_iterate_phdr_data cbdata;
858  cbdata.callback = callback;
859  cbdata.data = data;
860  int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
861  ExitLoader();
862  return res;
863}
864
865INTERCEPTOR(int, getrusage, int who, void *usage) {
866  ENSURE_MSAN_INITED();
867  int res = REAL(getrusage)(who, usage);
868  if (res == 0) {
869    __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
870  }
871  return res;
872}
873
874const int kMaxSignals = 1024;
875static uptr sigactions[kMaxSignals];
876static StaticSpinMutex sigactions_mu;
877
878static void SignalHandler(int signo) {
879  typedef void (*signal_cb)(int x);
880  signal_cb cb = (signal_cb)sigactions[signo];
881  cb(signo);
882}
883
884static void SignalAction(int signo, void *si, void *uc) {
885  UnpoisonParam(3);
886  __msan_unpoison(si, __sanitizer::struct_sigaction_sz);
887  __msan_unpoison(uc, __sanitizer::ucontext_t_sz);
888
889  typedef void (*sigaction_cb)(int, void *, void *);
890  sigaction_cb cb = (sigaction_cb)sigactions[signo];
891  cb(signo, si, uc);
892}
893
894INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
895            __sanitizer_sigaction *oldact) {
896  ENSURE_MSAN_INITED();
897  // FIXME: check that *act is unpoisoned.
898  // That requires intercepting all of sigemptyset, sigfillset, etc.
899  int res;
900  if (flags()->wrap_signals) {
901    SpinMutexLock lock(&sigactions_mu);
902    CHECK_LT(signo, kMaxSignals);
903    uptr old_cb = sigactions[signo];
904    __sanitizer_sigaction new_act;
905    __sanitizer_sigaction *pnew_act = act ? &new_act : 0;
906    if (act) {
907      internal_memcpy(pnew_act, act, __sanitizer::struct_sigaction_sz);
908      uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(pnew_act);
909      uptr new_cb =
910          __sanitizer::__sanitizer_get_sigaction_sa_siginfo(pnew_act) ?
911          (uptr)SignalAction : (uptr)SignalHandler;
912      if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
913        sigactions[signo] = cb;
914        __sanitizer::__sanitizer_set_sigaction_sa_sigaction(pnew_act, new_cb);
915      }
916    }
917    res = REAL(sigaction)(signo, pnew_act, oldact);
918    if (res == 0 && oldact) {
919      uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(oldact);
920      if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
921        __sanitizer::__sanitizer_set_sigaction_sa_sigaction(oldact, old_cb);
922      }
923    }
924  } else {
925    res = REAL(sigaction)(signo, act, oldact);
926  }
927
928  if (res == 0 && oldact) {
929    __msan_unpoison(oldact, __sanitizer::struct_sigaction_sz);
930  }
931  return res;
932}
933
934INTERCEPTOR(int, signal, int signo, uptr cb) {
935  ENSURE_MSAN_INITED();
936  if (flags()->wrap_signals) {
937    CHECK_LT(signo, kMaxSignals);
938    SpinMutexLock lock(&sigactions_mu);
939    if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
940      sigactions[signo] = cb;
941      cb = (uptr) SignalHandler;
942    }
943    return REAL(signal)(signo, cb);
944  } else {
945    return REAL(signal)(signo, cb);
946  }
947}
948
949extern "C" int pthread_attr_init(void *attr);
950extern "C" int pthread_attr_destroy(void *attr);
951extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
952extern "C" int pthread_attr_getstack(void *attr, uptr *stack, uptr *stacksize);
953
954INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
955            void * param) {
956  ENSURE_MSAN_INITED(); // for GetTlsSize()
957  __sanitizer_pthread_attr_t myattr;
958  if (attr == 0) {
959    pthread_attr_init(&myattr);
960    attr = &myattr;
961  }
962
963  AdjustStackSizeLinux(attr, flags()->verbosity);
964
965  int res = REAL(pthread_create)(th, attr, callback, param);
966  if (attr == &myattr)
967    pthread_attr_destroy(&myattr);
968  if (!res) {
969    __msan_unpoison(th, __sanitizer::pthread_t_sz);
970  }
971  return res;
972}
973
974INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
975            void (*dtor)(void *value)) {
976  ENSURE_MSAN_INITED();
977  int res = REAL(pthread_key_create)(key, dtor);
978  if (!res && key)
979    __msan_unpoison(key, sizeof(*key));
980  return res;
981}
982
983INTERCEPTOR(int, pthread_join, void *th, void **retval) {
984  ENSURE_MSAN_INITED();
985  int res = REAL(pthread_join)(th, retval);
986  if (!res && retval)
987    __msan_unpoison(retval, sizeof(*retval));
988  return res;
989}
990
991struct MSanInterceptorContext {
992  bool in_interceptor_scope;
993};
994
995// A version of CHECK_UNPOISED using a saved scope value. Used in common
996// interceptors.
997#define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
998  do {                                                          \
999    if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1000      CHECK_UNPOISONED_0(x, n);                                 \
1001  } while (0)
1002
1003#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count)  \
1004  UnpoisonParam(count)
1005#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1006  __msan_unpoison(ptr, size)
1007#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1008  CHECK_UNPOISONED_CTX(ctx, ptr, size)
1009#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
1010  if (msan_init_is_running) return REAL(func)(__VA_ARGS__);   \
1011  MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1012  ctx = (void *)&msan_ctx;                                    \
1013  InterceptorScope interceptor_scope;                         \
1014  ENSURE_MSAN_INITED();
1015#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1016  do {                                         \
1017  } while (false)
1018#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1019  do {                                         \
1020  } while (false)
1021#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1022  do {                                                      \
1023  } while (false)
1024#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1025  do {                                                \
1026  } while (false)  // FIXME
1027#include "sanitizer_common/sanitizer_common_interceptors.inc"
1028
1029#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1030#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
1031#define COMMON_SYSCALL_POST_READ_RANGE(p, s)
1032#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1033#include "sanitizer_common/sanitizer_common_syscalls.inc"
1034
1035// static
1036void *fast_memset(void *ptr, int c, SIZE_T n) {
1037  // hack until we have a really fast internal_memset
1038  if (sizeof(uptr) == 8 &&
1039      (n % 8) == 0 &&
1040      ((uptr)ptr % 8) == 0 &&
1041      (c == 0 || c == -1)) {
1042    // Printf("memset %p %zd %x\n", ptr, n, c);
1043    uptr to_store = c ? -1L : 0L;
1044    uptr *p = (uptr*)ptr;
1045    for (SIZE_T i = 0; i < n / 8; i++)
1046      p[i] = to_store;
1047    return ptr;
1048  }
1049  return internal_memset(ptr, c, n);
1050}
1051
1052// static
1053void *fast_memcpy(void *dst, const void *src, SIZE_T n) {
1054  // Same hack as in fast_memset above.
1055  if (sizeof(uptr) == 8 &&
1056      (n % 8) == 0 &&
1057      ((uptr)dst % 8) == 0 &&
1058      ((uptr)src % 8) == 0) {
1059    uptr *d = (uptr*)dst;
1060    uptr *s = (uptr*)src;
1061    for (SIZE_T i = 0; i < n / 8; i++)
1062      d[i] = s[i];
1063    return dst;
1064  }
1065  return internal_memcpy(dst, src, n);
1066}
1067
1068// These interface functions reside here so that they can use
1069// fast_memset, etc.
1070void __msan_unpoison(const void *a, uptr size) {
1071  if (!MEM_IS_APP(a)) return;
1072  fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
1073}
1074
1075void __msan_poison(const void *a, uptr size) {
1076  if (!MEM_IS_APP(a)) return;
1077  fast_memset((void*)MEM_TO_SHADOW((uptr)a),
1078              __msan::flags()->poison_heap_with_zeroes ? 0 : -1, size);
1079}
1080
1081void __msan_poison_stack(void *a, uptr size) {
1082  if (!MEM_IS_APP(a)) return;
1083  fast_memset((void*)MEM_TO_SHADOW((uptr)a),
1084              __msan::flags()->poison_stack_with_zeroes ? 0 : -1, size);
1085}
1086
1087void __msan_clear_and_unpoison(void *a, uptr size) {
1088  fast_memset(a, 0, size);
1089  fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
1090}
1091
1092void __msan_copy_origin(void *dst, const void *src, uptr size) {
1093  if (!__msan_get_track_origins()) return;
1094  if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
1095  uptr d = MEM_TO_ORIGIN(dst);
1096  uptr s = MEM_TO_ORIGIN(src);
1097  uptr beg = d & ~3UL;  // align down.
1098  uptr end = (d + size + 3) & ~3UL;  // align up.
1099  s = s & ~3UL;  // align down.
1100  fast_memcpy((void*)beg, (void*)s, end - beg);
1101}
1102
1103void __msan_copy_poison(void *dst, const void *src, uptr size) {
1104  if (!MEM_IS_APP(dst)) return;
1105  if (!MEM_IS_APP(src)) return;
1106  fast_memcpy((void*)MEM_TO_SHADOW((uptr)dst),
1107              (void*)MEM_TO_SHADOW((uptr)src), size);
1108  __msan_copy_origin(dst, src, size);
1109}
1110
1111void __msan_move_poison(void *dst, const void *src, uptr size) {
1112  if (!MEM_IS_APP(dst)) return;
1113  if (!MEM_IS_APP(src)) return;
1114  internal_memmove((void*)MEM_TO_SHADOW((uptr)dst),
1115         (void*)MEM_TO_SHADOW((uptr)src), size);
1116  __msan_copy_origin(dst, src, size);
1117}
1118
1119void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1120  ENSURE_MSAN_INITED();
1121  void *res = fast_memcpy(dest, src, n);
1122  __msan_copy_poison(dest, src, n);
1123  return res;
1124}
1125
1126void *__msan_memset(void *s, int c, SIZE_T n) {
1127  ENSURE_MSAN_INITED();
1128  void *res = fast_memset(s, c, n);
1129  __msan_unpoison(s, n);
1130  return res;
1131}
1132
1133void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1134  ENSURE_MSAN_INITED();
1135  void *res = REAL(memmove)(dest, src, n);
1136  __msan_move_poison(dest, src, n);
1137  return res;
1138}
1139
1140namespace __msan {
1141void InitializeInterceptors() {
1142  static int inited = 0;
1143  CHECK_EQ(inited, 0);
1144  SANITIZER_COMMON_INTERCEPTORS_INIT;
1145
1146  INTERCEPT_FUNCTION(mmap);
1147  INTERCEPT_FUNCTION(mmap64);
1148  INTERCEPT_FUNCTION(posix_memalign);
1149  INTERCEPT_FUNCTION(malloc);
1150  INTERCEPT_FUNCTION(calloc);
1151  INTERCEPT_FUNCTION(realloc);
1152  INTERCEPT_FUNCTION(free);
1153  INTERCEPT_FUNCTION(fread);
1154  INTERCEPT_FUNCTION(fread_unlocked);
1155  INTERCEPT_FUNCTION(readlink);
1156  INTERCEPT_FUNCTION(memcpy);
1157  INTERCEPT_FUNCTION(mempcpy);
1158  INTERCEPT_FUNCTION(memset);
1159  INTERCEPT_FUNCTION(memmove);
1160  INTERCEPT_FUNCTION(bcopy);
1161  INTERCEPT_FUNCTION(wmemset);
1162  INTERCEPT_FUNCTION(wmemcpy);
1163  INTERCEPT_FUNCTION(wmempcpy);
1164  INTERCEPT_FUNCTION(wmemmove);
1165  INTERCEPT_FUNCTION(strcpy);  // NOLINT
1166  INTERCEPT_FUNCTION(stpcpy);  // NOLINT
1167  INTERCEPT_FUNCTION(strdup);
1168  INTERCEPT_FUNCTION(__strdup);
1169  INTERCEPT_FUNCTION(strndup);
1170  INTERCEPT_FUNCTION(__strndup);
1171  INTERCEPT_FUNCTION(strncpy);  // NOLINT
1172  INTERCEPT_FUNCTION(strlen);
1173  INTERCEPT_FUNCTION(strnlen);
1174  INTERCEPT_FUNCTION(gcvt);
1175  INTERCEPT_FUNCTION(strcat);  // NOLINT
1176  INTERCEPT_FUNCTION(strncat);  // NOLINT
1177  INTERCEPT_FUNCTION(strtol);
1178  INTERCEPT_FUNCTION(strtoll);
1179  INTERCEPT_FUNCTION(strtoul);
1180  INTERCEPT_FUNCTION(strtoull);
1181  INTERCEPT_FUNCTION(strtod);
1182  INTERCEPT_FUNCTION(strtof);
1183  INTERCEPT_FUNCTION(strtold);
1184  INTERCEPT_FUNCTION(vasprintf);
1185  INTERCEPT_FUNCTION(asprintf);
1186  INTERCEPT_FUNCTION(vsprintf);
1187  INTERCEPT_FUNCTION(vsnprintf);
1188  INTERCEPT_FUNCTION(vswprintf);
1189  INTERCEPT_FUNCTION(sprintf);  // NOLINT
1190  INTERCEPT_FUNCTION(snprintf);
1191  INTERCEPT_FUNCTION(swprintf);
1192  INTERCEPT_FUNCTION(strftime);
1193  INTERCEPT_FUNCTION(mbtowc);
1194  INTERCEPT_FUNCTION(mbrtowc);
1195  INTERCEPT_FUNCTION(wcslen);
1196  INTERCEPT_FUNCTION(wcschr);
1197  INTERCEPT_FUNCTION(wcscpy);
1198  INTERCEPT_FUNCTION(wcscmp);
1199  INTERCEPT_FUNCTION(wcstod);
1200  INTERCEPT_FUNCTION(getenv);
1201  INTERCEPT_FUNCTION(gettimeofday);
1202  INTERCEPT_FUNCTION(fcvt);
1203  INTERCEPT_FUNCTION(__fxstat);
1204  INTERCEPT_FUNCTION(__xstat);
1205  INTERCEPT_FUNCTION(__lxstat);
1206  INTERCEPT_FUNCTION(__fxstat64);
1207  INTERCEPT_FUNCTION(__xstat64);
1208  INTERCEPT_FUNCTION(__lxstat64);
1209  INTERCEPT_FUNCTION(pipe);
1210  INTERCEPT_FUNCTION(pipe2);
1211  INTERCEPT_FUNCTION(socketpair);
1212  INTERCEPT_FUNCTION(fgets);
1213  INTERCEPT_FUNCTION(fgets_unlocked);
1214  INTERCEPT_FUNCTION(getrlimit);
1215  INTERCEPT_FUNCTION(getrlimit64);
1216  INTERCEPT_FUNCTION(statfs);
1217  INTERCEPT_FUNCTION(fstatfs);
1218  INTERCEPT_FUNCTION(statfs64);
1219  INTERCEPT_FUNCTION(fstatfs64);
1220  INTERCEPT_FUNCTION(uname);
1221  INTERCEPT_FUNCTION(gethostname);
1222  INTERCEPT_FUNCTION(epoll_wait);
1223  INTERCEPT_FUNCTION(epoll_pwait);
1224  INTERCEPT_FUNCTION(recv);
1225  INTERCEPT_FUNCTION(recvfrom);
1226  INTERCEPT_FUNCTION(dladdr);
1227  INTERCEPT_FUNCTION(dlopen);
1228  INTERCEPT_FUNCTION(dl_iterate_phdr);
1229  INTERCEPT_FUNCTION(getrusage);
1230  INTERCEPT_FUNCTION(sigaction);
1231  INTERCEPT_FUNCTION(signal);
1232  INTERCEPT_FUNCTION(pthread_create);
1233  INTERCEPT_FUNCTION(pthread_key_create);
1234  INTERCEPT_FUNCTION(pthread_join);
1235  inited = 1;
1236}
1237}  // namespace __msan
1238