Home | History | Annotate | Download | only in msan
      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 
     31 using namespace __msan;
     32 
     33 // True if this is a nested interceptor.
     34 static THREADLOCAL int in_interceptor_scope;
     35 
     36 struct InterceptorScope {
     37   InterceptorScope() { ++in_interceptor_scope; }
     38   ~InterceptorScope() { --in_interceptor_scope; }
     39 };
     40 
     41 bool 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 
     78 static void *fast_memset(void *ptr, int c, SIZE_T n);
     79 static void *fast_memcpy(void *dst, const void *src, SIZE_T n);
     80 
     81 INTERCEPTOR(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 
     89 INTERCEPTOR(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 
     98 INTERCEPTOR(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 
    106 INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) {
    107   return __msan_memcpy(dest, src, n);
    108 }
    109 
    110 INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
    111   return (char *)__msan_memcpy(dest, src, n) + n;
    112 }
    113 
    114 INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
    115   return __msan_memmove(dest, src, n);
    116 }
    117 
    118 INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
    119   return __msan_memset(s, c, n);
    120 }
    121 
    122 INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
    123   return __msan_memmove(dest, src, n);
    124 }
    125 
    126 INTERCEPTOR(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 
    136 INTERCEPTOR(void, free, void *ptr) {
    137   ENSURE_MSAN_INITED();
    138   if (ptr == 0) return;
    139   MsanDeallocate(ptr);
    140 }
    141 
    142 INTERCEPTOR(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 
    149 INTERCEPTOR(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 
    160 INTERCEPTOR(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 
    168 INTERCEPTOR(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 
    178 INTERCEPTOR(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 
    186 INTERCEPTOR(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 
    194 INTERCEPTOR(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 
    202 INTERCEPTOR(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 
    211 INTERCEPTOR(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 
    220 INTERCEPTOR(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 
    231 INTERCEPTOR(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 
    240 INTERCEPTOR(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 
    251 INTERCEPTOR(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 
    261 INTERCEPTOR(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 
    271 INTERCEPTOR(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 
    281 INTERCEPTOR(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 
    291 INTERCEPTOR(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 
    300 INTERCEPTOR(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 
    309 INTERCEPTOR(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 
    318 INTERCEPTOR(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 
    328 INTERCEPTOR(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 
    337 INTERCEPTOR(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 
    347 INTERCEPTOR(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 
    356 INTERCEPTOR(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 
    365 INTERCEPTOR(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 
    374 INTERCEPTOR(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 
    383 INTERCEPTOR(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);
    393 INTERCEPTOR(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 
    401 INTERCEPTOR(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 
    408 INTERCEPTOR(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 
    415 INTERCEPTOR(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);
    423 INTERCEPTOR(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);
    430 INTERCEPTOR(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);
    438 INTERCEPTOR(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 
    445 INTERCEPTOR(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 
    452 INTERCEPTOR(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 
    460 INTERCEPTOR(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 
    467 INTERCEPTOR(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 
    473 INTERCEPTOR(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 
    502 INTERCEPTOR(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 
    512 INTERCEPTOR(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 
    522 INTERCEPTOR(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 
    532 extern char **environ;
    533 
    534 static void UnpoisonEnviron() {
    535   char **envp = environ;
    536   for (; *envp; ++envp) {
    537     __msan_unpoison(envp, sizeof(*envp));
    538     __msan_unpoison(*envp, REAL(strlen)(*envp) + 1);
    539   }
    540   // Trailing NULL pointer.
    541   __msan_unpoison(envp, sizeof(*envp));
    542 }
    543 
    544 INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
    545   ENSURE_MSAN_INITED();
    546   int res = REAL(setenv)(name, value, overwrite);
    547   if (!res) UnpoisonEnviron();
    548   return res;
    549 }
    550 
    551 INTERCEPTOR(int, putenv, char *string) {
    552   ENSURE_MSAN_INITED();
    553   int res = REAL(putenv)(string);
    554   if (!res) UnpoisonEnviron();
    555   return res;
    556 }
    557 
    558 INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
    559   ENSURE_MSAN_INITED();
    560   int res = REAL(__fxstat)(magic, fd, buf);
    561   if (!res)
    562     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
    563   return res;
    564 }
    565 
    566 INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
    567   ENSURE_MSAN_INITED();
    568   int res = REAL(__fxstat64)(magic, fd, buf);
    569   if (!res)
    570     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
    571   return res;
    572 }
    573 
    574 INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) {
    575   ENSURE_MSAN_INITED();
    576   int res = REAL(__xstat)(magic, path, buf);
    577   if (!res)
    578     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
    579   return res;
    580 }
    581 
    582 INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) {
    583   ENSURE_MSAN_INITED();
    584   int res = REAL(__xstat64)(magic, path, buf);
    585   if (!res)
    586     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
    587   return res;
    588 }
    589 
    590 INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) {
    591   ENSURE_MSAN_INITED();
    592   int res = REAL(__lxstat)(magic, path, buf);
    593   if (!res)
    594     __msan_unpoison(buf, __sanitizer::struct_stat_sz);
    595   return res;
    596 }
    597 
    598 INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) {
    599   ENSURE_MSAN_INITED();
    600   int res = REAL(__lxstat64)(magic, path, buf);
    601   if (!res)
    602     __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
    603   return res;
    604 }
    605 
    606 INTERCEPTOR(int, pipe, int pipefd[2]) {
    607   if (msan_init_is_running)
    608     return REAL(pipe)(pipefd);
    609   ENSURE_MSAN_INITED();
    610   int res = REAL(pipe)(pipefd);
    611   if (!res)
    612     __msan_unpoison(pipefd, sizeof(int[2]));
    613   return res;
    614 }
    615 
    616 INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
    617   ENSURE_MSAN_INITED();
    618   int res = REAL(pipe2)(pipefd, flags);
    619   if (!res)
    620     __msan_unpoison(pipefd, sizeof(int[2]));
    621   return res;
    622 }
    623 
    624 INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
    625   ENSURE_MSAN_INITED();
    626   int res = REAL(socketpair)(domain, type, protocol, sv);
    627   if (!res)
    628     __msan_unpoison(sv, sizeof(int[2]));
    629   return res;
    630 }
    631 
    632 INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
    633   ENSURE_MSAN_INITED();
    634   char *res = REAL(fgets)(s, size, stream);
    635   if (res)
    636     __msan_unpoison(s, REAL(strlen)(s) + 1);
    637   return res;
    638 }
    639 
    640 INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
    641   ENSURE_MSAN_INITED();
    642   char *res = REAL(fgets_unlocked)(s, size, stream);
    643   if (res)
    644     __msan_unpoison(s, REAL(strlen)(s) + 1);
    645   return res;
    646 }
    647 
    648 INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
    649   if (msan_init_is_running)
    650     return REAL(getrlimit)(resource, rlim);
    651   ENSURE_MSAN_INITED();
    652   int res = REAL(getrlimit)(resource, rlim);
    653   if (!res)
    654     __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
    655   return res;
    656 }
    657 
    658 INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
    659   if (msan_init_is_running)
    660     return REAL(getrlimit64)(resource, rlim);
    661   ENSURE_MSAN_INITED();
    662   int res = REAL(getrlimit64)(resource, rlim);
    663   if (!res)
    664     __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
    665   return res;
    666 }
    667 
    668 INTERCEPTOR(int, statfs, const char *s, void *buf) {
    669   ENSURE_MSAN_INITED();
    670   int res = REAL(statfs)(s, buf);
    671   if (!res)
    672     __msan_unpoison(buf, __sanitizer::struct_statfs_sz);
    673   return res;
    674 }
    675 
    676 INTERCEPTOR(int, fstatfs, int fd, void *buf) {
    677   ENSURE_MSAN_INITED();
    678   int res = REAL(fstatfs)(fd, buf);
    679   if (!res)
    680     __msan_unpoison(buf, __sanitizer::struct_statfs_sz);
    681   return res;
    682 }
    683 
    684 INTERCEPTOR(int, statfs64, const char *s, void *buf) {
    685   ENSURE_MSAN_INITED();
    686   int res = REAL(statfs64)(s, buf);
    687   if (!res)
    688     __msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
    689   return res;
    690 }
    691 
    692 INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
    693   ENSURE_MSAN_INITED();
    694   int res = REAL(fstatfs64)(fd, buf);
    695   if (!res)
    696     __msan_unpoison(buf, __sanitizer::struct_statfs64_sz);
    697   return res;
    698 }
    699 
    700 INTERCEPTOR(int, uname, void *utsname) {
    701   ENSURE_MSAN_INITED();
    702   int res = REAL(uname)(utsname);
    703   if (!res) {
    704     __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
    705   }
    706   return res;
    707 }
    708 
    709 INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
    710   ENSURE_MSAN_INITED();
    711   int res = REAL(gethostname)(name, len);
    712   if (!res) {
    713     SIZE_T real_len = REAL(strnlen)(name, len);
    714     if (real_len < len)
    715       ++real_len;
    716     __msan_unpoison(name, real_len);
    717   }
    718   return res;
    719 }
    720 
    721 INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
    722     int timeout) {
    723   ENSURE_MSAN_INITED();
    724   int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
    725   if (res > 0) {
    726     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
    727   }
    728   return res;
    729 }
    730 
    731 INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
    732     int timeout, void *sigmask) {
    733   ENSURE_MSAN_INITED();
    734   int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
    735   if (res > 0) {
    736     __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
    737   }
    738   return res;
    739 }
    740 
    741 INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
    742   ENSURE_MSAN_INITED();
    743   SSIZE_T res = REAL(recv)(fd, buf, len, flags);
    744   if (res > 0)
    745     __msan_unpoison(buf, res);
    746   return res;
    747 }
    748 
    749 INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
    750             void *srcaddr, int *addrlen) {
    751   ENSURE_MSAN_INITED();
    752   SIZE_T srcaddr_sz;
    753   if (srcaddr) srcaddr_sz = *addrlen;
    754   SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
    755   if (res > 0) {
    756     __msan_unpoison(buf, res);
    757     if (srcaddr) {
    758       SIZE_T sz = *addrlen;
    759       __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
    760     }
    761   }
    762   return res;
    763 }
    764 
    765 INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
    766   if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
    767   GET_MALLOC_STACK_TRACE;
    768   if (!msan_inited) {
    769     // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
    770     const SIZE_T kCallocPoolSize = 1024;
    771     static uptr calloc_memory_for_dlsym[kCallocPoolSize];
    772     static SIZE_T allocated;
    773     SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
    774     void *mem = (void*)&calloc_memory_for_dlsym[allocated];
    775     allocated += size_in_words;
    776     CHECK(allocated < kCallocPoolSize);
    777     return mem;
    778   }
    779   return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true);
    780 }
    781 
    782 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
    783   GET_MALLOC_STACK_TRACE;
    784   return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
    785 }
    786 
    787 INTERCEPTOR(void *, malloc, SIZE_T size) {
    788   GET_MALLOC_STACK_TRACE;
    789   return MsanReallocate(&stack, 0, size, sizeof(u64), false);
    790 }
    791 
    792 void __msan_allocated_memory(const void* data, uptr size) {
    793   GET_MALLOC_STACK_TRACE;
    794   if (flags()->poison_in_malloc)
    795     __msan_poison(data, size);
    796   if (__msan_get_track_origins()) {
    797     u32 stack_id = StackDepotPut(stack.trace, stack.size);
    798     CHECK(stack_id);
    799     CHECK_EQ((stack_id >> 31), 0);  // Higher bit is occupied by stack origins.
    800     __msan_set_origin(data, size, stack_id);
    801   }
    802 }
    803 
    804 INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
    805             int fd, OFF_T offset) {
    806   ENSURE_MSAN_INITED();
    807   void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
    808   if (res != (void*)-1)
    809     __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
    810   return res;
    811 }
    812 
    813 INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
    814             int fd, OFF64_T offset) {
    815   ENSURE_MSAN_INITED();
    816   void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
    817   if (res != (void*)-1)
    818     __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
    819   return res;
    820 }
    821 
    822 struct dlinfo {
    823   char *dli_fname;
    824   void *dli_fbase;
    825   char *dli_sname;
    826   void *dli_saddr;
    827 };
    828 
    829 INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
    830   ENSURE_MSAN_INITED();
    831   int res = REAL(dladdr)(addr, info);
    832   if (res != 0) {
    833     __msan_unpoison(info, sizeof(*info));
    834     if (info->dli_fname)
    835       __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
    836     if (info->dli_sname)
    837       __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
    838   }
    839   return res;
    840 }
    841 
    842 // dlopen() ultimately calls mmap() down inside the loader, which generally
    843 // doesn't participate in dynamic symbol resolution.  Therefore we won't
    844 // intercept its calls to mmap, and we have to hook it here.  The loader
    845 // initializes the module before returning, so without the dynamic component, we
    846 // won't be able to clear the shadow before the initializers.  Fixing this would
    847 // require putting our own initializer first to clear the shadow.
    848 INTERCEPTOR(void *, dlopen, const char *filename, int flag) {
    849   ENSURE_MSAN_INITED();
    850   EnterLoader();
    851   link_map *map = (link_map *)REAL(dlopen)(filename, flag);
    852   ExitLoader();
    853   if (!__msan_has_dynamic_component() && map) {
    854     // If msandr didn't clear the shadow before the initializers ran, we do it
    855     // ourselves afterwards.
    856     ForEachMappedRegion(map, __msan_unpoison);
    857   }
    858   return (void *)map;
    859 }
    860 
    861 typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
    862                                   void *data);
    863 struct dl_iterate_phdr_data {
    864   dl_iterate_phdr_cb callback;
    865   void *data;
    866 };
    867 
    868 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
    869                                    void *data) {
    870   if (info) {
    871     __msan_unpoison(info, size);
    872     if (info->dlpi_name)
    873       __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1);
    874   }
    875   dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
    876   UnpoisonParam(3);
    877   return cbdata->callback(info, size, cbdata->data);
    878 }
    879 
    880 INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
    881   ENSURE_MSAN_INITED();
    882   EnterLoader();
    883   dl_iterate_phdr_data cbdata;
    884   cbdata.callback = callback;
    885   cbdata.data = data;
    886   int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
    887   ExitLoader();
    888   return res;
    889 }
    890 
    891 INTERCEPTOR(int, getrusage, int who, void *usage) {
    892   ENSURE_MSAN_INITED();
    893   int res = REAL(getrusage)(who, usage);
    894   if (res == 0) {
    895     __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
    896   }
    897   return res;
    898 }
    899 
    900 const int kMaxSignals = 1024;
    901 static uptr sigactions[kMaxSignals];
    902 static StaticSpinMutex sigactions_mu;
    903 
    904 static void SignalHandler(int signo) {
    905   typedef void (*signal_cb)(int x);
    906   signal_cb cb = (signal_cb)sigactions[signo];
    907   cb(signo);
    908 }
    909 
    910 static void SignalAction(int signo, void *si, void *uc) {
    911   UnpoisonParam(3);
    912   __msan_unpoison(si, __sanitizer::struct_sigaction_sz);
    913   __msan_unpoison(uc, __sanitizer::ucontext_t_sz);
    914 
    915   typedef void (*sigaction_cb)(int, void *, void *);
    916   sigaction_cb cb = (sigaction_cb)sigactions[signo];
    917   cb(signo, si, uc);
    918 }
    919 
    920 INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
    921             __sanitizer_sigaction *oldact) {
    922   ENSURE_MSAN_INITED();
    923   // FIXME: check that *act is unpoisoned.
    924   // That requires intercepting all of sigemptyset, sigfillset, etc.
    925   int res;
    926   if (flags()->wrap_signals) {
    927     SpinMutexLock lock(&sigactions_mu);
    928     CHECK_LT(signo, kMaxSignals);
    929     uptr old_cb = sigactions[signo];
    930     __sanitizer_sigaction new_act;
    931     __sanitizer_sigaction *pnew_act = act ? &new_act : 0;
    932     if (act) {
    933       internal_memcpy(pnew_act, act, __sanitizer::struct_sigaction_sz);
    934       uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(pnew_act);
    935       uptr new_cb =
    936           __sanitizer::__sanitizer_get_sigaction_sa_siginfo(pnew_act) ?
    937           (uptr)SignalAction : (uptr)SignalHandler;
    938       if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
    939         sigactions[signo] = cb;
    940         __sanitizer::__sanitizer_set_sigaction_sa_sigaction(pnew_act, new_cb);
    941       }
    942     }
    943     res = REAL(sigaction)(signo, pnew_act, oldact);
    944     if (res == 0 && oldact) {
    945       uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(oldact);
    946       if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
    947         __sanitizer::__sanitizer_set_sigaction_sa_sigaction(oldact, old_cb);
    948       }
    949     }
    950   } else {
    951     res = REAL(sigaction)(signo, act, oldact);
    952   }
    953 
    954   if (res == 0 && oldact) {
    955     __msan_unpoison(oldact, __sanitizer::struct_sigaction_sz);
    956   }
    957   return res;
    958 }
    959 
    960 INTERCEPTOR(int, signal, int signo, uptr cb) {
    961   ENSURE_MSAN_INITED();
    962   if (flags()->wrap_signals) {
    963     CHECK_LT(signo, kMaxSignals);
    964     SpinMutexLock lock(&sigactions_mu);
    965     if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
    966       sigactions[signo] = cb;
    967       cb = (uptr) SignalHandler;
    968     }
    969     return REAL(signal)(signo, cb);
    970   } else {
    971     return REAL(signal)(signo, cb);
    972   }
    973 }
    974 
    975 extern "C" int pthread_attr_init(void *attr);
    976 extern "C" int pthread_attr_destroy(void *attr);
    977 extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
    978 extern "C" int pthread_attr_getstack(void *attr, uptr *stack, uptr *stacksize);
    979 
    980 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
    981             void * param) {
    982   ENSURE_MSAN_INITED(); // for GetTlsSize()
    983   __sanitizer_pthread_attr_t myattr;
    984   if (attr == 0) {
    985     pthread_attr_init(&myattr);
    986     attr = &myattr;
    987   }
    988 
    989   AdjustStackSizeLinux(attr, flags()->verbosity);
    990 
    991   int res = REAL(pthread_create)(th, attr, callback, param);
    992   if (attr == &myattr)
    993     pthread_attr_destroy(&myattr);
    994   if (!res) {
    995     __msan_unpoison(th, __sanitizer::pthread_t_sz);
    996   }
    997   return res;
    998 }
    999 
   1000 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
   1001             void (*dtor)(void *value)) {
   1002   ENSURE_MSAN_INITED();
   1003   int res = REAL(pthread_key_create)(key, dtor);
   1004   if (!res && key)
   1005     __msan_unpoison(key, sizeof(*key));
   1006   return res;
   1007 }
   1008 
   1009 INTERCEPTOR(int, pthread_join, void *th, void **retval) {
   1010   ENSURE_MSAN_INITED();
   1011   int res = REAL(pthread_join)(th, retval);
   1012   if (!res && retval)
   1013     __msan_unpoison(retval, sizeof(*retval));
   1014   return res;
   1015 }
   1016 
   1017 struct MSanInterceptorContext {
   1018   bool in_interceptor_scope;
   1019 };
   1020 
   1021 // A version of CHECK_UNPOISED using a saved scope value. Used in common
   1022 // interceptors.
   1023 #define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
   1024   do {                                                          \
   1025     if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
   1026       CHECK_UNPOISONED_0(x, n);                                 \
   1027   } while (0)
   1028 
   1029 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count)  \
   1030   UnpoisonParam(count)
   1031 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
   1032   __msan_unpoison(ptr, size)
   1033 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
   1034   CHECK_UNPOISONED_CTX(ctx, ptr, size)
   1035 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)              \
   1036   if (msan_init_is_running) return REAL(func)(__VA_ARGS__);   \
   1037   MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
   1038   ctx = (void *)&msan_ctx;                                    \
   1039   InterceptorScope interceptor_scope;                         \
   1040   ENSURE_MSAN_INITED();
   1041 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
   1042   do {                                         \
   1043   } while (false)
   1044 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
   1045   do {                                         \
   1046   } while (false)
   1047 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
   1048   do {                                                      \
   1049   } while (false)
   1050 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
   1051   do {                                                \
   1052   } while (false)  // FIXME
   1053 #include "sanitizer_common/sanitizer_common_interceptors.inc"
   1054 
   1055 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
   1056 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
   1057 #define COMMON_SYSCALL_POST_READ_RANGE(p, s)
   1058 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
   1059 #include "sanitizer_common/sanitizer_common_syscalls.inc"
   1060 
   1061 // static
   1062 void *fast_memset(void *ptr, int c, SIZE_T n) {
   1063   // hack until we have a really fast internal_memset
   1064   if (sizeof(uptr) == 8 &&
   1065       (n % 8) == 0 &&
   1066       ((uptr)ptr % 8) == 0 &&
   1067       (c == 0 || c == -1)) {
   1068     // Printf("memset %p %zd %x\n", ptr, n, c);
   1069     uptr to_store = c ? -1L : 0L;
   1070     uptr *p = (uptr*)ptr;
   1071     for (SIZE_T i = 0; i < n / 8; i++)
   1072       p[i] = to_store;
   1073     return ptr;
   1074   }
   1075   return internal_memset(ptr, c, n);
   1076 }
   1077 
   1078 // static
   1079 void *fast_memcpy(void *dst, const void *src, SIZE_T n) {
   1080   // Same hack as in fast_memset above.
   1081   if (sizeof(uptr) == 8 &&
   1082       (n % 8) == 0 &&
   1083       ((uptr)dst % 8) == 0 &&
   1084       ((uptr)src % 8) == 0) {
   1085     uptr *d = (uptr*)dst;
   1086     uptr *s = (uptr*)src;
   1087     for (SIZE_T i = 0; i < n / 8; i++)
   1088       d[i] = s[i];
   1089     return dst;
   1090   }
   1091   return internal_memcpy(dst, src, n);
   1092 }
   1093 
   1094 // These interface functions reside here so that they can use
   1095 // fast_memset, etc.
   1096 void __msan_unpoison(const void *a, uptr size) {
   1097   if (!MEM_IS_APP(a)) return;
   1098   fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
   1099 }
   1100 
   1101 void __msan_poison(const void *a, uptr size) {
   1102   if (!MEM_IS_APP(a)) return;
   1103   fast_memset((void*)MEM_TO_SHADOW((uptr)a),
   1104               __msan::flags()->poison_heap_with_zeroes ? 0 : -1, size);
   1105 }
   1106 
   1107 void __msan_poison_stack(void *a, uptr size) {
   1108   if (!MEM_IS_APP(a)) return;
   1109   fast_memset((void*)MEM_TO_SHADOW((uptr)a),
   1110               __msan::flags()->poison_stack_with_zeroes ? 0 : -1, size);
   1111 }
   1112 
   1113 void __msan_clear_and_unpoison(void *a, uptr size) {
   1114   fast_memset(a, 0, size);
   1115   fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
   1116 }
   1117 
   1118 void __msan_copy_origin(void *dst, const void *src, uptr size) {
   1119   if (!__msan_get_track_origins()) return;
   1120   if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
   1121   uptr d = MEM_TO_ORIGIN(dst);
   1122   uptr s = MEM_TO_ORIGIN(src);
   1123   uptr beg = d & ~3UL;  // align down.
   1124   uptr end = (d + size + 3) & ~3UL;  // align up.
   1125   s = s & ~3UL;  // align down.
   1126   fast_memcpy((void*)beg, (void*)s, end - beg);
   1127 }
   1128 
   1129 void __msan_copy_poison(void *dst, const void *src, uptr size) {
   1130   if (!MEM_IS_APP(dst)) return;
   1131   if (!MEM_IS_APP(src)) return;
   1132   fast_memcpy((void*)MEM_TO_SHADOW((uptr)dst),
   1133               (void*)MEM_TO_SHADOW((uptr)src), size);
   1134   __msan_copy_origin(dst, src, size);
   1135 }
   1136 
   1137 void __msan_move_poison(void *dst, const void *src, uptr size) {
   1138   if (!MEM_IS_APP(dst)) return;
   1139   if (!MEM_IS_APP(src)) return;
   1140   internal_memmove((void*)MEM_TO_SHADOW((uptr)dst),
   1141          (void*)MEM_TO_SHADOW((uptr)src), size);
   1142   __msan_copy_origin(dst, src, size);
   1143 }
   1144 
   1145 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
   1146   ENSURE_MSAN_INITED();
   1147   void *res = fast_memcpy(dest, src, n);
   1148   __msan_copy_poison(dest, src, n);
   1149   return res;
   1150 }
   1151 
   1152 void *__msan_memset(void *s, int c, SIZE_T n) {
   1153   ENSURE_MSAN_INITED();
   1154   void *res = fast_memset(s, c, n);
   1155   __msan_unpoison(s, n);
   1156   return res;
   1157 }
   1158 
   1159 void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
   1160   ENSURE_MSAN_INITED();
   1161   void *res = REAL(memmove)(dest, src, n);
   1162   __msan_move_poison(dest, src, n);
   1163   return res;
   1164 }
   1165 
   1166 namespace __msan {
   1167 void InitializeInterceptors() {
   1168   static int inited = 0;
   1169   CHECK_EQ(inited, 0);
   1170   SANITIZER_COMMON_INTERCEPTORS_INIT;
   1171 
   1172   INTERCEPT_FUNCTION(mmap);
   1173   INTERCEPT_FUNCTION(mmap64);
   1174   INTERCEPT_FUNCTION(posix_memalign);
   1175   INTERCEPT_FUNCTION(malloc);
   1176   INTERCEPT_FUNCTION(calloc);
   1177   INTERCEPT_FUNCTION(realloc);
   1178   INTERCEPT_FUNCTION(free);
   1179   INTERCEPT_FUNCTION(fread);
   1180   INTERCEPT_FUNCTION(fread_unlocked);
   1181   INTERCEPT_FUNCTION(readlink);
   1182   INTERCEPT_FUNCTION(memcpy);
   1183   INTERCEPT_FUNCTION(mempcpy);
   1184   INTERCEPT_FUNCTION(memset);
   1185   INTERCEPT_FUNCTION(memmove);
   1186   INTERCEPT_FUNCTION(bcopy);
   1187   INTERCEPT_FUNCTION(wmemset);
   1188   INTERCEPT_FUNCTION(wmemcpy);
   1189   INTERCEPT_FUNCTION(wmempcpy);
   1190   INTERCEPT_FUNCTION(wmemmove);
   1191   INTERCEPT_FUNCTION(strcpy);  // NOLINT
   1192   INTERCEPT_FUNCTION(stpcpy);  // NOLINT
   1193   INTERCEPT_FUNCTION(strdup);
   1194   INTERCEPT_FUNCTION(__strdup);
   1195   INTERCEPT_FUNCTION(strndup);
   1196   INTERCEPT_FUNCTION(__strndup);
   1197   INTERCEPT_FUNCTION(strncpy);  // NOLINT
   1198   INTERCEPT_FUNCTION(strlen);
   1199   INTERCEPT_FUNCTION(strnlen);
   1200   INTERCEPT_FUNCTION(gcvt);
   1201   INTERCEPT_FUNCTION(strcat);  // NOLINT
   1202   INTERCEPT_FUNCTION(strncat);  // NOLINT
   1203   INTERCEPT_FUNCTION(strtol);
   1204   INTERCEPT_FUNCTION(strtoll);
   1205   INTERCEPT_FUNCTION(strtoul);
   1206   INTERCEPT_FUNCTION(strtoull);
   1207   INTERCEPT_FUNCTION(strtod);
   1208   INTERCEPT_FUNCTION(strtof);
   1209   INTERCEPT_FUNCTION(strtold);
   1210   INTERCEPT_FUNCTION(vasprintf);
   1211   INTERCEPT_FUNCTION(asprintf);
   1212   INTERCEPT_FUNCTION(vsprintf);
   1213   INTERCEPT_FUNCTION(vsnprintf);
   1214   INTERCEPT_FUNCTION(vswprintf);
   1215   INTERCEPT_FUNCTION(sprintf);  // NOLINT
   1216   INTERCEPT_FUNCTION(snprintf);
   1217   INTERCEPT_FUNCTION(swprintf);
   1218   INTERCEPT_FUNCTION(strftime);
   1219   INTERCEPT_FUNCTION(mbtowc);
   1220   INTERCEPT_FUNCTION(mbrtowc);
   1221   INTERCEPT_FUNCTION(wcslen);
   1222   INTERCEPT_FUNCTION(wcschr);
   1223   INTERCEPT_FUNCTION(wcscpy);
   1224   INTERCEPT_FUNCTION(wcscmp);
   1225   INTERCEPT_FUNCTION(wcstod);
   1226   INTERCEPT_FUNCTION(getenv);
   1227   INTERCEPT_FUNCTION(setenv);
   1228   INTERCEPT_FUNCTION(putenv);
   1229   INTERCEPT_FUNCTION(gettimeofday);
   1230   INTERCEPT_FUNCTION(fcvt);
   1231   INTERCEPT_FUNCTION(__fxstat);
   1232   INTERCEPT_FUNCTION(__xstat);
   1233   INTERCEPT_FUNCTION(__lxstat);
   1234   INTERCEPT_FUNCTION(__fxstat64);
   1235   INTERCEPT_FUNCTION(__xstat64);
   1236   INTERCEPT_FUNCTION(__lxstat64);
   1237   INTERCEPT_FUNCTION(pipe);
   1238   INTERCEPT_FUNCTION(pipe2);
   1239   INTERCEPT_FUNCTION(socketpair);
   1240   INTERCEPT_FUNCTION(fgets);
   1241   INTERCEPT_FUNCTION(fgets_unlocked);
   1242   INTERCEPT_FUNCTION(getrlimit);
   1243   INTERCEPT_FUNCTION(getrlimit64);
   1244   INTERCEPT_FUNCTION(statfs);
   1245   INTERCEPT_FUNCTION(fstatfs);
   1246   INTERCEPT_FUNCTION(statfs64);
   1247   INTERCEPT_FUNCTION(fstatfs64);
   1248   INTERCEPT_FUNCTION(uname);
   1249   INTERCEPT_FUNCTION(gethostname);
   1250   INTERCEPT_FUNCTION(epoll_wait);
   1251   INTERCEPT_FUNCTION(epoll_pwait);
   1252   INTERCEPT_FUNCTION(recv);
   1253   INTERCEPT_FUNCTION(recvfrom);
   1254   INTERCEPT_FUNCTION(dladdr);
   1255   INTERCEPT_FUNCTION(dlopen);
   1256   INTERCEPT_FUNCTION(dl_iterate_phdr);
   1257   INTERCEPT_FUNCTION(getrusage);
   1258   INTERCEPT_FUNCTION(sigaction);
   1259   INTERCEPT_FUNCTION(signal);
   1260   INTERCEPT_FUNCTION(pthread_create);
   1261   INTERCEPT_FUNCTION(pthread_key_create);
   1262   INTERCEPT_FUNCTION(pthread_join);
   1263   inited = 1;
   1264 }
   1265 }  // namespace __msan
   1266