1//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
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// Common function interceptors for tools like AddressSanitizer,
11// ThreadSanitizer, MemorySanitizer, etc.
12//
13// This file should be included into the tool's interceptor file,
14// which has to define it's own macros:
15//   COMMON_INTERCEPTOR_ENTER
16//   COMMON_INTERCEPTOR_ENTER_NOIGNORE
17//   COMMON_INTERCEPTOR_READ_RANGE
18//   COMMON_INTERCEPTOR_WRITE_RANGE
19//   COMMON_INTERCEPTOR_INITIALIZE_RANGE
20//   COMMON_INTERCEPTOR_DIR_ACQUIRE
21//   COMMON_INTERCEPTOR_FD_ACQUIRE
22//   COMMON_INTERCEPTOR_FD_RELEASE
23//   COMMON_INTERCEPTOR_FD_ACCESS
24//   COMMON_INTERCEPTOR_SET_THREAD_NAME
25//   COMMON_INTERCEPTOR_ON_DLOPEN
26//   COMMON_INTERCEPTOR_ON_EXIT
27//   COMMON_INTERCEPTOR_MUTEX_LOCK
28//   COMMON_INTERCEPTOR_MUTEX_UNLOCK
29//   COMMON_INTERCEPTOR_MUTEX_REPAIR
30//   COMMON_INTERCEPTOR_SET_PTHREAD_NAME
31//   COMMON_INTERCEPTOR_HANDLE_RECVMSG
32//   COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
33//===----------------------------------------------------------------------===//
34
35#include "interception/interception.h"
36#include "sanitizer_addrhashmap.h"
37#include "sanitizer_placement_new.h"
38#include "sanitizer_platform_interceptors.h"
39#include "sanitizer_tls_get_addr.h"
40
41#include <stdarg.h>
42
43#if SANITIZER_INTERCEPTOR_HOOKS
44#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)                                     \
45  do {                                                                         \
46    if (f)                                                                     \
47      f(__VA_ARGS__);                                                          \
48  } while (false);
49#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)                                  \
50  extern "C" {                                                                 \
51  SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);  \
52  } // extern "C"
53#else
54#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
55#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)
56
57#endif  // SANITIZER_INTERCEPTOR_HOOKS
58
59#if SANITIZER_WINDOWS && !defined(va_copy)
60#define va_copy(dst, src) ((dst) = (src))
61#endif // _WIN32
62
63#if SANITIZER_FREEBSD
64#define pthread_setname_np pthread_set_name_np
65#define inet_aton __inet_aton
66#define inet_pton __inet_pton
67#define iconv __bsd_iconv
68#endif
69
70#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
71#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
72#endif
73
74#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
75#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
76#endif
77
78#ifndef COMMON_INTERCEPTOR_FD_ACCESS
79#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
80#endif
81
82#ifndef COMMON_INTERCEPTOR_MUTEX_LOCK
83#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) {}
84#endif
85
86#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
87#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
88#endif
89
90#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
91#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
92#endif
93
94#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
95#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
96#endif
97
98#ifndef COMMON_INTERCEPTOR_FILE_OPEN
99#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
100#endif
101
102#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
103#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
104#endif
105
106#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
107#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
108#endif
109
110#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
111#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
112#endif
113
114#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
115#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
116  COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
117#endif
118
119#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
120#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
121#endif
122
123#define COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n)       \
124    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
125      common_flags()->strict_string_checks ? (len) + 1 : (n) )
126
127#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n)                   \
128    COMMON_INTERCEPTOR_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
129
130#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
131#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) {}
132#endif
133
134#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
135#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
136#endif
137
138#ifndef COMMON_INTERCEPTOR_ACQUIRE
139#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
140#endif
141
142#ifndef COMMON_INTERCEPTOR_RELEASE
143#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
144#endif
145
146struct FileMetadata {
147  // For open_memstream().
148  char **addr;
149  SIZE_T *size;
150};
151
152struct CommonInterceptorMetadata {
153  enum {
154    CIMT_INVALID = 0,
155    CIMT_FILE
156  } type;
157  union {
158    FileMetadata file;
159  };
160};
161
162typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
163
164static MetadataHashMap *interceptor_metadata_map;
165
166#if SI_NOT_WINDOWS
167UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
168                                          const FileMetadata &file) {
169  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
170  CHECK(h.created());
171  h->type = CommonInterceptorMetadata::CIMT_FILE;
172  h->file = file;
173}
174
175UNUSED static const FileMetadata *GetInterceptorMetadata(
176    __sanitizer_FILE *addr) {
177  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
178                            /* remove */ false,
179                            /* create */ false);
180  if (h.exists()) {
181    CHECK(!h.created());
182    CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
183    return &h->file;
184  } else {
185    return 0;
186  }
187}
188
189UNUSED static void DeleteInterceptorMetadata(void *addr) {
190  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
191  CHECK(h.exists());
192}
193#endif  // SI_NOT_WINDOWS
194
195#if SANITIZER_INTERCEPT_TEXTDOMAIN
196INTERCEPTOR(char*, textdomain, const char *domainname) {
197  void *ctx;
198  COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
199  COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
200  char *domain = REAL(textdomain)(domainname);
201  if (domain) {
202    COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
203  }
204  return domain;
205}
206#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
207#else
208#define INIT_TEXTDOMAIN
209#endif
210
211#if SANITIZER_INTERCEPT_STRCMP
212static inline int CharCmpX(unsigned char c1, unsigned char c2) {
213  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
214}
215
216DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
217                              const char *s1, const char *s2)
218
219INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
220  void *ctx;
221  COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
222  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
223                             s2);
224  unsigned char c1, c2;
225  uptr i;
226  for (i = 0;; i++) {
227    c1 = (unsigned char)s1[i];
228    c2 = (unsigned char)s2[i];
229    if (c1 != c2 || c1 == '\0') break;
230  }
231  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
232  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
233  return CharCmpX(c1, c2);
234}
235
236DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
237                              const char *s1, const char *s2, uptr n)
238
239INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
240  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
241    return internal_strncmp(s1, s2, size);
242  void *ctx;
243  COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
244  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
245                             s2, size);
246  unsigned char c1 = 0, c2 = 0;
247  uptr i;
248  for (i = 0; i < size; i++) {
249    c1 = (unsigned char)s1[i];
250    c2 = (unsigned char)s2[i];
251    if (c1 != c2 || c1 == '\0') break;
252  }
253  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
254  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
255  return CharCmpX(c1, c2);
256}
257
258#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
259#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
260#else
261#define INIT_STRCMP
262#define INIT_STRNCMP
263#endif
264
265#if SANITIZER_INTERCEPT_STRCASECMP
266static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
267  int c1_low = ToLower(c1);
268  int c2_low = ToLower(c2);
269  return c1_low - c2_low;
270}
271
272INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
273  void *ctx;
274  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
275  unsigned char c1 = 0, c2 = 0;
276  uptr i;
277  for (i = 0;; i++) {
278    c1 = (unsigned char)s1[i];
279    c2 = (unsigned char)s2[i];
280    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
281  }
282  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
283  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
284  return CharCaseCmp(c1, c2);
285}
286
287INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
288  void *ctx;
289  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
290  unsigned char c1 = 0, c2 = 0;
291  uptr i;
292  for (i = 0; i < n; i++) {
293    c1 = (unsigned char)s1[i];
294    c2 = (unsigned char)s2[i];
295    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
296  }
297  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
298  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
299  return CharCaseCmp(c1, c2);
300}
301
302#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
303#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
304#else
305#define INIT_STRCASECMP
306#define INIT_STRNCASECMP
307#endif
308
309#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
310static inline void StrstrCheck(void *ctx, char *r, const char *s1,
311                               const char *s2) {
312    uptr len1 = REAL(strlen)(s1);
313    uptr len2 = REAL(strlen)(s2);
314    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s1, len1,
315                                          r ? r - s1 + len2 : len1 + 1);
316    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
317}
318#endif
319
320#if SANITIZER_INTERCEPT_STRSTR
321INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
322  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
323    return internal_strstr(s1, s2);
324  void *ctx;
325  COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
326  char *r = REAL(strstr)(s1, s2);
327  if (common_flags()->intercept_strstr)
328    StrstrCheck(ctx, r, s1, s2);
329  return r;
330}
331
332#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
333#else
334#define INIT_STRSTR
335#endif
336
337#if SANITIZER_INTERCEPT_STRCASESTR
338INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
339  void *ctx;
340  COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
341  char *r = REAL(strcasestr)(s1, s2);
342  if (common_flags()->intercept_strstr)
343    StrstrCheck(ctx, r, s1, s2);
344  return r;
345}
346
347#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
348#else
349#define INIT_STRCASESTR
350#endif
351
352#if SANITIZER_INTERCEPT_STRSPN
353INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
354  void *ctx;
355  COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
356  SIZE_T r = REAL(strspn)(s1, s2);
357  if (common_flags()->intercept_strspn) {
358    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
359    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
360  }
361  return r;
362}
363
364INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
365  void *ctx;
366  COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
367  SIZE_T r = REAL(strcspn)(s1, s2);
368  if (common_flags()->intercept_strspn) {
369    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
370    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
371  }
372  return r;
373}
374
375#define INIT_STRSPN \
376  COMMON_INTERCEPT_FUNCTION(strspn); \
377  COMMON_INTERCEPT_FUNCTION(strcspn);
378#else
379#define INIT_STRSPN
380#endif
381
382#if SANITIZER_INTERCEPT_STRPBRK
383INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
384  void *ctx;
385  COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
386  char *r = REAL(strpbrk)(s1, s2);
387  if (common_flags()->intercept_strpbrk) {
388    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
389    COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
390        r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
391  }
392  return r;
393}
394
395#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
396#else
397#define INIT_STRPBRK
398#endif
399
400#if SANITIZER_INTERCEPT_MEMCMP
401
402DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
403                              const void *s1, const void *s2, uptr n)
404
405INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
406  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
407    return internal_memcmp(a1, a2, size);
408  void *ctx;
409  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
410  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
411                             a2, size);
412  if (common_flags()->intercept_memcmp) {
413    if (common_flags()->strict_memcmp) {
414      // Check the entire regions even if the first bytes of the buffers are
415      // different.
416      COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
417      COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
418      // Fallthrough to REAL(memcmp) below.
419    } else {
420      unsigned char c1 = 0, c2 = 0;
421      const unsigned char *s1 = (const unsigned char*)a1;
422      const unsigned char *s2 = (const unsigned char*)a2;
423      uptr i;
424      for (i = 0; i < size; i++) {
425        c1 = s1[i];
426        c2 = s2[i];
427        if (c1 != c2) break;
428      }
429      COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
430      COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
431      return CharCmpX(c1, c2);
432    }
433  }
434  return REAL(memcmp(a1, a2, size));
435}
436
437#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
438#else
439#define INIT_MEMCMP
440#endif
441
442#if SANITIZER_INTERCEPT_MEMCHR
443INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
444  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
445    return internal_memchr(s, c, n);
446  void *ctx;
447  COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
448  void *res = REAL(memchr)(s, c, n);
449  uptr len = res ? (char *)res - (const char *)s + 1 : n;
450  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
451  return res;
452}
453
454#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
455#else
456#define INIT_MEMCHR
457#endif
458
459#if SANITIZER_INTERCEPT_MEMRCHR
460INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
461  void *ctx;
462  COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
463  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
464  return REAL(memrchr)(s, c, n);
465}
466
467#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
468#else
469#define INIT_MEMRCHR
470#endif
471
472#if SANITIZER_INTERCEPT_FREXP
473INTERCEPTOR(double, frexp, double x, int *exp) {
474  void *ctx;
475  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
476  // Assuming frexp() always writes to |exp|.
477  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
478  double res = REAL(frexp)(x, exp);
479  return res;
480}
481
482#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
483#else
484#define INIT_FREXP
485#endif  // SANITIZER_INTERCEPT_FREXP
486
487#if SANITIZER_INTERCEPT_FREXPF_FREXPL
488INTERCEPTOR(float, frexpf, float x, int *exp) {
489  void *ctx;
490  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
491  // FIXME: under ASan the call below may write to freed memory and corrupt
492  // its metadata. See
493  // https://github.com/google/sanitizers/issues/321.
494  float res = REAL(frexpf)(x, exp);
495  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
496  return res;
497}
498
499INTERCEPTOR(long double, frexpl, long double x, int *exp) {
500  void *ctx;
501  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
502  // FIXME: under ASan the call below may write to freed memory and corrupt
503  // its metadata. See
504  // https://github.com/google/sanitizers/issues/321.
505  long double res = REAL(frexpl)(x, exp);
506  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
507  return res;
508}
509
510#define INIT_FREXPF_FREXPL           \
511  COMMON_INTERCEPT_FUNCTION(frexpf); \
512  COMMON_INTERCEPT_FUNCTION(frexpl)
513#else
514#define INIT_FREXPF_FREXPL
515#endif  // SANITIZER_INTERCEPT_FREXPF_FREXPL
516
517#if SI_NOT_WINDOWS
518static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
519                        SIZE_T iovlen, SIZE_T maxlen) {
520  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
521    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
522    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
523    maxlen -= sz;
524  }
525}
526
527static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
528                       SIZE_T iovlen, SIZE_T maxlen) {
529  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
530  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
531    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
532    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
533    maxlen -= sz;
534  }
535}
536#endif
537
538#if SANITIZER_INTERCEPT_READ
539INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
540  void *ctx;
541  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
542  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
543  // FIXME: under ASan the call below may write to freed memory and corrupt
544  // its metadata. See
545  // https://github.com/google/sanitizers/issues/321.
546  SSIZE_T res = REAL(read)(fd, ptr, count);
547  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
548  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
549  return res;
550}
551#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
552#else
553#define INIT_READ
554#endif
555
556#if SANITIZER_INTERCEPT_PREAD
557INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
558  void *ctx;
559  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
560  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
561  // FIXME: under ASan the call below may write to freed memory and corrupt
562  // its metadata. See
563  // https://github.com/google/sanitizers/issues/321.
564  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
565  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
566  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
567  return res;
568}
569#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
570#else
571#define INIT_PREAD
572#endif
573
574#if SANITIZER_INTERCEPT_PREAD64
575INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
576  void *ctx;
577  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
578  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
579  // FIXME: under ASan the call below may write to freed memory and corrupt
580  // its metadata. See
581  // https://github.com/google/sanitizers/issues/321.
582  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
583  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
584  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
585  return res;
586}
587#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
588#else
589#define INIT_PREAD64
590#endif
591
592#if SANITIZER_INTERCEPT_READV
593INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
594                        int iovcnt) {
595  void *ctx;
596  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
597  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
598  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
599  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
600  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
601  return res;
602}
603#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
604#else
605#define INIT_READV
606#endif
607
608#if SANITIZER_INTERCEPT_PREADV
609INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
610            OFF_T offset) {
611  void *ctx;
612  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
613  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
614  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
615  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
616  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
617  return res;
618}
619#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
620#else
621#define INIT_PREADV
622#endif
623
624#if SANITIZER_INTERCEPT_PREADV64
625INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
626            OFF64_T offset) {
627  void *ctx;
628  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
629  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
630  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
631  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
632  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
633  return res;
634}
635#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
636#else
637#define INIT_PREADV64
638#endif
639
640#if SANITIZER_INTERCEPT_WRITE
641INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
642  void *ctx;
643  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
644  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
645  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
646  SSIZE_T res = REAL(write)(fd, ptr, count);
647  // FIXME: this check should be _before_ the call to REAL(write), not after
648  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
649  return res;
650}
651#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
652#else
653#define INIT_WRITE
654#endif
655
656#if SANITIZER_INTERCEPT_PWRITE
657INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
658  void *ctx;
659  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
660  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
661  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
662  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
663  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
664  return res;
665}
666#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
667#else
668#define INIT_PWRITE
669#endif
670
671#if SANITIZER_INTERCEPT_PWRITE64
672INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
673            OFF64_T offset) {
674  void *ctx;
675  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
676  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
677  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
678  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
679  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
680  return res;
681}
682#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
683#else
684#define INIT_PWRITE64
685#endif
686
687#if SANITIZER_INTERCEPT_WRITEV
688INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
689                        int iovcnt) {
690  void *ctx;
691  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
692  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
693  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
694  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
695  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
696  return res;
697}
698#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
699#else
700#define INIT_WRITEV
701#endif
702
703#if SANITIZER_INTERCEPT_PWRITEV
704INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
705            OFF_T offset) {
706  void *ctx;
707  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
708  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
709  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
710  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
711  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
712  return res;
713}
714#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
715#else
716#define INIT_PWRITEV
717#endif
718
719#if SANITIZER_INTERCEPT_PWRITEV64
720INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
721            OFF64_T offset) {
722  void *ctx;
723  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
724  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
725  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
726  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
727  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
728  return res;
729}
730#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
731#else
732#define INIT_PWRITEV64
733#endif
734
735#if SANITIZER_INTERCEPT_PRCTL
736INTERCEPTOR(int, prctl, int option, unsigned long arg2,
737            unsigned long arg3,                        // NOLINT
738            unsigned long arg4, unsigned long arg5) {  // NOLINT
739  void *ctx;
740  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
741  static const int PR_SET_NAME = 15;
742  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
743  if (option == PR_SET_NAME) {
744    char buff[16];
745    internal_strncpy(buff, (char *)arg2, 15);
746    buff[15] = 0;
747    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
748  }
749  return res;
750}
751#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
752#else
753#define INIT_PRCTL
754#endif  // SANITIZER_INTERCEPT_PRCTL
755
756#if SANITIZER_INTERCEPT_TIME
757INTERCEPTOR(unsigned long, time, unsigned long *t) {
758  void *ctx;
759  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
760  unsigned long local_t;
761  unsigned long res = REAL(time)(&local_t);
762  if (t && res != (unsigned long)-1) {
763    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
764    *t = local_t;
765  }
766  return res;
767}
768#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
769#else
770#define INIT_TIME
771#endif  // SANITIZER_INTERCEPT_TIME
772
773#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
774static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
775  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
776  if (tm->tm_zone) {
777    // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
778    // can point to shared memory and tsan would report a data race.
779    COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
780                                        REAL(strlen(tm->tm_zone)) + 1);
781  }
782}
783INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
784  void *ctx;
785  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
786  __sanitizer_tm *res = REAL(localtime)(timep);
787  if (res) {
788    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
789    unpoison_tm(ctx, res);
790  }
791  return res;
792}
793INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
794  void *ctx;
795  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
796  __sanitizer_tm *res = REAL(localtime_r)(timep, result);
797  if (res) {
798    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
799    unpoison_tm(ctx, res);
800  }
801  return res;
802}
803INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
804  void *ctx;
805  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
806  __sanitizer_tm *res = REAL(gmtime)(timep);
807  if (res) {
808    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
809    unpoison_tm(ctx, res);
810  }
811  return res;
812}
813INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
814  void *ctx;
815  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
816  __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
817  if (res) {
818    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
819    unpoison_tm(ctx, res);
820  }
821  return res;
822}
823INTERCEPTOR(char *, ctime, unsigned long *timep) {
824  void *ctx;
825  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
826  // FIXME: under ASan the call below may write to freed memory and corrupt
827  // its metadata. See
828  // https://github.com/google/sanitizers/issues/321.
829  char *res = REAL(ctime)(timep);
830  if (res) {
831    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
832    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
833  }
834  return res;
835}
836INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
837  void *ctx;
838  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
839  // FIXME: under ASan the call below may write to freed memory and corrupt
840  // its metadata. See
841  // https://github.com/google/sanitizers/issues/321.
842  char *res = REAL(ctime_r)(timep, result);
843  if (res) {
844    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
845    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
846  }
847  return res;
848}
849INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
850  void *ctx;
851  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
852  // FIXME: under ASan the call below may write to freed memory and corrupt
853  // its metadata. See
854  // https://github.com/google/sanitizers/issues/321.
855  char *res = REAL(asctime)(tm);
856  if (res) {
857    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
858    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
859  }
860  return res;
861}
862INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
863  void *ctx;
864  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
865  // FIXME: under ASan the call below may write to freed memory and corrupt
866  // its metadata. See
867  // https://github.com/google/sanitizers/issues/321.
868  char *res = REAL(asctime_r)(tm, result);
869  if (res) {
870    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
871    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
872  }
873  return res;
874}
875INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
876  void *ctx;
877  COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
878  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
879  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
880  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
881  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
882  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
883  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
884  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
885  long res = REAL(mktime)(tm);
886  if (res != -1) unpoison_tm(ctx, tm);
887  return res;
888}
889#define INIT_LOCALTIME_AND_FRIENDS        \
890  COMMON_INTERCEPT_FUNCTION(localtime);   \
891  COMMON_INTERCEPT_FUNCTION(localtime_r); \
892  COMMON_INTERCEPT_FUNCTION(gmtime);      \
893  COMMON_INTERCEPT_FUNCTION(gmtime_r);    \
894  COMMON_INTERCEPT_FUNCTION(ctime);       \
895  COMMON_INTERCEPT_FUNCTION(ctime_r);     \
896  COMMON_INTERCEPT_FUNCTION(asctime);     \
897  COMMON_INTERCEPT_FUNCTION(asctime_r);   \
898  COMMON_INTERCEPT_FUNCTION(mktime);
899#else
900#define INIT_LOCALTIME_AND_FRIENDS
901#endif  // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
902
903#if SANITIZER_INTERCEPT_STRPTIME
904INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
905  void *ctx;
906  COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
907  if (format)
908    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
909  // FIXME: under ASan the call below may write to freed memory and corrupt
910  // its metadata. See
911  // https://github.com/google/sanitizers/issues/321.
912  char *res = REAL(strptime)(s, format, tm);
913  COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
914  if (res && tm) {
915    // Do not call unpoison_tm here, because strptime does not, in fact,
916    // initialize the entire struct tm. For example, tm_zone pointer is left
917    // uninitialized.
918    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
919  }
920  return res;
921}
922#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
923#else
924#define INIT_STRPTIME
925#endif
926
927#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
928#include "sanitizer_common_interceptors_format.inc"
929
930#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...)                              \
931  {                                                                            \
932    void *ctx;                                                                 \
933    va_list ap;                                                                \
934    va_start(ap, format);                                                      \
935    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap);                     \
936    int res = WRAP(vname)(__VA_ARGS__, ap);                                    \
937    va_end(ap);                                                                \
938    return res;                                                                \
939  }
940
941#endif
942
943#if SANITIZER_INTERCEPT_SCANF
944
945#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
946  {                                                                            \
947    void *ctx;                                                                 \
948    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
949    va_list aq;                                                                \
950    va_copy(aq, ap);                                                           \
951    int res = REAL(vname)(__VA_ARGS__);                                        \
952    if (res > 0)                                                               \
953      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
954    va_end(aq);                                                                \
955    return res;                                                                \
956  }
957
958INTERCEPTOR(int, vscanf, const char *format, va_list ap)
959VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
960
961INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
962VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
963
964INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
965VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
966
967#if SANITIZER_INTERCEPT_ISOC99_SCANF
968INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
969VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
970
971INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
972            va_list ap)
973VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
974
975INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
976VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
977#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF
978
979INTERCEPTOR(int, scanf, const char *format, ...)
980FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
981
982INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
983FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
984
985INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
986FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
987
988#if SANITIZER_INTERCEPT_ISOC99_SCANF
989INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
990FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
991
992INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
993FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
994
995INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
996FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
997#endif
998
999#endif
1000
1001#if SANITIZER_INTERCEPT_SCANF
1002#define INIT_SCANF                    \
1003  COMMON_INTERCEPT_FUNCTION(scanf);   \
1004  COMMON_INTERCEPT_FUNCTION(sscanf);  \
1005  COMMON_INTERCEPT_FUNCTION(fscanf);  \
1006  COMMON_INTERCEPT_FUNCTION(vscanf);  \
1007  COMMON_INTERCEPT_FUNCTION(vsscanf); \
1008  COMMON_INTERCEPT_FUNCTION(vfscanf);
1009#else
1010#define INIT_SCANF
1011#endif
1012
1013#if SANITIZER_INTERCEPT_ISOC99_SCANF
1014#define INIT_ISOC99_SCANF                      \
1015  COMMON_INTERCEPT_FUNCTION(__isoc99_scanf);   \
1016  COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf);  \
1017  COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf);  \
1018  COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf);  \
1019  COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
1020  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
1021#else
1022#define INIT_ISOC99_SCANF
1023#endif
1024
1025#if SANITIZER_INTERCEPT_PRINTF
1026
1027#define VPRINTF_INTERCEPTOR_ENTER(vname, ...)                                  \
1028  void *ctx;                                                                   \
1029  COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                           \
1030  va_list aq;                                                                  \
1031  va_copy(aq, ap);
1032
1033#define VPRINTF_INTERCEPTOR_RETURN()                                           \
1034  va_end(aq);
1035
1036#define VPRINTF_INTERCEPTOR_IMPL(vname, ...)                                   \
1037  {                                                                            \
1038    VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__);                             \
1039    if (common_flags()->check_printf)                                          \
1040      printf_common(ctx, format, aq);                                          \
1041    int res = REAL(vname)(__VA_ARGS__);                                        \
1042    VPRINTF_INTERCEPTOR_RETURN();                                              \
1043    return res;                                                                \
1044  }
1045
1046// FIXME: under ASan the REAL() call below may write to freed memory and
1047// corrupt its metadata. See
1048// https://github.com/google/sanitizers/issues/321.
1049#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...)                             \
1050  {                                                                            \
1051    VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__)                         \
1052    if (common_flags()->check_printf) {                                        \
1053      printf_common(ctx, format, aq);                                          \
1054    }                                                                          \
1055    int res = REAL(vname)(str, __VA_ARGS__);                                   \
1056    if (res >= 0) {                                                            \
1057      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1);                       \
1058    }                                                                          \
1059    VPRINTF_INTERCEPTOR_RETURN();                                              \
1060    return res;                                                                \
1061  }
1062
1063// FIXME: under ASan the REAL() call below may write to freed memory and
1064// corrupt its metadata. See
1065// https://github.com/google/sanitizers/issues/321.
1066#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...)                      \
1067  {                                                                            \
1068    VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__)                   \
1069    if (common_flags()->check_printf) {                                        \
1070      printf_common(ctx, format, aq);                                          \
1071    }                                                                          \
1072    int res = REAL(vname)(str, size, __VA_ARGS__);                             \
1073    if (res >= 0) {                                                            \
1074      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1)));  \
1075    }                                                                          \
1076    VPRINTF_INTERCEPTOR_RETURN();                                              \
1077    return res;                                                                \
1078  }
1079
1080// FIXME: under ASan the REAL() call below may write to freed memory and
1081// corrupt its metadata. See
1082// https://github.com/google/sanitizers/issues/321.
1083#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...)                           \
1084  {                                                                            \
1085    VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__)                        \
1086    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *));                 \
1087    if (common_flags()->check_printf) {                                        \
1088      printf_common(ctx, format, aq);                                          \
1089    }                                                                          \
1090    int res = REAL(vname)(strp, __VA_ARGS__);                                  \
1091    if (res >= 0) {                                                            \
1092      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1);                     \
1093    }                                                                          \
1094    VPRINTF_INTERCEPTOR_RETURN();                                              \
1095    return res;                                                                \
1096  }
1097
1098INTERCEPTOR(int, vprintf, const char *format, va_list ap)
1099VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
1100
1101INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
1102            va_list ap)
1103VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
1104
1105INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
1106            va_list ap)
1107VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
1108
1109#if SANITIZER_INTERCEPT_PRINTF_L
1110INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
1111            const char *format, va_list ap)
1112VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)
1113
1114INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
1115            const char *format, ...)
1116FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
1117#endif  // SANITIZER_INTERCEPT_PRINTF_L
1118
1119INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
1120VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
1121
1122INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
1123VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
1124
1125#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1126INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
1127VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
1128
1129INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
1130            const char *format, va_list ap)
1131VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
1132
1133INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
1134            va_list ap)
1135VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)
1136
1137INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
1138            va_list ap)
1139VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
1140                          ap)
1141
1142#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF
1143
1144INTERCEPTOR(int, printf, const char *format, ...)
1145FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
1146
1147INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
1148FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
1149
1150INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
1151FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
1152
1153INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
1154FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
1155
1156INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
1157FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
1158
1159#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1160INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
1161FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
1162
1163INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
1164            ...)
1165FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
1166
1167INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
1168FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)
1169
1170INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
1171            const char *format, ...)
1172FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
1173                        format)
1174
1175#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF
1176
1177#endif  // SANITIZER_INTERCEPT_PRINTF
1178
1179#if SANITIZER_INTERCEPT_PRINTF
1180#define INIT_PRINTF                     \
1181  COMMON_INTERCEPT_FUNCTION(printf);    \
1182  COMMON_INTERCEPT_FUNCTION(sprintf);   \
1183  COMMON_INTERCEPT_FUNCTION(snprintf);  \
1184  COMMON_INTERCEPT_FUNCTION(asprintf);  \
1185  COMMON_INTERCEPT_FUNCTION(fprintf);   \
1186  COMMON_INTERCEPT_FUNCTION(vprintf);   \
1187  COMMON_INTERCEPT_FUNCTION(vsprintf);  \
1188  COMMON_INTERCEPT_FUNCTION(vsnprintf); \
1189  COMMON_INTERCEPT_FUNCTION(vasprintf); \
1190  COMMON_INTERCEPT_FUNCTION(vfprintf);
1191#else
1192#define INIT_PRINTF
1193#endif
1194
1195#if SANITIZER_INTERCEPT_PRINTF_L
1196#define INIT_PRINTF_L                     \
1197  COMMON_INTERCEPT_FUNCTION(snprintf_l);  \
1198  COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
1199#else
1200#define INIT_PRINTF_L
1201#endif
1202
1203#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1204#define INIT_ISOC99_PRINTF                       \
1205  COMMON_INTERCEPT_FUNCTION(__isoc99_printf);    \
1206  COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf);   \
1207  COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf);  \
1208  COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf);   \
1209  COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf);   \
1210  COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf);  \
1211  COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
1212  COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
1213#else
1214#define INIT_ISOC99_PRINTF
1215#endif
1216
1217#if SANITIZER_INTERCEPT_IOCTL
1218#include "sanitizer_common_interceptors_ioctl.inc"
1219INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
1220  // We need a frame pointer, because we call into ioctl_common_[pre|post] which
1221  // can trigger a report and we need to be able to unwind through this
1222  // function.  On Mac in debug mode we might not have a frame pointer, because
1223  // ioctl_common_[pre|post] doesn't get inlined here.
1224  ENABLE_FRAME_POINTER;
1225
1226  void *ctx;
1227  va_list ap;
1228  va_start(ap, request);
1229  void *arg = va_arg(ap, void *);
1230  va_end(ap);
1231  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
1232
1233  CHECK(ioctl_initialized);
1234
1235  // Note: TSan does not use common flags, and they are zero-initialized.
1236  // This effectively disables ioctl handling in TSan.
1237  if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
1238
1239  // Although request is unsigned long, the rest of the interceptor uses it
1240  // as just "unsigned" to save space, because we know that all values fit in
1241  // "unsigned" - they are compile-time constants.
1242
1243  const ioctl_desc *desc = ioctl_lookup(request);
1244  ioctl_desc decoded_desc;
1245  if (!desc) {
1246    VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
1247    if (!ioctl_decode(request, &decoded_desc))
1248      Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
1249    else
1250      desc = &decoded_desc;
1251  }
1252
1253  if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
1254  int res = REAL(ioctl)(d, request, arg);
1255  // FIXME: some ioctls have different return values for success and failure.
1256  if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
1257  return res;
1258}
1259#define INIT_IOCTL \
1260  ioctl_init();    \
1261  COMMON_INTERCEPT_FUNCTION(ioctl);
1262#else
1263#define INIT_IOCTL
1264#endif
1265
1266#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS || \
1267    SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT || \
1268    SANITIZER_INTERCEPT_GETPWENT_R || SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
1269static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
1270  if (pwd) {
1271    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
1272    if (pwd->pw_name)
1273      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_name,
1274                                          REAL(strlen)(pwd->pw_name) + 1);
1275    if (pwd->pw_passwd)
1276      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_passwd,
1277                                          REAL(strlen)(pwd->pw_passwd) + 1);
1278#if !SANITIZER_ANDROID
1279    if (pwd->pw_gecos)
1280      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_gecos,
1281                                          REAL(strlen)(pwd->pw_gecos) + 1);
1282#endif
1283#if SANITIZER_MAC
1284    if (pwd->pw_class)
1285      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_class,
1286                                          REAL(strlen)(pwd->pw_class) + 1);
1287#endif
1288    if (pwd->pw_dir)
1289      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_dir,
1290                                          REAL(strlen)(pwd->pw_dir) + 1);
1291    if (pwd->pw_shell)
1292      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_shell,
1293                                          REAL(strlen)(pwd->pw_shell) + 1);
1294  }
1295}
1296
1297static void unpoison_group(void *ctx, __sanitizer_group *grp) {
1298  if (grp) {
1299    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
1300    if (grp->gr_name)
1301      COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_name,
1302                                          REAL(strlen)(grp->gr_name) + 1);
1303    if (grp->gr_passwd)
1304      COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_passwd,
1305                                          REAL(strlen)(grp->gr_passwd) + 1);
1306    char **p = grp->gr_mem;
1307    for (; *p; ++p) {
1308      COMMON_INTERCEPTOR_INITIALIZE_RANGE(*p, REAL(strlen)(*p) + 1);
1309    }
1310    COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_mem,
1311                                        (p - grp->gr_mem + 1) * sizeof(*p));
1312  }
1313}
1314#endif  // SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS ||
1315        // SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT ||
1316        // SANITIZER_INTERCEPT_GETPWENT_R ||
1317        // SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
1318
1319#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
1320INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
1321  void *ctx;
1322  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
1323  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1324  __sanitizer_passwd *res = REAL(getpwnam)(name);
1325  if (res) unpoison_passwd(ctx, res);
1326  return res;
1327}
1328INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
1329  void *ctx;
1330  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
1331  __sanitizer_passwd *res = REAL(getpwuid)(uid);
1332  if (res) unpoison_passwd(ctx, res);
1333  return res;
1334}
1335INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
1336  void *ctx;
1337  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
1338  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1339  __sanitizer_group *res = REAL(getgrnam)(name);
1340  if (res) unpoison_group(ctx, res);
1341  return res;
1342}
1343INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
1344  void *ctx;
1345  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
1346  __sanitizer_group *res = REAL(getgrgid)(gid);
1347  if (res) unpoison_group(ctx, res);
1348  return res;
1349}
1350#define INIT_GETPWNAM_AND_FRIENDS      \
1351  COMMON_INTERCEPT_FUNCTION(getpwnam); \
1352  COMMON_INTERCEPT_FUNCTION(getpwuid); \
1353  COMMON_INTERCEPT_FUNCTION(getgrnam); \
1354  COMMON_INTERCEPT_FUNCTION(getgrgid);
1355#else
1356#define INIT_GETPWNAM_AND_FRIENDS
1357#endif
1358
1359#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
1360INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
1361            char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
1362  void *ctx;
1363  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
1364  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1365  // FIXME: under ASan the call below may write to freed memory and corrupt
1366  // its metadata. See
1367  // https://github.com/google/sanitizers/issues/321.
1368  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
1369  if (!res) {
1370    if (result && *result) unpoison_passwd(ctx, *result);
1371    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1372  }
1373  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1374  return res;
1375}
1376INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
1377            SIZE_T buflen, __sanitizer_passwd **result) {
1378  void *ctx;
1379  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
1380  // FIXME: under ASan the call below may write to freed memory and corrupt
1381  // its metadata. See
1382  // https://github.com/google/sanitizers/issues/321.
1383  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
1384  if (!res) {
1385    if (result && *result) unpoison_passwd(ctx, *result);
1386    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1387  }
1388  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1389  return res;
1390}
1391INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
1392            char *buf, SIZE_T buflen, __sanitizer_group **result) {
1393  void *ctx;
1394  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
1395  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1396  // FIXME: under ASan the call below may write to freed memory and corrupt
1397  // its metadata. See
1398  // https://github.com/google/sanitizers/issues/321.
1399  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
1400  if (!res) {
1401    if (result && *result) unpoison_group(ctx, *result);
1402    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1403  }
1404  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1405  return res;
1406}
1407INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
1408            SIZE_T buflen, __sanitizer_group **result) {
1409  void *ctx;
1410  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
1411  // FIXME: under ASan the call below may write to freed memory and corrupt
1412  // its metadata. See
1413  // https://github.com/google/sanitizers/issues/321.
1414  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
1415  if (!res) {
1416    if (result && *result) unpoison_group(ctx, *result);
1417    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1418  }
1419  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1420  return res;
1421}
1422#define INIT_GETPWNAM_R_AND_FRIENDS      \
1423  COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
1424  COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
1425  COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
1426  COMMON_INTERCEPT_FUNCTION(getgrgid_r);
1427#else
1428#define INIT_GETPWNAM_R_AND_FRIENDS
1429#endif
1430
1431#if SANITIZER_INTERCEPT_GETPWENT
1432INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
1433  void *ctx;
1434  COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
1435  __sanitizer_passwd *res = REAL(getpwent)(dummy);
1436  if (res) unpoison_passwd(ctx, res);
1437  return res;
1438}
1439INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
1440  void *ctx;
1441  COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
1442  __sanitizer_group *res = REAL(getgrent)(dummy);
1443  if (res) unpoison_group(ctx, res);;
1444  return res;
1445}
1446#define INIT_GETPWENT                  \
1447  COMMON_INTERCEPT_FUNCTION(getpwent); \
1448  COMMON_INTERCEPT_FUNCTION(getgrent);
1449#else
1450#define INIT_GETPWENT
1451#endif
1452
1453#if SANITIZER_INTERCEPT_FGETPWENT
1454INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
1455  void *ctx;
1456  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
1457  __sanitizer_passwd *res = REAL(fgetpwent)(fp);
1458  if (res) unpoison_passwd(ctx, res);
1459  return res;
1460}
1461INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
1462  void *ctx;
1463  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
1464  __sanitizer_group *res = REAL(fgetgrent)(fp);
1465  if (res) unpoison_group(ctx, res);
1466  return res;
1467}
1468#define INIT_FGETPWENT                  \
1469  COMMON_INTERCEPT_FUNCTION(fgetpwent); \
1470  COMMON_INTERCEPT_FUNCTION(fgetgrent);
1471#else
1472#define INIT_FGETPWENT
1473#endif
1474
1475#if SANITIZER_INTERCEPT_GETPWENT_R
1476INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
1477            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
1478  void *ctx;
1479  COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
1480  // FIXME: under ASan the call below may write to freed memory and corrupt
1481  // its metadata. See
1482  // https://github.com/google/sanitizers/issues/321.
1483  int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
1484  if (!res) {
1485    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
1486    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1487  }
1488  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
1489  return res;
1490}
1491INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
1492            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
1493  void *ctx;
1494  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
1495  // FIXME: under ASan the call below may write to freed memory and corrupt
1496  // its metadata. See
1497  // https://github.com/google/sanitizers/issues/321.
1498  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
1499  if (!res) {
1500    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
1501    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1502  }
1503  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
1504  return res;
1505}
1506INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
1507            __sanitizer_group **pwbufp) {
1508  void *ctx;
1509  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
1510  // FIXME: under ASan the call below may write to freed memory and corrupt
1511  // its metadata. See
1512  // https://github.com/google/sanitizers/issues/321.
1513  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
1514  if (!res) {
1515    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
1516    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1517  }
1518  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
1519  return res;
1520}
1521INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
1522            SIZE_T buflen, __sanitizer_group **pwbufp) {
1523  void *ctx;
1524  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
1525  // FIXME: under ASan the call below may write to freed memory and corrupt
1526  // its metadata. See
1527  // https://github.com/google/sanitizers/issues/321.
1528  int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
1529  if (!res) {
1530    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
1531    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
1532  }
1533  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
1534  return res;
1535}
1536#define INIT_GETPWENT_R                   \
1537  COMMON_INTERCEPT_FUNCTION(getpwent_r);  \
1538  COMMON_INTERCEPT_FUNCTION(fgetpwent_r); \
1539  COMMON_INTERCEPT_FUNCTION(getgrent_r);  \
1540  COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
1541#else
1542#define INIT_GETPWENT_R
1543#endif
1544
1545#if SANITIZER_INTERCEPT_SETPWENT
1546// The only thing these interceptors do is disable any nested interceptors.
1547// These functions may open nss modules and call uninstrumented functions from
1548// them, and we don't want things like strlen() to trigger.
1549INTERCEPTOR(void, setpwent, int dummy) {
1550  void *ctx;
1551  COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
1552  REAL(setpwent)(dummy);
1553}
1554INTERCEPTOR(void, endpwent, int dummy) {
1555  void *ctx;
1556  COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
1557  REAL(endpwent)(dummy);
1558}
1559INTERCEPTOR(void, setgrent, int dummy) {
1560  void *ctx;
1561  COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
1562  REAL(setgrent)(dummy);
1563}
1564INTERCEPTOR(void, endgrent, int dummy) {
1565  void *ctx;
1566  COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
1567  REAL(endgrent)(dummy);
1568}
1569#define INIT_SETPWENT                  \
1570  COMMON_INTERCEPT_FUNCTION(setpwent); \
1571  COMMON_INTERCEPT_FUNCTION(endpwent); \
1572  COMMON_INTERCEPT_FUNCTION(setgrent); \
1573  COMMON_INTERCEPT_FUNCTION(endgrent);
1574#else
1575#define INIT_SETPWENT
1576#endif
1577
1578#if SANITIZER_INTERCEPT_CLOCK_GETTIME
1579INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
1580  void *ctx;
1581  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
1582  // FIXME: under ASan the call below may write to freed memory and corrupt
1583  // its metadata. See
1584  // https://github.com/google/sanitizers/issues/321.
1585  int res = REAL(clock_getres)(clk_id, tp);
1586  if (!res && tp) {
1587    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
1588  }
1589  return res;
1590}
1591INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
1592  void *ctx;
1593  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
1594  // FIXME: under ASan the call below may write to freed memory and corrupt
1595  // its metadata. See
1596  // https://github.com/google/sanitizers/issues/321.
1597  int res = REAL(clock_gettime)(clk_id, tp);
1598  if (!res) {
1599    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
1600  }
1601  return res;
1602}
1603INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
1604  void *ctx;
1605  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
1606  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
1607  return REAL(clock_settime)(clk_id, tp);
1608}
1609#define INIT_CLOCK_GETTIME                  \
1610  COMMON_INTERCEPT_FUNCTION(clock_getres);  \
1611  COMMON_INTERCEPT_FUNCTION(clock_gettime); \
1612  COMMON_INTERCEPT_FUNCTION(clock_settime);
1613#else
1614#define INIT_CLOCK_GETTIME
1615#endif
1616
1617#if SANITIZER_INTERCEPT_GETITIMER
1618INTERCEPTOR(int, getitimer, int which, void *curr_value) {
1619  void *ctx;
1620  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
1621  // FIXME: under ASan the call below may write to freed memory and corrupt
1622  // its metadata. See
1623  // https://github.com/google/sanitizers/issues/321.
1624  int res = REAL(getitimer)(which, curr_value);
1625  if (!res && curr_value) {
1626    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
1627  }
1628  return res;
1629}
1630INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
1631  void *ctx;
1632  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
1633  if (new_value)
1634    COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
1635  // FIXME: under ASan the call below may write to freed memory and corrupt
1636  // its metadata. See
1637  // https://github.com/google/sanitizers/issues/321.
1638  int res = REAL(setitimer)(which, new_value, old_value);
1639  if (!res && old_value) {
1640    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
1641  }
1642  return res;
1643}
1644#define INIT_GETITIMER                  \
1645  COMMON_INTERCEPT_FUNCTION(getitimer); \
1646  COMMON_INTERCEPT_FUNCTION(setitimer);
1647#else
1648#define INIT_GETITIMER
1649#endif
1650
1651#if SANITIZER_INTERCEPT_GLOB
1652static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
1653  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
1654  // +1 for NULL pointer at the end.
1655  if (pglob->gl_pathv)
1656    COMMON_INTERCEPTOR_WRITE_RANGE(
1657        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
1658  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
1659    char *p = pglob->gl_pathv[i];
1660    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
1661  }
1662}
1663
1664static THREADLOCAL __sanitizer_glob_t *pglob_copy;
1665
1666static void wrapped_gl_closedir(void *dir) {
1667  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
1668  pglob_copy->gl_closedir(dir);
1669}
1670
1671static void *wrapped_gl_readdir(void *dir) {
1672  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
1673  return pglob_copy->gl_readdir(dir);
1674}
1675
1676static void *wrapped_gl_opendir(const char *s) {
1677  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
1678  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
1679  return pglob_copy->gl_opendir(s);
1680}
1681
1682static int wrapped_gl_lstat(const char *s, void *st) {
1683  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
1684  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
1685  return pglob_copy->gl_lstat(s, st);
1686}
1687
1688static int wrapped_gl_stat(const char *s, void *st) {
1689  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
1690  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
1691  return pglob_copy->gl_stat(s, st);
1692}
1693
1694static const __sanitizer_glob_t kGlobCopy = {
1695      0,                  0,                   0,
1696      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
1697      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
1698
1699INTERCEPTOR(int, glob, const char *pattern, int flags,
1700            int (*errfunc)(const char *epath, int eerrno),
1701            __sanitizer_glob_t *pglob) {
1702  void *ctx;
1703  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
1704  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
1705  __sanitizer_glob_t glob_copy;
1706  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
1707  if (flags & glob_altdirfunc) {
1708    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
1709    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
1710    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
1711    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
1712    Swap(pglob->gl_stat, glob_copy.gl_stat);
1713    pglob_copy = &glob_copy;
1714  }
1715  int res = REAL(glob)(pattern, flags, errfunc, pglob);
1716  if (flags & glob_altdirfunc) {
1717    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
1718    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
1719    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
1720    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
1721    Swap(pglob->gl_stat, glob_copy.gl_stat);
1722  }
1723  pglob_copy = 0;
1724  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
1725  return res;
1726}
1727
1728INTERCEPTOR(int, glob64, const char *pattern, int flags,
1729            int (*errfunc)(const char *epath, int eerrno),
1730            __sanitizer_glob_t *pglob) {
1731  void *ctx;
1732  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
1733  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
1734  __sanitizer_glob_t glob_copy;
1735  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
1736  if (flags & glob_altdirfunc) {
1737    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
1738    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
1739    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
1740    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
1741    Swap(pglob->gl_stat, glob_copy.gl_stat);
1742    pglob_copy = &glob_copy;
1743  }
1744  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
1745  if (flags & glob_altdirfunc) {
1746    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
1747    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
1748    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
1749    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
1750    Swap(pglob->gl_stat, glob_copy.gl_stat);
1751  }
1752  pglob_copy = 0;
1753  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
1754  return res;
1755}
1756#define INIT_GLOB                  \
1757  COMMON_INTERCEPT_FUNCTION(glob); \
1758  COMMON_INTERCEPT_FUNCTION(glob64);
1759#else  // SANITIZER_INTERCEPT_GLOB
1760#define INIT_GLOB
1761#endif  // SANITIZER_INTERCEPT_GLOB
1762
1763#if SANITIZER_INTERCEPT_WAIT
1764// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
1765// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
1766// details.
1767INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
1768  void *ctx;
1769  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
1770  // FIXME: under ASan the call below may write to freed memory and corrupt
1771  // its metadata. See
1772  // https://github.com/google/sanitizers/issues/321.
1773  int res = REAL(wait)(status);
1774  if (res != -1 && status)
1775    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
1776  return res;
1777}
1778// On FreeBSD id_t is always 64-bit wide.
1779#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
1780INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
1781                        int options) {
1782#else
1783INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
1784                        int options) {
1785#endif
1786  void *ctx;
1787  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
1788  // FIXME: under ASan the call below may write to freed memory and corrupt
1789  // its metadata. See
1790  // https://github.com/google/sanitizers/issues/321.
1791  int res = REAL(waitid)(idtype, id, infop, options);
1792  if (res != -1 && infop)
1793    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
1794  return res;
1795}
1796INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
1797  void *ctx;
1798  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
1799  // FIXME: under ASan the call below may write to freed memory and corrupt
1800  // its metadata. See
1801  // https://github.com/google/sanitizers/issues/321.
1802  int res = REAL(waitpid)(pid, status, options);
1803  if (res != -1 && status)
1804    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
1805  return res;
1806}
1807INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
1808  void *ctx;
1809  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
1810  // FIXME: under ASan the call below may write to freed memory and corrupt
1811  // its metadata. See
1812  // https://github.com/google/sanitizers/issues/321.
1813  int res = REAL(wait3)(status, options, rusage);
1814  if (res != -1) {
1815    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
1816    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
1817  }
1818  return res;
1819}
1820#if SANITIZER_ANDROID
1821INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
1822  void *ctx;
1823  COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
1824  // FIXME: under ASan the call below may write to freed memory and corrupt
1825  // its metadata. See
1826  // https://github.com/google/sanitizers/issues/321.
1827  int res = REAL(__wait4)(pid, status, options, rusage);
1828  if (res != -1) {
1829    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
1830    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
1831  }
1832  return res;
1833}
1834#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
1835#else
1836INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
1837  void *ctx;
1838  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
1839  // FIXME: under ASan the call below may write to freed memory and corrupt
1840  // its metadata. See
1841  // https://github.com/google/sanitizers/issues/321.
1842  int res = REAL(wait4)(pid, status, options, rusage);
1843  if (res != -1) {
1844    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
1845    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
1846  }
1847  return res;
1848}
1849#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
1850#endif  // SANITIZER_ANDROID
1851#define INIT_WAIT                     \
1852  COMMON_INTERCEPT_FUNCTION(wait);    \
1853  COMMON_INTERCEPT_FUNCTION(waitid);  \
1854  COMMON_INTERCEPT_FUNCTION(waitpid); \
1855  COMMON_INTERCEPT_FUNCTION(wait3);
1856#else
1857#define INIT_WAIT
1858#define INIT_WAIT4
1859#endif
1860
1861#if SANITIZER_INTERCEPT_INET
1862INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
1863  void *ctx;
1864  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
1865  uptr sz = __sanitizer_in_addr_sz(af);
1866  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
1867  // FIXME: figure out read size based on the address family.
1868  // FIXME: under ASan the call below may write to freed memory and corrupt
1869  // its metadata. See
1870  // https://github.com/google/sanitizers/issues/321.
1871  char *res = REAL(inet_ntop)(af, src, dst, size);
1872  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1873  return res;
1874}
1875INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
1876  void *ctx;
1877  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
1878  COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
1879  // FIXME: figure out read size based on the address family.
1880  // FIXME: under ASan the call below may write to freed memory and corrupt
1881  // its metadata. See
1882  // https://github.com/google/sanitizers/issues/321.
1883  int res = REAL(inet_pton)(af, src, dst);
1884  if (res == 1) {
1885    uptr sz = __sanitizer_in_addr_sz(af);
1886    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
1887  }
1888  return res;
1889}
1890#define INIT_INET                       \
1891  COMMON_INTERCEPT_FUNCTION(inet_ntop); \
1892  COMMON_INTERCEPT_FUNCTION(inet_pton);
1893#else
1894#define INIT_INET
1895#endif
1896
1897#if SANITIZER_INTERCEPT_INET
1898INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
1899  void *ctx;
1900  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
1901  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
1902  // FIXME: under ASan the call below may write to freed memory and corrupt
1903  // its metadata. See
1904  // https://github.com/google/sanitizers/issues/321.
1905  int res = REAL(inet_aton)(cp, dst);
1906  if (res != 0) {
1907    uptr sz = __sanitizer_in_addr_sz(af_inet);
1908    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
1909  }
1910  return res;
1911}
1912#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
1913#else
1914#define INIT_INET_ATON
1915#endif
1916
1917#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
1918INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
1919  void *ctx;
1920  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
1921  // FIXME: under ASan the call below may write to freed memory and corrupt
1922  // its metadata. See
1923  // https://github.com/google/sanitizers/issues/321.
1924  int res = REAL(pthread_getschedparam)(thread, policy, param);
1925  if (res == 0) {
1926    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
1927    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
1928  }
1929  return res;
1930}
1931#define INIT_PTHREAD_GETSCHEDPARAM \
1932  COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
1933#else
1934#define INIT_PTHREAD_GETSCHEDPARAM
1935#endif
1936
1937#if SANITIZER_INTERCEPT_GETADDRINFO
1938INTERCEPTOR(int, getaddrinfo, char *node, char *service,
1939            struct __sanitizer_addrinfo *hints,
1940            struct __sanitizer_addrinfo **out) {
1941  void *ctx;
1942  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
1943  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
1944  if (service)
1945    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
1946  if (hints)
1947    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
1948  // FIXME: under ASan the call below may write to freed memory and corrupt
1949  // its metadata. See
1950  // https://github.com/google/sanitizers/issues/321.
1951  int res = REAL(getaddrinfo)(node, service, hints, out);
1952  if (res == 0 && out) {
1953    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
1954    struct __sanitizer_addrinfo *p = *out;
1955    while (p) {
1956      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
1957      if (p->ai_addr)
1958        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
1959      if (p->ai_canonname)
1960        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
1961                                       REAL(strlen)(p->ai_canonname) + 1);
1962      p = p->ai_next;
1963    }
1964  }
1965  return res;
1966}
1967#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
1968#else
1969#define INIT_GETADDRINFO
1970#endif
1971
1972#if SANITIZER_INTERCEPT_GETNAMEINFO
1973INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
1974            unsigned hostlen, char *serv, unsigned servlen, int flags) {
1975  void *ctx;
1976  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
1977                           serv, servlen, flags);
1978  // FIXME: consider adding READ_RANGE(sockaddr, salen)
1979  // There is padding in in_addr that may make this too noisy
1980  // FIXME: under ASan the call below may write to freed memory and corrupt
1981  // its metadata. See
1982  // https://github.com/google/sanitizers/issues/321.
1983  int res =
1984      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
1985  if (res == 0) {
1986    if (host && hostlen)
1987      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
1988    if (serv && servlen)
1989      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
1990  }
1991  return res;
1992}
1993#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
1994#else
1995#define INIT_GETNAMEINFO
1996#endif
1997
1998#if SANITIZER_INTERCEPT_GETSOCKNAME
1999INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
2000  void *ctx;
2001  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
2002  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2003  int addrlen_in = *addrlen;
2004  // FIXME: under ASan the call below may write to freed memory and corrupt
2005  // its metadata. See
2006  // https://github.com/google/sanitizers/issues/321.
2007  int res = REAL(getsockname)(sock_fd, addr, addrlen);
2008  if (res == 0) {
2009    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
2010  }
2011  return res;
2012}
2013#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
2014#else
2015#define INIT_GETSOCKNAME
2016#endif
2017
2018#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
2019static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
2020  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
2021  if (h->h_name)
2022    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
2023  char **p = h->h_aliases;
2024  while (*p) {
2025    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
2026    ++p;
2027  }
2028  COMMON_INTERCEPTOR_WRITE_RANGE(
2029      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
2030  p = h->h_addr_list;
2031  while (*p) {
2032    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
2033    ++p;
2034  }
2035  COMMON_INTERCEPTOR_WRITE_RANGE(
2036      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
2037}
2038#endif
2039
2040#if SANITIZER_INTERCEPT_GETHOSTBYNAME
2041INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
2042  void *ctx;
2043  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
2044  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
2045  if (res) write_hostent(ctx, res);
2046  return res;
2047}
2048
2049INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
2050            int type) {
2051  void *ctx;
2052  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
2053  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
2054  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
2055  if (res) write_hostent(ctx, res);
2056  return res;
2057}
2058
2059INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
2060  void *ctx;
2061  COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
2062  struct __sanitizer_hostent *res = REAL(gethostent)(fake);
2063  if (res) write_hostent(ctx, res);
2064  return res;
2065}
2066
2067INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
2068  void *ctx;
2069  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
2070  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
2071  if (res) write_hostent(ctx, res);
2072  return res;
2073}
2074#define INIT_GETHOSTBYNAME                  \
2075  COMMON_INTERCEPT_FUNCTION(gethostent);    \
2076  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
2077  COMMON_INTERCEPT_FUNCTION(gethostbyname); \
2078  COMMON_INTERCEPT_FUNCTION(gethostbyname2);
2079#else
2080#define INIT_GETHOSTBYNAME
2081#endif
2082
2083#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
2084INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
2085            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
2086            int *h_errnop) {
2087  void *ctx;
2088  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
2089                           h_errnop);
2090  // FIXME: under ASan the call below may write to freed memory and corrupt
2091  // its metadata. See
2092  // https://github.com/google/sanitizers/issues/321.
2093  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
2094  if (result) {
2095    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2096    if (res == 0 && *result) write_hostent(ctx, *result);
2097  }
2098  if (h_errnop)
2099    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2100  return res;
2101}
2102#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
2103#else
2104#define INIT_GETHOSTBYNAME_R
2105#endif
2106
2107#if SANITIZER_INTERCEPT_GETHOSTENT_R
2108INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
2109            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
2110  void *ctx;
2111  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
2112                           h_errnop);
2113  // FIXME: under ASan the call below may write to freed memory and corrupt
2114  // its metadata. See
2115  // https://github.com/google/sanitizers/issues/321.
2116  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
2117  if (result) {
2118    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2119    if (res == 0 && *result) write_hostent(ctx, *result);
2120  }
2121  if (h_errnop)
2122    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2123  return res;
2124}
2125#define INIT_GETHOSTENT_R                  \
2126  COMMON_INTERCEPT_FUNCTION(gethostent_r);
2127#else
2128#define INIT_GETHOSTENT_R
2129#endif
2130
2131#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
2132INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
2133            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
2134            __sanitizer_hostent **result, int *h_errnop) {
2135  void *ctx;
2136  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
2137                           buflen, result, h_errnop);
2138  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
2139  // FIXME: under ASan the call below may write to freed memory and corrupt
2140  // its metadata. See
2141  // https://github.com/google/sanitizers/issues/321.
2142  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
2143                                  h_errnop);
2144  if (result) {
2145    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2146    if (res == 0 && *result) write_hostent(ctx, *result);
2147  }
2148  if (h_errnop)
2149    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2150  return res;
2151}
2152#define INIT_GETHOSTBYADDR_R                  \
2153  COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
2154#else
2155#define INIT_GETHOSTBYADDR_R
2156#endif
2157
2158#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
2159INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
2160            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
2161            __sanitizer_hostent **result, int *h_errnop) {
2162  void *ctx;
2163  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
2164                           result, h_errnop);
2165  // FIXME: under ASan the call below may write to freed memory and corrupt
2166  // its metadata. See
2167  // https://github.com/google/sanitizers/issues/321.
2168  int res =
2169      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
2170  if (result) {
2171    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2172    if (res == 0 && *result) write_hostent(ctx, *result);
2173  }
2174  if (h_errnop)
2175    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2176  return res;
2177}
2178#define INIT_GETHOSTBYNAME2_R                  \
2179  COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
2180#else
2181#define INIT_GETHOSTBYNAME2_R
2182#endif
2183
2184#if SANITIZER_INTERCEPT_GETSOCKOPT
2185INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
2186            int *optlen) {
2187  void *ctx;
2188  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
2189                           optlen);
2190  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
2191  // FIXME: under ASan the call below may write to freed memory and corrupt
2192  // its metadata. See
2193  // https://github.com/google/sanitizers/issues/321.
2194  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
2195  if (res == 0)
2196    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
2197  return res;
2198}
2199#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
2200#else
2201#define INIT_GETSOCKOPT
2202#endif
2203
2204#if SANITIZER_INTERCEPT_ACCEPT
2205INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
2206  void *ctx;
2207  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
2208  unsigned addrlen0 = 0;
2209  if (addrlen) {
2210    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2211    addrlen0 = *addrlen;
2212  }
2213  int fd2 = REAL(accept)(fd, addr, addrlen);
2214  if (fd2 >= 0) {
2215    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
2216    if (addr && addrlen)
2217      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
2218  }
2219  return fd2;
2220}
2221#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
2222#else
2223#define INIT_ACCEPT
2224#endif
2225
2226#if SANITIZER_INTERCEPT_ACCEPT4
2227INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
2228  void *ctx;
2229  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
2230  unsigned addrlen0 = 0;
2231  if (addrlen) {
2232    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2233    addrlen0 = *addrlen;
2234  }
2235  // FIXME: under ASan the call below may write to freed memory and corrupt
2236  // its metadata. See
2237  // https://github.com/google/sanitizers/issues/321.
2238  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
2239  if (fd2 >= 0) {
2240    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
2241    if (addr && addrlen)
2242      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
2243  }
2244  return fd2;
2245}
2246#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
2247#else
2248#define INIT_ACCEPT4
2249#endif
2250
2251#if SANITIZER_INTERCEPT_MODF
2252INTERCEPTOR(double, modf, double x, double *iptr) {
2253  void *ctx;
2254  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
2255  // FIXME: under ASan the call below may write to freed memory and corrupt
2256  // its metadata. See
2257  // https://github.com/google/sanitizers/issues/321.
2258  double res = REAL(modf)(x, iptr);
2259  if (iptr) {
2260    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
2261  }
2262  return res;
2263}
2264INTERCEPTOR(float, modff, float x, float *iptr) {
2265  void *ctx;
2266  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
2267  // FIXME: under ASan the call below may write to freed memory and corrupt
2268  // its metadata. See
2269  // https://github.com/google/sanitizers/issues/321.
2270  float res = REAL(modff)(x, iptr);
2271  if (iptr) {
2272    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
2273  }
2274  return res;
2275}
2276INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
2277  void *ctx;
2278  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
2279  // FIXME: under ASan the call below may write to freed memory and corrupt
2280  // its metadata. See
2281  // https://github.com/google/sanitizers/issues/321.
2282  long double res = REAL(modfl)(x, iptr);
2283  if (iptr) {
2284    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
2285  }
2286  return res;
2287}
2288#define INIT_MODF                   \
2289  COMMON_INTERCEPT_FUNCTION(modf);  \
2290  COMMON_INTERCEPT_FUNCTION(modff); \
2291  COMMON_INTERCEPT_FUNCTION(modfl);
2292#else
2293#define INIT_MODF
2294#endif
2295
2296#if SANITIZER_INTERCEPT_RECVMSG
2297static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
2298                         SSIZE_T maxlen) {
2299  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
2300  if (msg->msg_name && msg->msg_namelen)
2301    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
2302  if (msg->msg_iov && msg->msg_iovlen)
2303    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
2304                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
2305  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
2306  if (msg->msg_control && msg->msg_controllen)
2307    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
2308}
2309
2310INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
2311            int flags) {
2312  void *ctx;
2313  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
2314  // FIXME: under ASan the call below may write to freed memory and corrupt
2315  // its metadata. See
2316  // https://github.com/google/sanitizers/issues/321.
2317  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
2318  if (res >= 0) {
2319    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
2320    if (msg) {
2321      write_msghdr(ctx, msg, res);
2322      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
2323    }
2324  }
2325  return res;
2326}
2327#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
2328#else
2329#define INIT_RECVMSG
2330#endif
2331
2332#if SANITIZER_INTERCEPT_GETPEERNAME
2333INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
2334  void *ctx;
2335  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
2336  unsigned addr_sz;
2337  if (addrlen) addr_sz = *addrlen;
2338  // FIXME: under ASan the call below may write to freed memory and corrupt
2339  // its metadata. See
2340  // https://github.com/google/sanitizers/issues/321.
2341  int res = REAL(getpeername)(sockfd, addr, addrlen);
2342  if (!res && addr && addrlen)
2343    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
2344  return res;
2345}
2346#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
2347#else
2348#define INIT_GETPEERNAME
2349#endif
2350
2351#if SANITIZER_INTERCEPT_SYSINFO
2352INTERCEPTOR(int, sysinfo, void *info) {
2353  void *ctx;
2354  // FIXME: under ASan the call below may write to freed memory and corrupt
2355  // its metadata. See
2356  // https://github.com/google/sanitizers/issues/321.
2357  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
2358  int res = REAL(sysinfo)(info);
2359  if (!res && info)
2360    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
2361  return res;
2362}
2363#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
2364#else
2365#define INIT_SYSINFO
2366#endif
2367
2368#if SANITIZER_INTERCEPT_READDIR
2369INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
2370  void *ctx;
2371  COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
2372  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2373  __sanitizer_dirent *res = REAL(opendir)(path);
2374  if (res)
2375    COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
2376  return res;
2377}
2378
2379INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
2380  void *ctx;
2381  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
2382  // FIXME: under ASan the call below may write to freed memory and corrupt
2383  // its metadata. See
2384  // https://github.com/google/sanitizers/issues/321.
2385  __sanitizer_dirent *res = REAL(readdir)(dirp);
2386  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
2387  return res;
2388}
2389
2390INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
2391            __sanitizer_dirent **result) {
2392  void *ctx;
2393  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
2394  // FIXME: under ASan the call below may write to freed memory and corrupt
2395  // its metadata. See
2396  // https://github.com/google/sanitizers/issues/321.
2397  int res = REAL(readdir_r)(dirp, entry, result);
2398  if (!res) {
2399    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2400    if (*result)
2401      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
2402  }
2403  return res;
2404}
2405
2406#define INIT_READDIR                  \
2407  COMMON_INTERCEPT_FUNCTION(opendir); \
2408  COMMON_INTERCEPT_FUNCTION(readdir); \
2409  COMMON_INTERCEPT_FUNCTION(readdir_r);
2410#else
2411#define INIT_READDIR
2412#endif
2413
2414#if SANITIZER_INTERCEPT_READDIR64
2415INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
2416  void *ctx;
2417  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
2418  // FIXME: under ASan the call below may write to freed memory and corrupt
2419  // its metadata. See
2420  // https://github.com/google/sanitizers/issues/321.
2421  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
2422  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
2423  return res;
2424}
2425
2426INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
2427            __sanitizer_dirent64 **result) {
2428  void *ctx;
2429  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
2430  // FIXME: under ASan the call below may write to freed memory and corrupt
2431  // its metadata. See
2432  // https://github.com/google/sanitizers/issues/321.
2433  int res = REAL(readdir64_r)(dirp, entry, result);
2434  if (!res) {
2435    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2436    if (*result)
2437      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
2438  }
2439  return res;
2440}
2441#define INIT_READDIR64                  \
2442  COMMON_INTERCEPT_FUNCTION(readdir64); \
2443  COMMON_INTERCEPT_FUNCTION(readdir64_r);
2444#else
2445#define INIT_READDIR64
2446#endif
2447
2448#if SANITIZER_INTERCEPT_PTRACE
2449INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
2450  void *ctx;
2451  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
2452  __sanitizer_iovec local_iovec;
2453
2454  if (data) {
2455    if (request == ptrace_setregs)
2456      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
2457    else if (request == ptrace_setfpregs)
2458      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
2459    else if (request == ptrace_setfpxregs)
2460      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
2461    else if (request == ptrace_setvfpregs)
2462      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
2463    else if (request == ptrace_setsiginfo)
2464      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
2465    // Some kernel might zero the iovec::iov_base in case of invalid
2466    // write access.  In this case copy the invalid address for further
2467    // inspection.
2468    else if (request == ptrace_setregset || request == ptrace_getregset) {
2469      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
2470      COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
2471      local_iovec = *iovec;
2472      if (request == ptrace_setregset)
2473        COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
2474    }
2475  }
2476
2477  // FIXME: under ASan the call below may write to freed memory and corrupt
2478  // its metadata. See
2479  // https://github.com/google/sanitizers/issues/321.
2480  uptr res = REAL(ptrace)(request, pid, addr, data);
2481
2482  if (!res && data) {
2483    // Note that PEEK* requests assign different meaning to the return value.
2484    // This function does not handle them (nor does it need to).
2485    if (request == ptrace_getregs)
2486      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
2487    else if (request == ptrace_getfpregs)
2488      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
2489    else if (request == ptrace_getfpxregs)
2490      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
2491    else if (request == ptrace_getvfpregs)
2492      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
2493    else if (request == ptrace_getsiginfo)
2494      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
2495    else if (request == ptrace_geteventmsg)
2496      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
2497    else if (request == ptrace_getregset) {
2498      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
2499      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
2500      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
2501                                     local_iovec.iov_len);
2502    }
2503  }
2504  return res;
2505}
2506
2507#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
2508#else
2509#define INIT_PTRACE
2510#endif
2511
2512#if SANITIZER_INTERCEPT_SETLOCALE
2513INTERCEPTOR(char *, setlocale, int category, char *locale) {
2514  void *ctx;
2515  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
2516  if (locale)
2517    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
2518  char *res = REAL(setlocale)(category, locale);
2519  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2520  return res;
2521}
2522
2523#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
2524#else
2525#define INIT_SETLOCALE
2526#endif
2527
2528#if SANITIZER_INTERCEPT_GETCWD
2529INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
2530  void *ctx;
2531  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
2532  // FIXME: under ASan the call below may write to freed memory and corrupt
2533  // its metadata. See
2534  // https://github.com/google/sanitizers/issues/321.
2535  char *res = REAL(getcwd)(buf, size);
2536  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2537  return res;
2538}
2539#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
2540#else
2541#define INIT_GETCWD
2542#endif
2543
2544#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
2545INTERCEPTOR(char *, get_current_dir_name, int fake) {
2546  void *ctx;
2547  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
2548  // FIXME: under ASan the call below may write to freed memory and corrupt
2549  // its metadata. See
2550  // https://github.com/google/sanitizers/issues/321.
2551  char *res = REAL(get_current_dir_name)(fake);
2552  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2553  return res;
2554}
2555
2556#define INIT_GET_CURRENT_DIR_NAME \
2557  COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
2558#else
2559#define INIT_GET_CURRENT_DIR_NAME
2560#endif
2561
2562UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
2563  CHECK(endptr);
2564  if (nptr == *endptr) {
2565    // No digits were found at strtol call, we need to find out the last
2566    // symbol accessed by strtoll on our own.
2567    // We get this symbol by skipping leading blanks and optional +/- sign.
2568    while (IsSpace(*nptr)) nptr++;
2569    if (*nptr == '+' || *nptr == '-') nptr++;
2570    *endptr = const_cast<char *>(nptr);
2571  }
2572  CHECK(*endptr >= nptr);
2573}
2574
2575UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
2576                             char **endptr, char *real_endptr, int base) {
2577  if (endptr) {
2578    *endptr = real_endptr;
2579    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
2580  }
2581  // If base has unsupported value, strtol can exit with EINVAL
2582  // without reading any characters. So do additional checks only
2583  // if base is valid.
2584  bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
2585  if (is_valid_base) {
2586    FixRealStrtolEndptr(nptr, &real_endptr);
2587  }
2588  COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
2589                                 (real_endptr - nptr) + 1 : 0);
2590}
2591
2592
2593#if SANITIZER_INTERCEPT_STRTOIMAX
2594INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
2595  void *ctx;
2596  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
2597  // FIXME: under ASan the call below may write to freed memory and corrupt
2598  // its metadata. See
2599  // https://github.com/google/sanitizers/issues/321.
2600  char *real_endptr;
2601  INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
2602  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
2603  return res;
2604}
2605
2606INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
2607  void *ctx;
2608  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
2609  // FIXME: under ASan the call below may write to freed memory and corrupt
2610  // its metadata. See
2611  // https://github.com/google/sanitizers/issues/321.
2612  char *real_endptr;
2613  INTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
2614  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
2615  return res;
2616}
2617
2618#define INIT_STRTOIMAX                  \
2619  COMMON_INTERCEPT_FUNCTION(strtoimax); \
2620  COMMON_INTERCEPT_FUNCTION(strtoumax);
2621#else
2622#define INIT_STRTOIMAX
2623#endif
2624
2625#if SANITIZER_INTERCEPT_MBSTOWCS
2626INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
2627  void *ctx;
2628  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
2629  // FIXME: under ASan the call below may write to freed memory and corrupt
2630  // its metadata. See
2631  // https://github.com/google/sanitizers/issues/321.
2632  SIZE_T res = REAL(mbstowcs)(dest, src, len);
2633  if (res != (SIZE_T) - 1 && dest) {
2634    SIZE_T write_cnt = res + (res < len);
2635    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
2636  }
2637  return res;
2638}
2639
2640INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
2641            void *ps) {
2642  void *ctx;
2643  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
2644  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
2645  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
2646  // FIXME: under ASan the call below may write to freed memory and corrupt
2647  // its metadata. See
2648  // https://github.com/google/sanitizers/issues/321.
2649  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
2650  if (res != (SIZE_T)(-1) && dest && src) {
2651    // This function, and several others, may or may not write the terminating
2652    // \0 character. They write it iff they clear *src.
2653    SIZE_T write_cnt = res + !*src;
2654    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
2655  }
2656  return res;
2657}
2658
2659#define INIT_MBSTOWCS                  \
2660  COMMON_INTERCEPT_FUNCTION(mbstowcs); \
2661  COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
2662#else
2663#define INIT_MBSTOWCS
2664#endif
2665
2666#if SANITIZER_INTERCEPT_MBSNRTOWCS
2667INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
2668            SIZE_T len, void *ps) {
2669  void *ctx;
2670  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
2671  if (src) {
2672    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
2673    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
2674  }
2675  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
2676  // FIXME: under ASan the call below may write to freed memory and corrupt
2677  // its metadata. See
2678  // https://github.com/google/sanitizers/issues/321.
2679  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
2680  if (res != (SIZE_T)(-1) && dest && src) {
2681    SIZE_T write_cnt = res + !*src;
2682    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
2683  }
2684  return res;
2685}
2686
2687#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
2688#else
2689#define INIT_MBSNRTOWCS
2690#endif
2691
2692#if SANITIZER_INTERCEPT_WCSTOMBS
2693INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
2694  void *ctx;
2695  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
2696  // FIXME: under ASan the call below may write to freed memory and corrupt
2697  // its metadata. See
2698  // https://github.com/google/sanitizers/issues/321.
2699  SIZE_T res = REAL(wcstombs)(dest, src, len);
2700  if (res != (SIZE_T) - 1 && dest) {
2701    SIZE_T write_cnt = res + (res < len);
2702    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
2703  }
2704  return res;
2705}
2706
2707INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
2708            void *ps) {
2709  void *ctx;
2710  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
2711  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
2712  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
2713  // FIXME: under ASan the call below may write to freed memory and corrupt
2714  // its metadata. See
2715  // https://github.com/google/sanitizers/issues/321.
2716  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
2717  if (res != (SIZE_T) - 1 && dest && src) {
2718    SIZE_T write_cnt = res + !*src;
2719    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
2720  }
2721  return res;
2722}
2723
2724#define INIT_WCSTOMBS                  \
2725  COMMON_INTERCEPT_FUNCTION(wcstombs); \
2726  COMMON_INTERCEPT_FUNCTION(wcsrtombs);
2727#else
2728#define INIT_WCSTOMBS
2729#endif
2730
2731#if SANITIZER_INTERCEPT_WCSNRTOMBS
2732INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
2733            SIZE_T len, void *ps) {
2734  void *ctx;
2735  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
2736  if (src) {
2737    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
2738    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
2739  }
2740  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
2741  // FIXME: under ASan the call below may write to freed memory and corrupt
2742  // its metadata. See
2743  // https://github.com/google/sanitizers/issues/321.
2744  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
2745  if (res != ((SIZE_T)-1) && dest && src) {
2746    SIZE_T write_cnt = res + !*src;
2747    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
2748  }
2749  return res;
2750}
2751
2752#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
2753#else
2754#define INIT_WCSNRTOMBS
2755#endif
2756
2757
2758#if SANITIZER_INTERCEPT_WCRTOMB
2759INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
2760  void *ctx;
2761  COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
2762  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
2763  // FIXME: under ASan the call below may write to freed memory and corrupt
2764  // its metadata. See
2765  // https://github.com/google/sanitizers/issues/321.
2766  SIZE_T res = REAL(wcrtomb)(dest, src, ps);
2767  if (res != ((SIZE_T)-1) && dest) {
2768    SIZE_T write_cnt = res;
2769    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
2770  }
2771  return res;
2772}
2773
2774#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
2775#else
2776#define INIT_WCRTOMB
2777#endif
2778
2779#if SANITIZER_INTERCEPT_TCGETATTR
2780INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
2781  void *ctx;
2782  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
2783  // FIXME: under ASan the call below may write to freed memory and corrupt
2784  // its metadata. See
2785  // https://github.com/google/sanitizers/issues/321.
2786  int res = REAL(tcgetattr)(fd, termios_p);
2787  if (!res && termios_p)
2788    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
2789  return res;
2790}
2791
2792#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
2793#else
2794#define INIT_TCGETATTR
2795#endif
2796
2797#if SANITIZER_INTERCEPT_REALPATH
2798INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
2799  void *ctx;
2800  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
2801  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2802
2803  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
2804  // version of a versioned symbol. For realpath(), this gives us something
2805  // (called __old_realpath) that does not handle NULL in the second argument.
2806  // Handle it as part of the interceptor.
2807  char *allocated_path = nullptr;
2808  if (!resolved_path)
2809    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
2810
2811  char *res = REAL(realpath)(path, resolved_path);
2812  if (allocated_path && !res) WRAP(free)(allocated_path);
2813  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2814  return res;
2815}
2816#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
2817#else
2818#define INIT_REALPATH
2819#endif
2820
2821#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
2822INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
2823  void *ctx;
2824  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
2825  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2826  char *res = REAL(canonicalize_file_name)(path);
2827  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2828  return res;
2829}
2830#define INIT_CANONICALIZE_FILE_NAME \
2831  COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
2832#else
2833#define INIT_CANONICALIZE_FILE_NAME
2834#endif
2835
2836#if SANITIZER_INTERCEPT_CONFSTR
2837INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
2838  void *ctx;
2839  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
2840  // FIXME: under ASan the call below may write to freed memory and corrupt
2841  // its metadata. See
2842  // https://github.com/google/sanitizers/issues/321.
2843  SIZE_T res = REAL(confstr)(name, buf, len);
2844  if (buf && res)
2845    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
2846  return res;
2847}
2848#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
2849#else
2850#define INIT_CONFSTR
2851#endif
2852
2853#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
2854INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
2855  void *ctx;
2856  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
2857  // FIXME: under ASan the call below may write to freed memory and corrupt
2858  // its metadata. See
2859  // https://github.com/google/sanitizers/issues/321.
2860  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
2861  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
2862  return res;
2863}
2864#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
2865#else
2866#define INIT_SCHED_GETAFFINITY
2867#endif
2868
2869#if SANITIZER_INTERCEPT_SCHED_GETPARAM
2870INTERCEPTOR(int, sched_getparam, int pid, void *param) {
2871  void *ctx;
2872  COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
2873  int res = REAL(sched_getparam)(pid, param);
2874  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
2875  return res;
2876}
2877#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
2878#else
2879#define INIT_SCHED_GETPARAM
2880#endif
2881
2882#if SANITIZER_INTERCEPT_STRERROR
2883INTERCEPTOR(char *, strerror, int errnum) {
2884  void *ctx;
2885  COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
2886  char *res = REAL(strerror)(errnum);
2887  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
2888  return res;
2889}
2890#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
2891#else
2892#define INIT_STRERROR
2893#endif
2894
2895#if SANITIZER_INTERCEPT_STRERROR_R
2896INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
2897  void *ctx;
2898  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
2899  // FIXME: under ASan the call below may write to freed memory and corrupt
2900  // its metadata. See
2901  // https://github.com/google/sanitizers/issues/321.
2902  char *res = REAL(strerror_r)(errnum, buf, buflen);
2903  // There are 2 versions of strerror_r:
2904  //  * POSIX version returns 0 on success, negative error code on failure,
2905  //    writes message to buf.
2906  //  * GNU version returns message pointer, which points to either buf or some
2907  //    static storage.
2908  SIZE_T posix_res = (SIZE_T)res;
2909  if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
2910    // POSIX version. Spec is not clear on whether buf is NULL-terminated.
2911    // At least on OSX, buf contents are valid even when the call fails.
2912    SIZE_T sz = internal_strnlen(buf, buflen);
2913    if (sz < buflen) ++sz;
2914    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
2915  } else {
2916    // GNU version.
2917    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2918  }
2919  return res;
2920}
2921#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
2922#else
2923#define INIT_STRERROR_R
2924#endif
2925
2926#if SANITIZER_INTERCEPT_XPG_STRERROR_R
2927INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
2928  void *ctx;
2929  COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
2930  // FIXME: under ASan the call below may write to freed memory and corrupt
2931  // its metadata. See
2932  // https://github.com/google/sanitizers/issues/321.
2933  int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
2934  // This version always returns a null-terminated string.
2935  if (buf && buflen)
2936    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
2937  return res;
2938}
2939#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
2940#else
2941#define INIT_XPG_STRERROR_R
2942#endif
2943
2944#if SANITIZER_INTERCEPT_SCANDIR
2945typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
2946typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
2947                                const struct __sanitizer_dirent **);
2948
2949static THREADLOCAL scandir_filter_f scandir_filter;
2950static THREADLOCAL scandir_compar_f scandir_compar;
2951
2952static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
2953  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2954  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
2955  return scandir_filter(dir);
2956}
2957
2958static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
2959                                  const struct __sanitizer_dirent **b) {
2960  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2961  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
2962  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
2963  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
2964  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
2965  return scandir_compar(a, b);
2966}
2967
2968INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
2969            scandir_filter_f filter, scandir_compar_f compar) {
2970  void *ctx;
2971  COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
2972  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
2973  scandir_filter = filter;
2974  scandir_compar = compar;
2975  // FIXME: under ASan the call below may write to freed memory and corrupt
2976  // its metadata. See
2977  // https://github.com/google/sanitizers/issues/321.
2978  int res = REAL(scandir)(dirp, namelist,
2979                          filter ? wrapped_scandir_filter : nullptr,
2980                          compar ? wrapped_scandir_compar : nullptr);
2981  scandir_filter = nullptr;
2982  scandir_compar = nullptr;
2983  if (namelist && res > 0) {
2984    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
2985    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
2986    for (int i = 0; i < res; ++i)
2987      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
2988                                     (*namelist)[i]->d_reclen);
2989  }
2990  return res;
2991}
2992#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
2993#else
2994#define INIT_SCANDIR
2995#endif
2996
2997#if SANITIZER_INTERCEPT_SCANDIR64
2998typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
2999typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
3000                                  const struct __sanitizer_dirent64 **);
3001
3002static THREADLOCAL scandir64_filter_f scandir64_filter;
3003static THREADLOCAL scandir64_compar_f scandir64_compar;
3004
3005static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
3006  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
3007  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
3008  return scandir64_filter(dir);
3009}
3010
3011static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
3012                                    const struct __sanitizer_dirent64 **b) {
3013  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
3014  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
3015  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
3016  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
3017  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
3018  return scandir64_compar(a, b);
3019}
3020
3021INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
3022            scandir64_filter_f filter, scandir64_compar_f compar) {
3023  void *ctx;
3024  COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
3025  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
3026  scandir64_filter = filter;
3027  scandir64_compar = compar;
3028  // FIXME: under ASan the call below may write to freed memory and corrupt
3029  // its metadata. See
3030  // https://github.com/google/sanitizers/issues/321.
3031  int res =
3032      REAL(scandir64)(dirp, namelist,
3033                      filter ? wrapped_scandir64_filter : nullptr,
3034                      compar ? wrapped_scandir64_compar : nullptr);
3035  scandir64_filter = nullptr;
3036  scandir64_compar = nullptr;
3037  if (namelist && res > 0) {
3038    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
3039    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
3040    for (int i = 0; i < res; ++i)
3041      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
3042                                     (*namelist)[i]->d_reclen);
3043  }
3044  return res;
3045}
3046#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
3047#else
3048#define INIT_SCANDIR64
3049#endif
3050
3051#if SANITIZER_INTERCEPT_GETGROUPS
3052INTERCEPTOR(int, getgroups, int size, u32 *lst) {
3053  void *ctx;
3054  COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
3055  // FIXME: under ASan the call below may write to freed memory and corrupt
3056  // its metadata. See
3057  // https://github.com/google/sanitizers/issues/321.
3058  int res = REAL(getgroups)(size, lst);
3059  if (res && lst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
3060  return res;
3061}
3062#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
3063#else
3064#define INIT_GETGROUPS
3065#endif
3066
3067#if SANITIZER_INTERCEPT_POLL
3068static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
3069                        __sanitizer_nfds_t nfds) {
3070  for (unsigned i = 0; i < nfds; ++i) {
3071    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
3072    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
3073  }
3074}
3075
3076static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
3077                         __sanitizer_nfds_t nfds) {
3078  for (unsigned i = 0; i < nfds; ++i)
3079    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
3080                                   sizeof(fds[i].revents));
3081}
3082
3083INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
3084            int timeout) {
3085  void *ctx;
3086  COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
3087  if (fds && nfds) read_pollfd(ctx, fds, nfds);
3088  int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
3089  if (fds && nfds) write_pollfd(ctx, fds, nfds);
3090  return res;
3091}
3092#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
3093#else
3094#define INIT_POLL
3095#endif
3096
3097#if SANITIZER_INTERCEPT_PPOLL
3098INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
3099            void *timeout_ts, __sanitizer_sigset_t *sigmask) {
3100  void *ctx;
3101  COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
3102  if (fds && nfds) read_pollfd(ctx, fds, nfds);
3103  if (timeout_ts)
3104    COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
3105  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
3106  int res =
3107      COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
3108  if (fds && nfds) write_pollfd(ctx, fds, nfds);
3109  return res;
3110}
3111#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
3112#else
3113#define INIT_PPOLL
3114#endif
3115
3116#if SANITIZER_INTERCEPT_WORDEXP
3117INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
3118  void *ctx;
3119  COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
3120  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
3121  // FIXME: under ASan the call below may write to freed memory and corrupt
3122  // its metadata. See
3123  // https://github.com/google/sanitizers/issues/321.
3124  int res = REAL(wordexp)(s, p, flags);
3125  if (!res && p) {
3126    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
3127    if (p->we_wordc)
3128      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
3129                                     sizeof(*p->we_wordv) * p->we_wordc);
3130    for (uptr i = 0; i < p->we_wordc; ++i) {
3131      char *w = p->we_wordv[i];
3132      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
3133    }
3134  }
3135  return res;
3136}
3137#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
3138#else
3139#define INIT_WORDEXP
3140#endif
3141
3142#if SANITIZER_INTERCEPT_SIGWAIT
3143INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
3144  void *ctx;
3145  COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
3146  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
3147  // FIXME: under ASan the call below may write to freed memory and corrupt
3148  // its metadata. See
3149  // https://github.com/google/sanitizers/issues/321.
3150  int res = REAL(sigwait)(set, sig);
3151  if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
3152  return res;
3153}
3154#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
3155#else
3156#define INIT_SIGWAIT
3157#endif
3158
3159#if SANITIZER_INTERCEPT_SIGWAITINFO
3160INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
3161  void *ctx;
3162  COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
3163  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
3164  // FIXME: under ASan the call below may write to freed memory and corrupt
3165  // its metadata. See
3166  // https://github.com/google/sanitizers/issues/321.
3167  int res = REAL(sigwaitinfo)(set, info);
3168  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
3169  return res;
3170}
3171#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
3172#else
3173#define INIT_SIGWAITINFO
3174#endif
3175
3176#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
3177INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
3178            void *timeout) {
3179  void *ctx;
3180  COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
3181  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
3182  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
3183  // FIXME: under ASan the call below may write to freed memory and corrupt
3184  // its metadata. See
3185  // https://github.com/google/sanitizers/issues/321.
3186  int res = REAL(sigtimedwait)(set, info, timeout);
3187  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
3188  return res;
3189}
3190#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
3191#else
3192#define INIT_SIGTIMEDWAIT
3193#endif
3194
3195#if SANITIZER_INTERCEPT_SIGSETOPS
3196INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
3197  void *ctx;
3198  COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
3199  // FIXME: under ASan the call below may write to freed memory and corrupt
3200  // its metadata. See
3201  // https://github.com/google/sanitizers/issues/321.
3202  int res = REAL(sigemptyset)(set);
3203  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
3204  return res;
3205}
3206
3207INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
3208  void *ctx;
3209  COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
3210  // FIXME: under ASan the call below may write to freed memory and corrupt
3211  // its metadata. See
3212  // https://github.com/google/sanitizers/issues/321.
3213  int res = REAL(sigfillset)(set);
3214  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
3215  return res;
3216}
3217#define INIT_SIGSETOPS                    \
3218  COMMON_INTERCEPT_FUNCTION(sigemptyset); \
3219  COMMON_INTERCEPT_FUNCTION(sigfillset);
3220#else
3221#define INIT_SIGSETOPS
3222#endif
3223
3224#if SANITIZER_INTERCEPT_SIGPENDING
3225INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
3226  void *ctx;
3227  COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
3228  // FIXME: under ASan the call below may write to freed memory and corrupt
3229  // its metadata. See
3230  // https://github.com/google/sanitizers/issues/321.
3231  int res = REAL(sigpending)(set);
3232  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
3233  return res;
3234}
3235#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
3236#else
3237#define INIT_SIGPENDING
3238#endif
3239
3240#if SANITIZER_INTERCEPT_SIGPROCMASK
3241INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
3242            __sanitizer_sigset_t *oldset) {
3243  void *ctx;
3244  COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
3245  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
3246  // FIXME: under ASan the call below may write to freed memory and corrupt
3247  // its metadata. See
3248  // https://github.com/google/sanitizers/issues/321.
3249  int res = REAL(sigprocmask)(how, set, oldset);
3250  if (!res && oldset)
3251    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
3252  return res;
3253}
3254#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
3255#else
3256#define INIT_SIGPROCMASK
3257#endif
3258
3259#if SANITIZER_INTERCEPT_BACKTRACE
3260INTERCEPTOR(int, backtrace, void **buffer, int size) {
3261  void *ctx;
3262  COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
3263  // FIXME: under ASan the call below may write to freed memory and corrupt
3264  // its metadata. See
3265  // https://github.com/google/sanitizers/issues/321.
3266  int res = REAL(backtrace)(buffer, size);
3267  if (res && buffer)
3268    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
3269  return res;
3270}
3271
3272INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
3273  void *ctx;
3274  COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
3275  if (buffer && size)
3276    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
3277  // FIXME: under ASan the call below may write to freed memory and corrupt
3278  // its metadata. See
3279  // https://github.com/google/sanitizers/issues/321.
3280  char **res = REAL(backtrace_symbols)(buffer, size);
3281  if (res && size) {
3282    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
3283    for (int i = 0; i < size; ++i)
3284      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
3285  }
3286  return res;
3287}
3288#define INIT_BACKTRACE                  \
3289  COMMON_INTERCEPT_FUNCTION(backtrace); \
3290  COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
3291#else
3292#define INIT_BACKTRACE
3293#endif
3294
3295#if SANITIZER_INTERCEPT__EXIT
3296INTERCEPTOR(void, _exit, int status) {
3297  void *ctx;
3298  COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
3299  int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
3300  if (status == 0) status = status1;
3301  REAL(_exit)(status);
3302}
3303#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
3304#else
3305#define INIT__EXIT
3306#endif
3307
3308#if SANITIZER_INTERCEPT_PHTREAD_MUTEX
3309INTERCEPTOR(int, pthread_mutex_lock, void *m) {
3310  void *ctx;
3311  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
3312  int res = REAL(pthread_mutex_lock)(m);
3313  if (res == errno_EOWNERDEAD)
3314    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
3315  if (res == 0 || res == errno_EOWNERDEAD)
3316    COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
3317  return res;
3318}
3319
3320INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
3321  void *ctx;
3322  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
3323  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
3324  return REAL(pthread_mutex_unlock)(m);
3325}
3326
3327#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
3328#define INIT_PTHREAD_MUTEX_UNLOCK \
3329  COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
3330#else
3331#define INIT_PTHREAD_MUTEX_LOCK
3332#define INIT_PTHREAD_MUTEX_UNLOCK
3333#endif
3334
3335#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
3336static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
3337  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
3338  if (mnt->mnt_fsname)
3339    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
3340                                   REAL(strlen)(mnt->mnt_fsname) + 1);
3341  if (mnt->mnt_dir)
3342    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
3343                                   REAL(strlen)(mnt->mnt_dir) + 1);
3344  if (mnt->mnt_type)
3345    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
3346                                   REAL(strlen)(mnt->mnt_type) + 1);
3347  if (mnt->mnt_opts)
3348    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
3349                                   REAL(strlen)(mnt->mnt_opts) + 1);
3350}
3351#endif
3352
3353#if SANITIZER_INTERCEPT_GETMNTENT
3354INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
3355  void *ctx;
3356  COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
3357  __sanitizer_mntent *res = REAL(getmntent)(fp);
3358  if (res) write_mntent(ctx, res);
3359  return res;
3360}
3361#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
3362#else
3363#define INIT_GETMNTENT
3364#endif
3365
3366#if SANITIZER_INTERCEPT_GETMNTENT_R
3367INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
3368            __sanitizer_mntent *mntbuf, char *buf, int buflen) {
3369  void *ctx;
3370  COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
3371  __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
3372  if (res) write_mntent(ctx, res);
3373  return res;
3374}
3375#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
3376#else
3377#define INIT_GETMNTENT_R
3378#endif
3379
3380#if SANITIZER_INTERCEPT_STATFS
3381INTERCEPTOR(int, statfs, char *path, void *buf) {
3382  void *ctx;
3383  COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
3384  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3385  // FIXME: under ASan the call below may write to freed memory and corrupt
3386  // its metadata. See
3387  // https://github.com/google/sanitizers/issues/321.
3388  int res = REAL(statfs)(path, buf);
3389  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
3390  return res;
3391}
3392INTERCEPTOR(int, fstatfs, int fd, void *buf) {
3393  void *ctx;
3394  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
3395  // FIXME: under ASan the call below may write to freed memory and corrupt
3396  // its metadata. See
3397  // https://github.com/google/sanitizers/issues/321.
3398  int res = REAL(fstatfs)(fd, buf);
3399  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
3400  return res;
3401}
3402#define INIT_STATFS                  \
3403  COMMON_INTERCEPT_FUNCTION(statfs); \
3404  COMMON_INTERCEPT_FUNCTION(fstatfs);
3405#else
3406#define INIT_STATFS
3407#endif
3408
3409#if SANITIZER_INTERCEPT_STATFS64
3410INTERCEPTOR(int, statfs64, char *path, void *buf) {
3411  void *ctx;
3412  COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
3413  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3414  // FIXME: under ASan the call below may write to freed memory and corrupt
3415  // its metadata. See
3416  // https://github.com/google/sanitizers/issues/321.
3417  int res = REAL(statfs64)(path, buf);
3418  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
3419  return res;
3420}
3421INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
3422  void *ctx;
3423  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
3424  // FIXME: under ASan the call below may write to freed memory and corrupt
3425  // its metadata. See
3426  // https://github.com/google/sanitizers/issues/321.
3427  int res = REAL(fstatfs64)(fd, buf);
3428  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
3429  return res;
3430}
3431#define INIT_STATFS64                  \
3432  COMMON_INTERCEPT_FUNCTION(statfs64); \
3433  COMMON_INTERCEPT_FUNCTION(fstatfs64);
3434#else
3435#define INIT_STATFS64
3436#endif
3437
3438#if SANITIZER_INTERCEPT_STATVFS
3439INTERCEPTOR(int, statvfs, char *path, void *buf) {
3440  void *ctx;
3441  COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
3442  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3443  // FIXME: under ASan the call below may write to freed memory and corrupt
3444  // its metadata. See
3445  // https://github.com/google/sanitizers/issues/321.
3446  int res = REAL(statvfs)(path, buf);
3447  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
3448  return res;
3449}
3450INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
3451  void *ctx;
3452  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
3453  // FIXME: under ASan the call below may write to freed memory and corrupt
3454  // its metadata. See
3455  // https://github.com/google/sanitizers/issues/321.
3456  int res = REAL(fstatvfs)(fd, buf);
3457  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
3458  return res;
3459}
3460#define INIT_STATVFS                  \
3461  COMMON_INTERCEPT_FUNCTION(statvfs); \
3462  COMMON_INTERCEPT_FUNCTION(fstatvfs);
3463#else
3464#define INIT_STATVFS
3465#endif
3466
3467#if SANITIZER_INTERCEPT_STATVFS64
3468INTERCEPTOR(int, statvfs64, char *path, void *buf) {
3469  void *ctx;
3470  COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
3471  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3472  // FIXME: under ASan the call below may write to freed memory and corrupt
3473  // its metadata. See
3474  // https://github.com/google/sanitizers/issues/321.
3475  int res = REAL(statvfs64)(path, buf);
3476  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
3477  return res;
3478}
3479INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
3480  void *ctx;
3481  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
3482  // FIXME: under ASan the call below may write to freed memory and corrupt
3483  // its metadata. See
3484  // https://github.com/google/sanitizers/issues/321.
3485  int res = REAL(fstatvfs64)(fd, buf);
3486  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
3487  return res;
3488}
3489#define INIT_STATVFS64                  \
3490  COMMON_INTERCEPT_FUNCTION(statvfs64); \
3491  COMMON_INTERCEPT_FUNCTION(fstatvfs64);
3492#else
3493#define INIT_STATVFS64
3494#endif
3495
3496#if SANITIZER_INTERCEPT_INITGROUPS
3497INTERCEPTOR(int, initgroups, char *user, u32 group) {
3498  void *ctx;
3499  COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
3500  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
3501  int res = REAL(initgroups)(user, group);
3502  return res;
3503}
3504#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
3505#else
3506#define INIT_INITGROUPS
3507#endif
3508
3509#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
3510INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
3511  void *ctx;
3512  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
3513  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
3514  char *res = REAL(ether_ntoa)(addr);
3515  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3516  return res;
3517}
3518INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
3519  void *ctx;
3520  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
3521  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
3522  __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
3523  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
3524  return res;
3525}
3526#define INIT_ETHER_NTOA_ATON             \
3527  COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
3528  COMMON_INTERCEPT_FUNCTION(ether_aton);
3529#else
3530#define INIT_ETHER_NTOA_ATON
3531#endif
3532
3533#if SANITIZER_INTERCEPT_ETHER_HOST
3534INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
3535  void *ctx;
3536  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
3537  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
3538  // FIXME: under ASan the call below may write to freed memory and corrupt
3539  // its metadata. See
3540  // https://github.com/google/sanitizers/issues/321.
3541  int res = REAL(ether_ntohost)(hostname, addr);
3542  if (!res && hostname)
3543    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
3544  return res;
3545}
3546INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
3547  void *ctx;
3548  COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
3549  if (hostname)
3550    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
3551  // FIXME: under ASan the call below may write to freed memory and corrupt
3552  // its metadata. See
3553  // https://github.com/google/sanitizers/issues/321.
3554  int res = REAL(ether_hostton)(hostname, addr);
3555  if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
3556  return res;
3557}
3558INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
3559            char *hostname) {
3560  void *ctx;
3561  COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
3562  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
3563  // FIXME: under ASan the call below may write to freed memory and corrupt
3564  // its metadata. See
3565  // https://github.com/google/sanitizers/issues/321.
3566  int res = REAL(ether_line)(line, addr, hostname);
3567  if (!res) {
3568    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
3569    if (hostname)
3570      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
3571  }
3572  return res;
3573}
3574#define INIT_ETHER_HOST                     \
3575  COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
3576  COMMON_INTERCEPT_FUNCTION(ether_hostton); \
3577  COMMON_INTERCEPT_FUNCTION(ether_line);
3578#else
3579#define INIT_ETHER_HOST
3580#endif
3581
3582#if SANITIZER_INTERCEPT_ETHER_R
3583INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
3584  void *ctx;
3585  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
3586  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
3587  // FIXME: under ASan the call below may write to freed memory and corrupt
3588  // its metadata. See
3589  // https://github.com/google/sanitizers/issues/321.
3590  char *res = REAL(ether_ntoa_r)(addr, buf);
3591  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3592  return res;
3593}
3594INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
3595            __sanitizer_ether_addr *addr) {
3596  void *ctx;
3597  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
3598  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
3599  // FIXME: under ASan the call below may write to freed memory and corrupt
3600  // its metadata. See
3601  // https://github.com/google/sanitizers/issues/321.
3602  __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
3603  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
3604  return res;
3605}
3606#define INIT_ETHER_R                       \
3607  COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
3608  COMMON_INTERCEPT_FUNCTION(ether_aton_r);
3609#else
3610#define INIT_ETHER_R
3611#endif
3612
3613#if SANITIZER_INTERCEPT_SHMCTL
3614INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
3615  void *ctx;
3616  COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
3617  // FIXME: under ASan the call below may write to freed memory and corrupt
3618  // its metadata. See
3619  // https://github.com/google/sanitizers/issues/321.
3620  int res = REAL(shmctl)(shmid, cmd, buf);
3621  if (res >= 0) {
3622    unsigned sz = 0;
3623    if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
3624      sz = sizeof(__sanitizer_shmid_ds);
3625    else if (cmd == shmctl_ipc_info)
3626      sz = struct_shminfo_sz;
3627    else if (cmd == shmctl_shm_info)
3628      sz = struct_shm_info_sz;
3629    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
3630  }
3631  return res;
3632}
3633#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
3634#else
3635#define INIT_SHMCTL
3636#endif
3637
3638#if SANITIZER_INTERCEPT_RANDOM_R
3639INTERCEPTOR(int, random_r, void *buf, u32 *result) {
3640  void *ctx;
3641  COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
3642  // FIXME: under ASan the call below may write to freed memory and corrupt
3643  // its metadata. See
3644  // https://github.com/google/sanitizers/issues/321.
3645  int res = REAL(random_r)(buf, result);
3646  if (!res && result)
3647    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3648  return res;
3649}
3650#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
3651#else
3652#define INIT_RANDOM_R
3653#endif
3654
3655// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
3656// its metadata. See
3657// https://github.com/google/sanitizers/issues/321.
3658#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET ||              \
3659    SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
3660    SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET ||         \
3661    SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET ||        \
3662    SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET ||          \
3663    SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
3664#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz)            \
3665  INTERCEPTOR(int, fn, void *attr, void *r) {                  \
3666    void *ctx;                                                 \
3667    COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r);                \
3668    int res = REAL(fn)(attr, r);                               \
3669    if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
3670    return res;                                                \
3671  }
3672#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
3673  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
3674#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
3675  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
3676#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
3677  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
3678#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
3679  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
3680#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
3681  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
3682#endif
3683
3684#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
3685INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
3686INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
3687INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
3688INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
3689INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
3690INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
3691INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
3692  void *ctx;
3693  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
3694  // FIXME: under ASan the call below may write to freed memory and corrupt
3695  // its metadata. See
3696  // https://github.com/google/sanitizers/issues/321.
3697  int res = REAL(pthread_attr_getstack)(attr, addr, size);
3698  if (!res) {
3699    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
3700    if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
3701  }
3702  return res;
3703}
3704
3705// We may need to call the real pthread_attr_getstack from the run-time
3706// in sanitizer_common, but we don't want to include the interception headers
3707// there. So, just define this function here.
3708namespace __sanitizer {
3709extern "C" {
3710int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
3711  return REAL(pthread_attr_getstack)(attr, addr, size);
3712}
3713}  // extern "C"
3714}  // namespace __sanitizer
3715
3716#define INIT_PTHREAD_ATTR_GET                             \
3717  COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
3718  COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize);   \
3719  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam);  \
3720  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy); \
3721  COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope);       \
3722  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize);   \
3723  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
3724#else
3725#define INIT_PTHREAD_ATTR_GET
3726#endif
3727
3728#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
3729INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
3730
3731#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
3732  COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
3733#else
3734#define INIT_PTHREAD_ATTR_GETINHERITSCHED
3735#endif
3736
3737#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
3738INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
3739            void *cpuset) {
3740  void *ctx;
3741  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
3742                           cpuset);
3743  // FIXME: under ASan the call below may write to freed memory and corrupt
3744  // its metadata. See
3745  // https://github.com/google/sanitizers/issues/321.
3746  int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
3747  if (!res && cpusetsize && cpuset)
3748    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
3749  return res;
3750}
3751
3752#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
3753  COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
3754#else
3755#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
3756#endif
3757
3758#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
3759INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
3760#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
3761  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
3762#else
3763#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
3764#endif
3765
3766#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
3767INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
3768#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
3769  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
3770#else
3771#define INIT_PTHREAD_MUTEXATTR_GETTYPE
3772#endif
3773
3774#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
3775INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
3776#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
3777  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
3778#else
3779#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
3780#endif
3781
3782#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
3783INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
3784#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
3785  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
3786#else
3787#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
3788#endif
3789
3790#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
3791INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
3792#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
3793  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
3794#else
3795#define INIT_PTHREAD_MUTEXATTR_GETROBUST
3796#endif
3797
3798#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
3799INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
3800#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
3801  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
3802#else
3803#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
3804#endif
3805
3806#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
3807INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
3808#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
3809  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
3810#else
3811#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
3812#endif
3813
3814#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
3815INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
3816#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
3817  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
3818#else
3819#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
3820#endif
3821
3822#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
3823INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
3824#define INIT_PTHREAD_CONDATTR_GETPSHARED \
3825  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
3826#else
3827#define INIT_PTHREAD_CONDATTR_GETPSHARED
3828#endif
3829
3830#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
3831INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
3832#define INIT_PTHREAD_CONDATTR_GETCLOCK \
3833  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
3834#else
3835#define INIT_PTHREAD_CONDATTR_GETCLOCK
3836#endif
3837
3838#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
3839INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
3840#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
3841  COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
3842#else
3843#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
3844#endif
3845
3846#if SANITIZER_INTERCEPT_TMPNAM
3847INTERCEPTOR(char *, tmpnam, char *s) {
3848  void *ctx;
3849  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
3850  char *res = REAL(tmpnam)(s);
3851  if (res) {
3852    if (s)
3853      // FIXME: under ASan the call below may write to freed memory and corrupt
3854      // its metadata. See
3855      // https://github.com/google/sanitizers/issues/321.
3856      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
3857    else
3858      COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3859  }
3860  return res;
3861}
3862#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
3863#else
3864#define INIT_TMPNAM
3865#endif
3866
3867#if SANITIZER_INTERCEPT_TMPNAM_R
3868INTERCEPTOR(char *, tmpnam_r, char *s) {
3869  void *ctx;
3870  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
3871  // FIXME: under ASan the call below may write to freed memory and corrupt
3872  // its metadata. See
3873  // https://github.com/google/sanitizers/issues/321.
3874  char *res = REAL(tmpnam_r)(s);
3875  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
3876  return res;
3877}
3878#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
3879#else
3880#define INIT_TMPNAM_R
3881#endif
3882
3883#if SANITIZER_INTERCEPT_TEMPNAM
3884INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
3885  void *ctx;
3886  COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
3887  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
3888  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
3889  char *res = REAL(tempnam)(dir, pfx);
3890  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3891  return res;
3892}
3893#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
3894#else
3895#define INIT_TEMPNAM
3896#endif
3897
3898#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP
3899INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
3900  void *ctx;
3901  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
3902  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
3903  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
3904  return REAL(pthread_setname_np)(thread, name);
3905}
3906#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
3907#else
3908#define INIT_PTHREAD_SETNAME_NP
3909#endif
3910
3911#if SANITIZER_INTERCEPT_SINCOS
3912INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
3913  void *ctx;
3914  COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
3915  // FIXME: under ASan the call below may write to freed memory and corrupt
3916  // its metadata. See
3917  // https://github.com/google/sanitizers/issues/321.
3918  REAL(sincos)(x, sin, cos);
3919  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
3920  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
3921}
3922INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
3923  void *ctx;
3924  COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
3925  // FIXME: under ASan the call below may write to freed memory and corrupt
3926  // its metadata. See
3927  // https://github.com/google/sanitizers/issues/321.
3928  REAL(sincosf)(x, sin, cos);
3929  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
3930  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
3931}
3932INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
3933  void *ctx;
3934  COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
3935  // FIXME: under ASan the call below may write to freed memory and corrupt
3936  // its metadata. See
3937  // https://github.com/google/sanitizers/issues/321.
3938  REAL(sincosl)(x, sin, cos);
3939  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
3940  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
3941}
3942#define INIT_SINCOS                   \
3943  COMMON_INTERCEPT_FUNCTION(sincos);  \
3944  COMMON_INTERCEPT_FUNCTION(sincosf); \
3945  COMMON_INTERCEPT_FUNCTION(sincosl);
3946#else
3947#define INIT_SINCOS
3948#endif
3949
3950#if SANITIZER_INTERCEPT_REMQUO
3951INTERCEPTOR(double, remquo, double x, double y, int *quo) {
3952  void *ctx;
3953  COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
3954  // FIXME: under ASan the call below may write to freed memory and corrupt
3955  // its metadata. See
3956  // https://github.com/google/sanitizers/issues/321.
3957  double res = REAL(remquo)(x, y, quo);
3958  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
3959  return res;
3960}
3961INTERCEPTOR(float, remquof, float x, float y, int *quo) {
3962  void *ctx;
3963  COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
3964  // FIXME: under ASan the call below may write to freed memory and corrupt
3965  // its metadata. See
3966  // https://github.com/google/sanitizers/issues/321.
3967  float res = REAL(remquof)(x, y, quo);
3968  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
3969  return res;
3970}
3971INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
3972  void *ctx;
3973  COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
3974  // FIXME: under ASan the call below may write to freed memory and corrupt
3975  // its metadata. See
3976  // https://github.com/google/sanitizers/issues/321.
3977  long double res = REAL(remquol)(x, y, quo);
3978  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
3979  return res;
3980}
3981#define INIT_REMQUO                   \
3982  COMMON_INTERCEPT_FUNCTION(remquo);  \
3983  COMMON_INTERCEPT_FUNCTION(remquof); \
3984  COMMON_INTERCEPT_FUNCTION(remquol);
3985#else
3986#define INIT_REMQUO
3987#endif
3988
3989#if SANITIZER_INTERCEPT_LGAMMA
3990extern int signgam;
3991INTERCEPTOR(double, lgamma, double x) {
3992  void *ctx;
3993  COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
3994  double res = REAL(lgamma)(x);
3995  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
3996  return res;
3997}
3998INTERCEPTOR(float, lgammaf, float x) {
3999  void *ctx;
4000  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
4001  float res = REAL(lgammaf)(x);
4002  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
4003  return res;
4004}
4005INTERCEPTOR(long double, lgammal, long double x) {
4006  void *ctx;
4007  COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
4008  long double res = REAL(lgammal)(x);
4009  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
4010  return res;
4011}
4012#define INIT_LGAMMA                   \
4013  COMMON_INTERCEPT_FUNCTION(lgamma);  \
4014  COMMON_INTERCEPT_FUNCTION(lgammaf); \
4015  COMMON_INTERCEPT_FUNCTION(lgammal);
4016#else
4017#define INIT_LGAMMA
4018#endif
4019
4020#if SANITIZER_INTERCEPT_LGAMMA_R
4021INTERCEPTOR(double, lgamma_r, double x, int *signp) {
4022  void *ctx;
4023  COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
4024  // FIXME: under ASan the call below may write to freed memory and corrupt
4025  // its metadata. See
4026  // https://github.com/google/sanitizers/issues/321.
4027  double res = REAL(lgamma_r)(x, signp);
4028  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
4029  return res;
4030}
4031INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
4032  void *ctx;
4033  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
4034  // FIXME: under ASan the call below may write to freed memory and corrupt
4035  // its metadata. See
4036  // https://github.com/google/sanitizers/issues/321.
4037  float res = REAL(lgammaf_r)(x, signp);
4038  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
4039  return res;
4040}
4041#define INIT_LGAMMA_R                   \
4042  COMMON_INTERCEPT_FUNCTION(lgamma_r);  \
4043  COMMON_INTERCEPT_FUNCTION(lgammaf_r);
4044#else
4045#define INIT_LGAMMA_R
4046#endif
4047
4048#if SANITIZER_INTERCEPT_LGAMMAL_R
4049INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
4050  void *ctx;
4051  COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
4052  // FIXME: under ASan the call below may write to freed memory and corrupt
4053  // its metadata. See
4054  // https://github.com/google/sanitizers/issues/321.
4055  long double res = REAL(lgammal_r)(x, signp);
4056  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
4057  return res;
4058}
4059#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION(lgammal_r);
4060#else
4061#define INIT_LGAMMAL_R
4062#endif
4063
4064#if SANITIZER_INTERCEPT_DRAND48_R
4065INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
4066  void *ctx;
4067  COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
4068  // FIXME: under ASan the call below may write to freed memory and corrupt
4069  // its metadata. See
4070  // https://github.com/google/sanitizers/issues/321.
4071  int res = REAL(drand48_r)(buffer, result);
4072  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
4073  return res;
4074}
4075INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
4076  void *ctx;
4077  COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
4078  // FIXME: under ASan the call below may write to freed memory and corrupt
4079  // its metadata. See
4080  // https://github.com/google/sanitizers/issues/321.
4081  int res = REAL(lrand48_r)(buffer, result);
4082  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
4083  return res;
4084}
4085#define INIT_DRAND48_R                  \
4086  COMMON_INTERCEPT_FUNCTION(drand48_r); \
4087  COMMON_INTERCEPT_FUNCTION(lrand48_r);
4088#else
4089#define INIT_DRAND48_R
4090#endif
4091
4092#if SANITIZER_INTERCEPT_RAND_R
4093INTERCEPTOR(int, rand_r, unsigned *seedp) {
4094  void *ctx;
4095  COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
4096  COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
4097  return REAL(rand_r)(seedp);
4098}
4099#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
4100#else
4101#define INIT_RAND_R
4102#endif
4103
4104#if SANITIZER_INTERCEPT_GETLINE
4105INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
4106  void *ctx;
4107  COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
4108  // FIXME: under ASan the call below may write to freed memory and corrupt
4109  // its metadata. See
4110  // https://github.com/google/sanitizers/issues/321.
4111  SSIZE_T res = REAL(getline)(lineptr, n, stream);
4112  if (res > 0) {
4113    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
4114    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
4115    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
4116  }
4117  return res;
4118}
4119
4120// FIXME: under ASan the call below may write to freed memory and corrupt its
4121// metadata. See
4122// https://github.com/google/sanitizers/issues/321.
4123#define GETDELIM_INTERCEPTOR_IMPL(vname)                                       \
4124  {                                                                            \
4125    void *ctx;                                                                 \
4126    COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream);           \
4127    SSIZE_T res = REAL(vname)(lineptr, n, delim, stream);                      \
4128    if (res > 0) {                                                             \
4129      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));          \
4130      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));                      \
4131      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);                  \
4132    }                                                                          \
4133    return res;                                                                \
4134  }
4135
4136INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
4137            void *stream)
4138GETDELIM_INTERCEPTOR_IMPL(__getdelim)
4139
4140// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
4141// with its own body.
4142INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
4143            void *stream)
4144GETDELIM_INTERCEPTOR_IMPL(getdelim)
4145
4146#define INIT_GETLINE                     \
4147  COMMON_INTERCEPT_FUNCTION(getline);    \
4148  COMMON_INTERCEPT_FUNCTION(__getdelim); \
4149  COMMON_INTERCEPT_FUNCTION(getdelim);
4150#else
4151#define INIT_GETLINE
4152#endif
4153
4154#if SANITIZER_INTERCEPT_ICONV
4155INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
4156            char **outbuf, SIZE_T *outbytesleft) {
4157  void *ctx;
4158  COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
4159                           outbytesleft);
4160  if (inbytesleft)
4161    COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
4162  if (inbuf && inbytesleft)
4163    COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
4164  if (outbytesleft)
4165    COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
4166  void *outbuf_orig = outbuf ? *outbuf : nullptr;
4167  // FIXME: under ASan the call below may write to freed memory and corrupt
4168  // its metadata. See
4169  // https://github.com/google/sanitizers/issues/321.
4170  SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
4171  if (res != (SIZE_T) - 1 && outbuf && *outbuf > outbuf_orig) {
4172    SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
4173    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
4174  }
4175  return res;
4176}
4177#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
4178#else
4179#define INIT_ICONV
4180#endif
4181
4182#if SANITIZER_INTERCEPT_TIMES
4183INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
4184  void *ctx;
4185  COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
4186  // FIXME: under ASan the call below may write to freed memory and corrupt
4187  // its metadata. See
4188  // https://github.com/google/sanitizers/issues/321.
4189  __sanitizer_clock_t res = REAL(times)(tms);
4190  if (res != (__sanitizer_clock_t)-1 && tms)
4191    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
4192  return res;
4193}
4194#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
4195#else
4196#define INIT_TIMES
4197#endif
4198
4199#if SANITIZER_INTERCEPT_TLS_GET_ADDR
4200#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
4201// If you see any crashes around this functions, there are 2 known issues with
4202// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
4203// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
4204// 2. It can be called recursively if sanitizer code uses __tls_get_addr
4205// to access thread local variables (it should not happen normally,
4206// because sanitizers use initial-exec tls model).
4207INTERCEPTOR(void *, __tls_get_addr, void *arg) {
4208  void *ctx;
4209  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
4210  void *res = REAL(__tls_get_addr)(arg);
4211  uptr tls_begin, tls_end;
4212  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
4213  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
4214  if (dtv) {
4215    // New DTLS block has been allocated.
4216    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
4217  }
4218  return res;
4219}
4220#else
4221#define INIT_TLS_GET_ADDR
4222#endif
4223
4224#if SANITIZER_INTERCEPT_LISTXATTR
4225INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
4226  void *ctx;
4227  COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
4228  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4229  // FIXME: under ASan the call below may write to freed memory and corrupt
4230  // its metadata. See
4231  // https://github.com/google/sanitizers/issues/321.
4232  SSIZE_T res = REAL(listxattr)(path, list, size);
4233  // Here and below, size == 0 is a special case where nothing is written to the
4234  // buffer, and res contains the desired buffer size.
4235  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
4236  return res;
4237}
4238INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
4239  void *ctx;
4240  COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
4241  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4242  // FIXME: under ASan the call below may write to freed memory and corrupt
4243  // its metadata. See
4244  // https://github.com/google/sanitizers/issues/321.
4245  SSIZE_T res = REAL(llistxattr)(path, list, size);
4246  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
4247  return res;
4248}
4249INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
4250  void *ctx;
4251  COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
4252  // FIXME: under ASan the call below may write to freed memory and corrupt
4253  // its metadata. See
4254  // https://github.com/google/sanitizers/issues/321.
4255  SSIZE_T res = REAL(flistxattr)(fd, list, size);
4256  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
4257  return res;
4258}
4259#define INIT_LISTXATTR                   \
4260  COMMON_INTERCEPT_FUNCTION(listxattr);  \
4261  COMMON_INTERCEPT_FUNCTION(llistxattr); \
4262  COMMON_INTERCEPT_FUNCTION(flistxattr);
4263#else
4264#define INIT_LISTXATTR
4265#endif
4266
4267#if SANITIZER_INTERCEPT_GETXATTR
4268INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
4269            SIZE_T size) {
4270  void *ctx;
4271  COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
4272  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4273  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
4274  // FIXME: under ASan the call below may write to freed memory and corrupt
4275  // its metadata. See
4276  // https://github.com/google/sanitizers/issues/321.
4277  SSIZE_T res = REAL(getxattr)(path, name, value, size);
4278  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
4279  return res;
4280}
4281INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
4282            SIZE_T size) {
4283  void *ctx;
4284  COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
4285  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4286  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
4287  // FIXME: under ASan the call below may write to freed memory and corrupt
4288  // its metadata. See
4289  // https://github.com/google/sanitizers/issues/321.
4290  SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
4291  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
4292  return res;
4293}
4294INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
4295            SIZE_T size) {
4296  void *ctx;
4297  COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
4298  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
4299  // FIXME: under ASan the call below may write to freed memory and corrupt
4300  // its metadata. See
4301  // https://github.com/google/sanitizers/issues/321.
4302  SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
4303  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
4304  return res;
4305}
4306#define INIT_GETXATTR                   \
4307  COMMON_INTERCEPT_FUNCTION(getxattr);  \
4308  COMMON_INTERCEPT_FUNCTION(lgetxattr); \
4309  COMMON_INTERCEPT_FUNCTION(fgetxattr);
4310#else
4311#define INIT_GETXATTR
4312#endif
4313
4314#if SANITIZER_INTERCEPT_GETRESID
4315INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
4316  void *ctx;
4317  COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
4318  // FIXME: under ASan the call below may write to freed memory and corrupt
4319  // its metadata. See
4320  // https://github.com/google/sanitizers/issues/321.
4321  int res = REAL(getresuid)(ruid, euid, suid);
4322  if (res >= 0) {
4323    if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
4324    if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
4325    if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
4326  }
4327  return res;
4328}
4329INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
4330  void *ctx;
4331  COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
4332  // FIXME: under ASan the call below may write to freed memory and corrupt
4333  // its metadata. See
4334  // https://github.com/google/sanitizers/issues/321.
4335  int res = REAL(getresgid)(rgid, egid, sgid);
4336  if (res >= 0) {
4337    if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
4338    if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
4339    if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
4340  }
4341  return res;
4342}
4343#define INIT_GETRESID                   \
4344  COMMON_INTERCEPT_FUNCTION(getresuid); \
4345  COMMON_INTERCEPT_FUNCTION(getresgid);
4346#else
4347#define INIT_GETRESID
4348#endif
4349
4350#if SANITIZER_INTERCEPT_GETIFADDRS
4351// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
4352// intercept freeifaddrs(). If that ceases to be the case, we might need to
4353// intercept it to poison the memory again.
4354INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
4355  void *ctx;
4356  COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
4357  // FIXME: under ASan the call below may write to freed memory and corrupt
4358  // its metadata. See
4359  // https://github.com/google/sanitizers/issues/321.
4360  int res = REAL(getifaddrs)(ifap);
4361  if (res == 0 && ifap) {
4362    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
4363    __sanitizer_ifaddrs *p = *ifap;
4364    while (p) {
4365      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
4366      if (p->ifa_name)
4367        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
4368                                       REAL(strlen)(p->ifa_name) + 1);
4369      if (p->ifa_addr)
4370        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
4371      if (p->ifa_netmask)
4372        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
4373      // On Linux this is a union, but the other member also points to a
4374      // struct sockaddr, so the following is sufficient.
4375      if (p->ifa_dstaddr)
4376        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
4377      // FIXME(smatveev): Unpoison p->ifa_data as well.
4378      p = p->ifa_next;
4379    }
4380  }
4381  return res;
4382}
4383#define INIT_GETIFADDRS                  \
4384  COMMON_INTERCEPT_FUNCTION(getifaddrs);
4385#else
4386#define INIT_GETIFADDRS
4387#endif
4388
4389#if SANITIZER_INTERCEPT_IF_INDEXTONAME
4390INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
4391  void *ctx;
4392  COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
4393  // FIXME: under ASan the call below may write to freed memory and corrupt
4394  // its metadata. See
4395  // https://github.com/google/sanitizers/issues/321.
4396  char *res = REAL(if_indextoname)(ifindex, ifname);
4397  if (res && ifname)
4398    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
4399  return res;
4400}
4401INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
4402  void *ctx;
4403  COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
4404  if (ifname)
4405    COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
4406  return REAL(if_nametoindex)(ifname);
4407}
4408#define INIT_IF_INDEXTONAME                  \
4409  COMMON_INTERCEPT_FUNCTION(if_indextoname); \
4410  COMMON_INTERCEPT_FUNCTION(if_nametoindex);
4411#else
4412#define INIT_IF_INDEXTONAME
4413#endif
4414
4415#if SANITIZER_INTERCEPT_CAPGET
4416INTERCEPTOR(int, capget, void *hdrp, void *datap) {
4417  void *ctx;
4418  COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
4419  if (hdrp)
4420    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
4421  // FIXME: under ASan the call below may write to freed memory and corrupt
4422  // its metadata. See
4423  // https://github.com/google/sanitizers/issues/321.
4424  int res = REAL(capget)(hdrp, datap);
4425  if (res == 0 && datap)
4426    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
4427  // We can also return -1 and write to hdrp->version if the version passed in
4428  // hdrp->version is unsupported. But that's not a trivial condition to check,
4429  // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
4430  return res;
4431}
4432INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
4433  void *ctx;
4434  COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
4435  if (hdrp)
4436    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
4437  if (datap)
4438    COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
4439  return REAL(capset)(hdrp, datap);
4440}
4441#define INIT_CAPGET                  \
4442  COMMON_INTERCEPT_FUNCTION(capget); \
4443  COMMON_INTERCEPT_FUNCTION(capset);
4444#else
4445#define INIT_CAPGET
4446#endif
4447
4448#if SANITIZER_INTERCEPT_AEABI_MEM
4449DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr)
4450DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr)
4451DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr)
4452
4453INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
4454  return WRAP(memmove)(to, from, size);
4455}
4456INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
4457  return WRAP(memmove)(to, from, size);
4458}
4459INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
4460  return WRAP(memmove)(to, from, size);
4461}
4462INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
4463  return WRAP(memcpy)(to, from, size);
4464}
4465INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
4466  return WRAP(memcpy)(to, from, size);
4467}
4468INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
4469  return WRAP(memcpy)(to, from, size);
4470}
4471// Note the argument order.
4472INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
4473  return WRAP(memset)(block, c, size);
4474}
4475INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
4476  return WRAP(memset)(block, c, size);
4477}
4478INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
4479  return WRAP(memset)(block, c, size);
4480}
4481INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
4482  return WRAP(memset)(block, 0, size);
4483}
4484INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
4485  return WRAP(memset)(block, 0, size);
4486}
4487INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
4488  return WRAP(memset)(block, 0, size);
4489}
4490#define INIT_AEABI_MEM                         \
4491  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove);  \
4492  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
4493  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
4494  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy);   \
4495  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4);  \
4496  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8);  \
4497  COMMON_INTERCEPT_FUNCTION(__aeabi_memset);   \
4498  COMMON_INTERCEPT_FUNCTION(__aeabi_memset4);  \
4499  COMMON_INTERCEPT_FUNCTION(__aeabi_memset8);  \
4500  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr);   \
4501  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4);  \
4502  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
4503#else
4504#define INIT_AEABI_MEM
4505#endif  // SANITIZER_INTERCEPT_AEABI_MEM
4506
4507#if SANITIZER_INTERCEPT___BZERO
4508DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);
4509
4510INTERCEPTOR(void *, __bzero, void *block, uptr size) {
4511  return WRAP(memset)(block, 0, size);
4512}
4513#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
4514#else
4515#define INIT___BZERO
4516#endif  // SANITIZER_INTERCEPT___BZERO
4517
4518#if SANITIZER_INTERCEPT_FTIME
4519INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
4520  void *ctx;
4521  COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
4522  // FIXME: under ASan the call below may write to freed memory and corrupt
4523  // its metadata. See
4524  // https://github.com/google/sanitizers/issues/321.
4525  int res = REAL(ftime)(tp);
4526  if (tp)
4527    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
4528  return res;
4529}
4530#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
4531#else
4532#define INIT_FTIME
4533#endif  // SANITIZER_INTERCEPT_FTIME
4534
4535#if SANITIZER_INTERCEPT_XDR
4536INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
4537            unsigned size, int op) {
4538  void *ctx;
4539  COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
4540  // FIXME: under ASan the call below may write to freed memory and corrupt
4541  // its metadata. See
4542  // https://github.com/google/sanitizers/issues/321.
4543  REAL(xdrmem_create)(xdrs, addr, size, op);
4544  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
4545  if (op == __sanitizer_XDR_ENCODE) {
4546    // It's not obvious how much data individual xdr_ routines write.
4547    // Simply unpoison the entire target buffer in advance.
4548    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
4549  }
4550}
4551
4552INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
4553  void *ctx;
4554  COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
4555  // FIXME: under ASan the call below may write to freed memory and corrupt
4556  // its metadata. See
4557  // https://github.com/google/sanitizers/issues/321.
4558  REAL(xdrstdio_create)(xdrs, file, op);
4559  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
4560}
4561
4562// FIXME: under ASan the call below may write to freed memory and corrupt
4563// its metadata. See
4564// https://github.com/google/sanitizers/issues/321.
4565#define XDR_INTERCEPTOR(F, T)                             \
4566  INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) {      \
4567    void *ctx;                                            \
4568    COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p);            \
4569    if (p && xdrs->x_op == __sanitizer_XDR_ENCODE)        \
4570      COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));  \
4571    int res = REAL(F)(xdrs, p);                           \
4572    if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
4573      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
4574    return res;                                           \
4575  }
4576
4577XDR_INTERCEPTOR(xdr_short, short)
4578XDR_INTERCEPTOR(xdr_u_short, unsigned short)
4579XDR_INTERCEPTOR(xdr_int, int)
4580XDR_INTERCEPTOR(xdr_u_int, unsigned)
4581XDR_INTERCEPTOR(xdr_long, long)
4582XDR_INTERCEPTOR(xdr_u_long, unsigned long)
4583XDR_INTERCEPTOR(xdr_hyper, long long)
4584XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
4585XDR_INTERCEPTOR(xdr_longlong_t, long long)
4586XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
4587XDR_INTERCEPTOR(xdr_int8_t, u8)
4588XDR_INTERCEPTOR(xdr_uint8_t, u8)
4589XDR_INTERCEPTOR(xdr_int16_t, u16)
4590XDR_INTERCEPTOR(xdr_uint16_t, u16)
4591XDR_INTERCEPTOR(xdr_int32_t, u32)
4592XDR_INTERCEPTOR(xdr_uint32_t, u32)
4593XDR_INTERCEPTOR(xdr_int64_t, u64)
4594XDR_INTERCEPTOR(xdr_uint64_t, u64)
4595XDR_INTERCEPTOR(xdr_quad_t, long long)
4596XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
4597XDR_INTERCEPTOR(xdr_bool, bool)
4598XDR_INTERCEPTOR(xdr_enum, int)
4599XDR_INTERCEPTOR(xdr_char, char)
4600XDR_INTERCEPTOR(xdr_u_char, unsigned char)
4601XDR_INTERCEPTOR(xdr_float, float)
4602XDR_INTERCEPTOR(xdr_double, double)
4603
4604// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
4605// wrapstring, sizeof
4606
4607INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
4608            unsigned maxsize) {
4609  void *ctx;
4610  COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
4611  if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
4612    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
4613    COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
4614    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
4615  }
4616  // FIXME: under ASan the call below may write to freed memory and corrupt
4617  // its metadata. See
4618  // https://github.com/google/sanitizers/issues/321.
4619  int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
4620  if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
4621    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
4622    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
4623    if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
4624  }
4625  return res;
4626}
4627
4628INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
4629            unsigned maxsize) {
4630  void *ctx;
4631  COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
4632  if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
4633    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
4634    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
4635  }
4636  // FIXME: under ASan the call below may write to freed memory and corrupt
4637  // its metadata. See
4638  // https://github.com/google/sanitizers/issues/321.
4639  int res = REAL(xdr_string)(xdrs, p, maxsize);
4640  if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
4641    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
4642    if (res && *p)
4643      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
4644  }
4645  return res;
4646}
4647
4648#define INIT_XDR                               \
4649  COMMON_INTERCEPT_FUNCTION(xdrmem_create);    \
4650  COMMON_INTERCEPT_FUNCTION(xdrstdio_create);  \
4651  COMMON_INTERCEPT_FUNCTION(xdr_short);        \
4652  COMMON_INTERCEPT_FUNCTION(xdr_u_short);      \
4653  COMMON_INTERCEPT_FUNCTION(xdr_int);          \
4654  COMMON_INTERCEPT_FUNCTION(xdr_u_int);        \
4655  COMMON_INTERCEPT_FUNCTION(xdr_long);         \
4656  COMMON_INTERCEPT_FUNCTION(xdr_u_long);       \
4657  COMMON_INTERCEPT_FUNCTION(xdr_hyper);        \
4658  COMMON_INTERCEPT_FUNCTION(xdr_u_hyper);      \
4659  COMMON_INTERCEPT_FUNCTION(xdr_longlong_t);   \
4660  COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
4661  COMMON_INTERCEPT_FUNCTION(xdr_int8_t);       \
4662  COMMON_INTERCEPT_FUNCTION(xdr_uint8_t);      \
4663  COMMON_INTERCEPT_FUNCTION(xdr_int16_t);      \
4664  COMMON_INTERCEPT_FUNCTION(xdr_uint16_t);     \
4665  COMMON_INTERCEPT_FUNCTION(xdr_int32_t);      \
4666  COMMON_INTERCEPT_FUNCTION(xdr_uint32_t);     \
4667  COMMON_INTERCEPT_FUNCTION(xdr_int64_t);      \
4668  COMMON_INTERCEPT_FUNCTION(xdr_uint64_t);     \
4669  COMMON_INTERCEPT_FUNCTION(xdr_quad_t);       \
4670  COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t);     \
4671  COMMON_INTERCEPT_FUNCTION(xdr_bool);         \
4672  COMMON_INTERCEPT_FUNCTION(xdr_enum);         \
4673  COMMON_INTERCEPT_FUNCTION(xdr_char);         \
4674  COMMON_INTERCEPT_FUNCTION(xdr_u_char);       \
4675  COMMON_INTERCEPT_FUNCTION(xdr_float);        \
4676  COMMON_INTERCEPT_FUNCTION(xdr_double);       \
4677  COMMON_INTERCEPT_FUNCTION(xdr_bytes);        \
4678  COMMON_INTERCEPT_FUNCTION(xdr_string);
4679#else
4680#define INIT_XDR
4681#endif  // SANITIZER_INTERCEPT_XDR
4682
4683#if SANITIZER_INTERCEPT_TSEARCH
4684INTERCEPTOR(void *, tsearch, void *key, void **rootp,
4685            int (*compar)(const void *, const void *)) {
4686  void *ctx;
4687  COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
4688  // FIXME: under ASan the call below may write to freed memory and corrupt
4689  // its metadata. See
4690  // https://github.com/google/sanitizers/issues/321.
4691  void *res = REAL(tsearch)(key, rootp, compar);
4692  if (res && *(void **)res == key)
4693    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
4694  return res;
4695}
4696#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
4697#else
4698#define INIT_TSEARCH
4699#endif
4700
4701#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
4702    SANITIZER_INTERCEPT_OPEN_MEMSTREAM
4703void unpoison_file(__sanitizer_FILE *fp) {
4704#if SANITIZER_HAS_STRUCT_FILE
4705  COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
4706  if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
4707    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
4708                                        fp->_IO_read_end - fp->_IO_read_base);
4709#endif  // SANITIZER_HAS_STRUCT_FILE
4710}
4711#endif
4712
4713#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
4714// These guys are called when a .c source is built with -O2.
4715INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
4716  void *ctx;
4717  COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
4718  int res = REAL(__uflow)(fp);
4719  unpoison_file(fp);
4720  return res;
4721}
4722INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
4723  void *ctx;
4724  COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
4725  int res = REAL(__underflow)(fp);
4726  unpoison_file(fp);
4727  return res;
4728}
4729INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
4730  void *ctx;
4731  COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
4732  int res = REAL(__overflow)(fp, ch);
4733  unpoison_file(fp);
4734  return res;
4735}
4736INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
4737  void *ctx;
4738  COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
4739  int res = REAL(__wuflow)(fp);
4740  unpoison_file(fp);
4741  return res;
4742}
4743INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
4744  void *ctx;
4745  COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
4746  int res = REAL(__wunderflow)(fp);
4747  unpoison_file(fp);
4748  return res;
4749}
4750INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
4751  void *ctx;
4752  COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
4753  int res = REAL(__woverflow)(fp, ch);
4754  unpoison_file(fp);
4755  return res;
4756}
4757#define INIT_LIBIO_INTERNALS               \
4758  COMMON_INTERCEPT_FUNCTION(__uflow);      \
4759  COMMON_INTERCEPT_FUNCTION(__underflow);  \
4760  COMMON_INTERCEPT_FUNCTION(__overflow);   \
4761  COMMON_INTERCEPT_FUNCTION(__wuflow);     \
4762  COMMON_INTERCEPT_FUNCTION(__wunderflow); \
4763  COMMON_INTERCEPT_FUNCTION(__woverflow);
4764#else
4765#define INIT_LIBIO_INTERNALS
4766#endif
4767
4768#if SANITIZER_INTERCEPT_FOPEN
4769INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
4770  void *ctx;
4771  COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
4772  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4773  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
4774  __sanitizer_FILE *res = REAL(fopen)(path, mode);
4775  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
4776  if (res) unpoison_file(res);
4777  return res;
4778}
4779INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
4780  void *ctx;
4781  COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
4782  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
4783  __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
4784  if (res) unpoison_file(res);
4785  return res;
4786}
4787INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
4788            __sanitizer_FILE *fp) {
4789  void *ctx;
4790  COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
4791  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4792  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
4793  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
4794  __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
4795  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
4796  if (res) unpoison_file(res);
4797  return res;
4798}
4799#define INIT_FOPEN                   \
4800  COMMON_INTERCEPT_FUNCTION(fopen);  \
4801  COMMON_INTERCEPT_FUNCTION(fdopen); \
4802  COMMON_INTERCEPT_FUNCTION(freopen);
4803#else
4804#define INIT_FOPEN
4805#endif
4806
4807#if SANITIZER_INTERCEPT_FOPEN64
4808INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
4809  void *ctx;
4810  COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
4811  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4812  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
4813  __sanitizer_FILE *res = REAL(fopen64)(path, mode);
4814  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
4815  if (res) unpoison_file(res);
4816  return res;
4817}
4818INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
4819            __sanitizer_FILE *fp) {
4820  void *ctx;
4821  COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
4822  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4823  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
4824  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
4825  __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
4826  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
4827  if (res) unpoison_file(res);
4828  return res;
4829}
4830#define INIT_FOPEN64                  \
4831  COMMON_INTERCEPT_FUNCTION(fopen64); \
4832  COMMON_INTERCEPT_FUNCTION(freopen64);
4833#else
4834#define INIT_FOPEN64
4835#endif
4836
4837#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
4838INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
4839  void *ctx;
4840  COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
4841  // FIXME: under ASan the call below may write to freed memory and corrupt
4842  // its metadata. See
4843  // https://github.com/google/sanitizers/issues/321.
4844  __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
4845  if (res) {
4846    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
4847    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
4848    unpoison_file(res);
4849    FileMetadata file = {ptr, sizeloc};
4850    SetInterceptorMetadata(res, file);
4851  }
4852  return res;
4853}
4854INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
4855            SIZE_T *sizeloc) {
4856  void *ctx;
4857  COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
4858  __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
4859  if (res) {
4860    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
4861    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
4862    unpoison_file(res);
4863    FileMetadata file = {(char **)ptr, sizeloc};
4864    SetInterceptorMetadata(res, file);
4865  }
4866  return res;
4867}
4868INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
4869            const char *mode) {
4870  void *ctx;
4871  COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
4872  // FIXME: under ASan the call below may write to freed memory and corrupt
4873  // its metadata. See
4874  // https://github.com/google/sanitizers/issues/321.
4875  __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
4876  if (res) unpoison_file(res);
4877  return res;
4878}
4879#define INIT_OPEN_MEMSTREAM                   \
4880  COMMON_INTERCEPT_FUNCTION(open_memstream);  \
4881  COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
4882  COMMON_INTERCEPT_FUNCTION(fmemopen);
4883#else
4884#define INIT_OPEN_MEMSTREAM
4885#endif
4886
4887#if SANITIZER_INTERCEPT_OBSTACK
4888static void initialize_obstack(__sanitizer_obstack *obstack) {
4889  COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
4890  if (obstack->chunk)
4891    COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
4892                                        sizeof(*obstack->chunk));
4893}
4894
4895INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
4896            int align, void *(*alloc_fn)(uptr arg, uptr sz),
4897            void (*free_fn)(uptr arg, void *p)) {
4898  void *ctx;
4899  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
4900                           free_fn);
4901  int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
4902  if (res) initialize_obstack(obstack);
4903  return res;
4904}
4905INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
4906            int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
4907  void *ctx;
4908  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
4909                           free_fn);
4910  int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
4911  if (res) initialize_obstack(obstack);
4912  return res;
4913}
4914INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
4915  void *ctx;
4916  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
4917  REAL(_obstack_newchunk)(obstack, length);
4918  if (obstack->chunk)
4919    COMMON_INTERCEPTOR_INITIALIZE_RANGE(
4920        obstack->chunk, obstack->next_free - (char *)obstack->chunk);
4921}
4922#define INIT_OBSTACK                           \
4923  COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
4924  COMMON_INTERCEPT_FUNCTION(_obstack_begin);   \
4925  COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
4926#else
4927#define INIT_OBSTACK
4928#endif
4929
4930#if SANITIZER_INTERCEPT_FFLUSH
4931INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
4932  void *ctx;
4933  COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
4934  int res = REAL(fflush)(fp);
4935  // FIXME: handle fp == NULL
4936  if (fp) {
4937    const FileMetadata *m = GetInterceptorMetadata(fp);
4938    if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
4939  }
4940  return res;
4941}
4942#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
4943#else
4944#define INIT_FFLUSH
4945#endif
4946
4947#if SANITIZER_INTERCEPT_FCLOSE
4948INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
4949  void *ctx;
4950  COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
4951  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
4952  const FileMetadata *m = GetInterceptorMetadata(fp);
4953  int res = REAL(fclose)(fp);
4954  if (m) {
4955    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
4956    DeleteInterceptorMetadata(fp);
4957  }
4958  return res;
4959}
4960#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
4961#else
4962#define INIT_FCLOSE
4963#endif
4964
4965#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
4966INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
4967  void *ctx;
4968  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
4969  if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
4970  COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
4971  void *res = REAL(dlopen)(filename, flag);
4972  COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
4973  return res;
4974}
4975
4976INTERCEPTOR(int, dlclose, void *handle) {
4977  void *ctx;
4978  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
4979  int res = REAL(dlclose)(handle);
4980  COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
4981  return res;
4982}
4983#define INIT_DLOPEN_DLCLOSE          \
4984  COMMON_INTERCEPT_FUNCTION(dlopen); \
4985  COMMON_INTERCEPT_FUNCTION(dlclose);
4986#else
4987#define INIT_DLOPEN_DLCLOSE
4988#endif
4989
4990#if SANITIZER_INTERCEPT_GETPASS
4991INTERCEPTOR(char *, getpass, const char *prompt) {
4992  void *ctx;
4993  COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
4994  if (prompt)
4995    COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
4996  char *res = REAL(getpass)(prompt);
4997  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
4998  return res;
4999}
5000
5001#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
5002#else
5003#define INIT_GETPASS
5004#endif
5005
5006#if SANITIZER_INTERCEPT_TIMERFD
5007INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
5008            void *old_value) {
5009  void *ctx;
5010  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
5011                           old_value);
5012  COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
5013  int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
5014  if (res != -1 && old_value)
5015    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
5016  return res;
5017}
5018
5019INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
5020  void *ctx;
5021  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
5022  int res = REAL(timerfd_gettime)(fd, curr_value);
5023  if (res != -1 && curr_value)
5024    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
5025  return res;
5026}
5027#define INIT_TIMERFD                          \
5028  COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
5029  COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
5030#else
5031#define INIT_TIMERFD
5032#endif
5033
5034#if SANITIZER_INTERCEPT_MLOCKX
5035// Linux kernel has a bug that leads to kernel deadlock if a process
5036// maps TBs of memory and then calls mlock().
5037static void MlockIsUnsupported() {
5038  static atomic_uint8_t printed;
5039  if (atomic_exchange(&printed, 1, memory_order_relaxed))
5040    return;
5041  VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
5042          SanitizerToolName);
5043}
5044
5045INTERCEPTOR(int, mlock, const void *addr, uptr len) {
5046  MlockIsUnsupported();
5047  return 0;
5048}
5049
5050INTERCEPTOR(int, munlock, const void *addr, uptr len) {
5051  MlockIsUnsupported();
5052  return 0;
5053}
5054
5055INTERCEPTOR(int, mlockall, int flags) {
5056  MlockIsUnsupported();
5057  return 0;
5058}
5059
5060INTERCEPTOR(int, munlockall, void) {
5061  MlockIsUnsupported();
5062  return 0;
5063}
5064
5065#define INIT_MLOCKX                                                            \
5066  COMMON_INTERCEPT_FUNCTION(mlock);                                            \
5067  COMMON_INTERCEPT_FUNCTION(munlock);                                          \
5068  COMMON_INTERCEPT_FUNCTION(mlockall);                                         \
5069  COMMON_INTERCEPT_FUNCTION(munlockall);
5070
5071#else
5072#define INIT_MLOCKX
5073#endif  // SANITIZER_INTERCEPT_MLOCKX
5074
5075#if SANITIZER_INTERCEPT_FOPENCOOKIE
5076struct WrappedCookie {
5077  void *real_cookie;
5078  __sanitizer_cookie_io_functions_t real_io_funcs;
5079};
5080
5081static uptr wrapped_read(void *cookie, char *buf, uptr size) {
5082  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
5083  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
5084  __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
5085  return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
5086}
5087
5088static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
5089  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
5090  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
5091  __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
5092  return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
5093}
5094
5095static int wrapped_seek(void *cookie, u64 *offset, int whence) {
5096  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
5097  COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
5098  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
5099  __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
5100  return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
5101                   : -1;
5102}
5103
5104static int wrapped_close(void *cookie) {
5105  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
5106  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
5107  __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
5108  int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
5109  InternalFree(wrapped_cookie);
5110  return res;
5111}
5112
5113INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
5114            __sanitizer_cookie_io_functions_t io_funcs) {
5115  void *ctx;
5116  COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
5117  WrappedCookie *wrapped_cookie =
5118      (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
5119  wrapped_cookie->real_cookie = cookie;
5120  wrapped_cookie->real_io_funcs = io_funcs;
5121  __sanitizer_FILE *res =
5122      REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
5123                                               wrapped_seek, wrapped_close});
5124  return res;
5125}
5126
5127#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
5128#else
5129#define INIT_FOPENCOOKIE
5130#endif  // SANITIZER_INTERCEPT_FOPENCOOKIE
5131
5132#if SANITIZER_INTERCEPT_SEM
5133INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
5134  void *ctx;
5135  COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
5136  // Workaround a bug in glibc's "old" semaphore implementation by
5137  // zero-initializing the sem_t contents. This has to be done here because
5138  // interceptors bind to the lowest symbols version by default, hitting the
5139  // buggy code path while the non-sanitized build of the same code works fine.
5140  REAL(memset)(s, 0, sizeof(*s));
5141  int res = REAL(sem_init)(s, pshared, value);
5142  return res;
5143}
5144
5145INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
5146  void *ctx;
5147  COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
5148  int res = REAL(sem_destroy)(s);
5149  return res;
5150}
5151
5152INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
5153  void *ctx;
5154  COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
5155  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
5156  if (res == 0) {
5157    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
5158  }
5159  return res;
5160}
5161
5162INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
5163  void *ctx;
5164  COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
5165  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
5166  if (res == 0) {
5167    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
5168  }
5169  return res;
5170}
5171
5172INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
5173  void *ctx;
5174  COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
5175  COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
5176  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
5177  if (res == 0) {
5178    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
5179  }
5180  return res;
5181}
5182
5183INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
5184  void *ctx;
5185  COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
5186  COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
5187  int res = REAL(sem_post)(s);
5188  return res;
5189}
5190
5191INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
5192  void *ctx;
5193  COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
5194  int res = REAL(sem_getvalue)(s, sval);
5195  if (res == 0) {
5196    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
5197    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
5198  }
5199  return res;
5200}
5201#define INIT_SEM                                                               \
5202  COMMON_INTERCEPT_FUNCTION(sem_init);                                         \
5203  COMMON_INTERCEPT_FUNCTION(sem_destroy);                                      \
5204  COMMON_INTERCEPT_FUNCTION(sem_wait);                                         \
5205  COMMON_INTERCEPT_FUNCTION(sem_trywait);                                      \
5206  COMMON_INTERCEPT_FUNCTION(sem_timedwait);                                    \
5207  COMMON_INTERCEPT_FUNCTION(sem_post);                                         \
5208  COMMON_INTERCEPT_FUNCTION(sem_getvalue);
5209#else
5210#define INIT_SEM
5211#endif // SANITIZER_INTERCEPT_SEM
5212
5213#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
5214INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
5215  void *ctx;
5216  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
5217  int res = REAL(pthread_setcancelstate)(state, oldstate);
5218  if (res == 0)
5219    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
5220  return res;
5221}
5222
5223INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
5224  void *ctx;
5225  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
5226  int res = REAL(pthread_setcanceltype)(type, oldtype);
5227  if (res == 0)
5228    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
5229  return res;
5230}
5231#define INIT_PTHREAD_SETCANCEL                                                 \
5232  COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate);                           \
5233  COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
5234#else
5235#define INIT_PTHREAD_SETCANCEL
5236#endif
5237
5238#if SANITIZER_INTERCEPT_MINCORE
5239INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
5240  void *ctx;
5241  COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
5242  int res = REAL(mincore)(addr, length, vec);
5243  if (res == 0) {
5244    uptr page_size = GetPageSizeCached();
5245    uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
5246    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
5247  }
5248  return res;
5249}
5250#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
5251#else
5252#define INIT_MINCORE
5253#endif
5254
5255#if SANITIZER_INTERCEPT_PROCESS_VM_READV
5256INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
5257            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
5258            uptr flags) {
5259  void *ctx;
5260  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
5261                           remote_iov, riovcnt, flags);
5262  SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
5263                                       riovcnt, flags);
5264  if (res > 0)
5265    write_iovec(ctx, local_iov, liovcnt, res);
5266  return res;
5267}
5268
5269INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
5270            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
5271            uptr flags) {
5272  void *ctx;
5273  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
5274                           remote_iov, riovcnt, flags);
5275  SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
5276                                        riovcnt, flags);
5277  if (res > 0)
5278    read_iovec(ctx, local_iov, liovcnt, res);
5279  return res;
5280}
5281#define INIT_PROCESS_VM_READV                                                  \
5282  COMMON_INTERCEPT_FUNCTION(process_vm_readv);                                 \
5283  COMMON_INTERCEPT_FUNCTION(process_vm_writev);
5284#else
5285#define INIT_PROCESS_VM_READV
5286#endif
5287
5288#if SANITIZER_INTERCEPT_CTERMID
5289INTERCEPTOR(char *, ctermid, char *s) {
5290  void *ctx;
5291  COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
5292  char *res = REAL(ctermid)(s);
5293  if (res) {
5294    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
5295  }
5296  return res;
5297}
5298#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
5299#else
5300#define INIT_CTERMID
5301#endif
5302
5303#if SANITIZER_INTERCEPT_CTERMID_R
5304INTERCEPTOR(char *, ctermid_r, char *s) {
5305  void *ctx;
5306  COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
5307  char *res = REAL(ctermid_r)(s);
5308  if (res) {
5309    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
5310  }
5311  return res;
5312}
5313#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
5314#else
5315#define INIT_CTERMID_R
5316#endif
5317
5318static void InitializeCommonInterceptors() {
5319  static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
5320  interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
5321
5322  INIT_TEXTDOMAIN;
5323  INIT_STRCMP;
5324  INIT_STRNCMP;
5325  INIT_STRCASECMP;
5326  INIT_STRNCASECMP;
5327  INIT_STRSTR;
5328  INIT_STRCASESTR;
5329  INIT_STRSPN;
5330  INIT_STRPBRK;
5331  INIT_MEMCHR;
5332  INIT_MEMCMP;
5333  INIT_MEMRCHR;
5334  INIT_READ;
5335  INIT_PREAD;
5336  INIT_PREAD64;
5337  INIT_READV;
5338  INIT_PREADV;
5339  INIT_PREADV64;
5340  INIT_WRITE;
5341  INIT_PWRITE;
5342  INIT_PWRITE64;
5343  INIT_WRITEV;
5344  INIT_PWRITEV;
5345  INIT_PWRITEV64;
5346  INIT_PRCTL;
5347  INIT_LOCALTIME_AND_FRIENDS;
5348  INIT_STRPTIME;
5349  INIT_SCANF;
5350  INIT_ISOC99_SCANF;
5351  INIT_PRINTF;
5352  INIT_PRINTF_L;
5353  INIT_ISOC99_PRINTF;
5354  INIT_FREXP;
5355  INIT_FREXPF_FREXPL;
5356  INIT_GETPWNAM_AND_FRIENDS;
5357  INIT_GETPWNAM_R_AND_FRIENDS;
5358  INIT_GETPWENT;
5359  INIT_FGETPWENT;
5360  INIT_GETPWENT_R;
5361  INIT_SETPWENT;
5362  INIT_CLOCK_GETTIME;
5363  INIT_GETITIMER;
5364  INIT_TIME;
5365  INIT_GLOB;
5366  INIT_WAIT;
5367  INIT_WAIT4;
5368  INIT_INET;
5369  INIT_PTHREAD_GETSCHEDPARAM;
5370  INIT_GETADDRINFO;
5371  INIT_GETNAMEINFO;
5372  INIT_GETSOCKNAME;
5373  INIT_GETHOSTBYNAME;
5374  INIT_GETHOSTBYNAME_R;
5375  INIT_GETHOSTBYNAME2_R;
5376  INIT_GETHOSTBYADDR_R;
5377  INIT_GETHOSTENT_R;
5378  INIT_GETSOCKOPT;
5379  INIT_ACCEPT;
5380  INIT_ACCEPT4;
5381  INIT_MODF;
5382  INIT_RECVMSG;
5383  INIT_GETPEERNAME;
5384  INIT_IOCTL;
5385  INIT_INET_ATON;
5386  INIT_SYSINFO;
5387  INIT_READDIR;
5388  INIT_READDIR64;
5389  INIT_PTRACE;
5390  INIT_SETLOCALE;
5391  INIT_GETCWD;
5392  INIT_GET_CURRENT_DIR_NAME;
5393  INIT_STRTOIMAX;
5394  INIT_MBSTOWCS;
5395  INIT_MBSNRTOWCS;
5396  INIT_WCSTOMBS;
5397  INIT_WCSNRTOMBS;
5398  INIT_WCRTOMB;
5399  INIT_TCGETATTR;
5400  INIT_REALPATH;
5401  INIT_CANONICALIZE_FILE_NAME;
5402  INIT_CONFSTR;
5403  INIT_SCHED_GETAFFINITY;
5404  INIT_SCHED_GETPARAM;
5405  INIT_STRERROR;
5406  INIT_STRERROR_R;
5407  INIT_XPG_STRERROR_R;
5408  INIT_SCANDIR;
5409  INIT_SCANDIR64;
5410  INIT_GETGROUPS;
5411  INIT_POLL;
5412  INIT_PPOLL;
5413  INIT_WORDEXP;
5414  INIT_SIGWAIT;
5415  INIT_SIGWAITINFO;
5416  INIT_SIGTIMEDWAIT;
5417  INIT_SIGSETOPS;
5418  INIT_SIGPENDING;
5419  INIT_SIGPROCMASK;
5420  INIT_BACKTRACE;
5421  INIT__EXIT;
5422  INIT_PTHREAD_MUTEX_LOCK;
5423  INIT_PTHREAD_MUTEX_UNLOCK;
5424  INIT_GETMNTENT;
5425  INIT_GETMNTENT_R;
5426  INIT_STATFS;
5427  INIT_STATFS64;
5428  INIT_STATVFS;
5429  INIT_STATVFS64;
5430  INIT_INITGROUPS;
5431  INIT_ETHER_NTOA_ATON;
5432  INIT_ETHER_HOST;
5433  INIT_ETHER_R;
5434  INIT_SHMCTL;
5435  INIT_RANDOM_R;
5436  INIT_PTHREAD_ATTR_GET;
5437  INIT_PTHREAD_ATTR_GETINHERITSCHED;
5438  INIT_PTHREAD_ATTR_GETAFFINITY_NP;
5439  INIT_PTHREAD_MUTEXATTR_GETPSHARED;
5440  INIT_PTHREAD_MUTEXATTR_GETTYPE;
5441  INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
5442  INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
5443  INIT_PTHREAD_MUTEXATTR_GETROBUST;
5444  INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
5445  INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
5446  INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
5447  INIT_PTHREAD_CONDATTR_GETPSHARED;
5448  INIT_PTHREAD_CONDATTR_GETCLOCK;
5449  INIT_PTHREAD_BARRIERATTR_GETPSHARED;
5450  INIT_TMPNAM;
5451  INIT_TMPNAM_R;
5452  INIT_TEMPNAM;
5453  INIT_PTHREAD_SETNAME_NP;
5454  INIT_SINCOS;
5455  INIT_REMQUO;
5456  INIT_LGAMMA;
5457  INIT_LGAMMA_R;
5458  INIT_LGAMMAL_R;
5459  INIT_DRAND48_R;
5460  INIT_RAND_R;
5461  INIT_GETLINE;
5462  INIT_ICONV;
5463  INIT_TIMES;
5464  INIT_TLS_GET_ADDR;
5465  INIT_LISTXATTR;
5466  INIT_GETXATTR;
5467  INIT_GETRESID;
5468  INIT_GETIFADDRS;
5469  INIT_IF_INDEXTONAME;
5470  INIT_CAPGET;
5471  INIT_AEABI_MEM;
5472  INIT___BZERO;
5473  INIT_FTIME;
5474  INIT_XDR;
5475  INIT_TSEARCH;
5476  INIT_LIBIO_INTERNALS;
5477  INIT_FOPEN;
5478  INIT_FOPEN64;
5479  INIT_OPEN_MEMSTREAM;
5480  INIT_OBSTACK;
5481  INIT_FFLUSH;
5482  INIT_FCLOSE;
5483  INIT_DLOPEN_DLCLOSE;
5484  INIT_GETPASS;
5485  INIT_TIMERFD;
5486  INIT_MLOCKX;
5487  INIT_FOPENCOOKIE;
5488  INIT_SEM;
5489  INIT_PTHREAD_SETCANCEL;
5490  INIT_MINCORE;
5491  INIT_PROCESS_VM_READV;
5492  INIT_CTERMID;
5493  INIT_CTERMID_R;
5494}
5495