sanitizer_common_interceptors.inc revision 11f5309ec1bf13430c8a3a16f177d9e8e1190e38
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_READ_RANGE
17//   COMMON_INTERCEPTOR_WRITE_RANGE
18//   COMMON_INTERCEPTOR_INITIALIZE_RANGE
19//   COMMON_INTERCEPTOR_FD_ACQUIRE
20//   COMMON_INTERCEPTOR_FD_RELEASE
21//   COMMON_INTERCEPTOR_FD_ACCESS
22//   COMMON_INTERCEPTOR_SET_THREAD_NAME
23//   COMMON_INTERCEPTOR_ON_EXIT
24//   COMMON_INTERCEPTOR_MUTEX_LOCK
25//   COMMON_INTERCEPTOR_MUTEX_UNLOCK
26//   COMMON_INTERCEPTOR_MUTEX_REPAIR
27//   COMMON_INTERCEPTOR_SET_PTHREAD_NAME
28//===----------------------------------------------------------------------===//
29#include "interception/interception.h"
30#include "sanitizer_platform_interceptors.h"
31
32#include <stdarg.h>
33
34#if SANITIZER_WINDOWS
35#define va_copy(dst, src) ((dst) = (src))
36#endif // _WIN32
37
38#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
39#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, p, size) {}
40#endif
41
42#ifndef COMMON_INTERCEPTOR_FD_ACCESS
43#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
44#endif
45
46#ifndef COMMON_INTERCEPTOR_MUTEX_LOCK
47#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) {}
48#endif
49
50#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
51#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
52#endif
53
54#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
55#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
56#endif
57
58#if SANITIZER_INTERCEPT_STRCMP
59static inline int CharCmpX(unsigned char c1, unsigned char c2) {
60  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
61}
62
63INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
64  void *ctx;
65  COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
66  unsigned char c1, c2;
67  uptr i;
68  for (i = 0;; i++) {
69    c1 = (unsigned char)s1[i];
70    c2 = (unsigned char)s2[i];
71    if (c1 != c2 || c1 == '\0') break;
72  }
73  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
74  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
75  return CharCmpX(c1, c2);
76}
77
78INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
79  void *ctx;
80  COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
81  unsigned char c1 = 0, c2 = 0;
82  uptr i;
83  for (i = 0; i < size; i++) {
84    c1 = (unsigned char)s1[i];
85    c2 = (unsigned char)s2[i];
86    if (c1 != c2 || c1 == '\0') break;
87  }
88  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
89  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
90  return CharCmpX(c1, c2);
91}
92
93#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
94#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
95#else
96#define INIT_STRCMP
97#define INIT_STRNCMP
98#endif
99
100#if SANITIZER_INTERCEPT_STRCASECMP
101static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
102  int c1_low = ToLower(c1);
103  int c2_low = ToLower(c2);
104  return c1_low - c2_low;
105}
106
107INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
108  void *ctx;
109  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
110  unsigned char c1 = 0, c2 = 0;
111  uptr i;
112  for (i = 0;; i++) {
113    c1 = (unsigned char)s1[i];
114    c2 = (unsigned char)s2[i];
115    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
116  }
117  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
118  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
119  return CharCaseCmp(c1, c2);
120}
121
122INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
123  void *ctx;
124  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
125  unsigned char c1 = 0, c2 = 0;
126  uptr i;
127  for (i = 0; i < n; i++) {
128    c1 = (unsigned char)s1[i];
129    c2 = (unsigned char)s2[i];
130    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
131  }
132  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
133  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
134  return CharCaseCmp(c1, c2);
135}
136
137#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
138#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
139#else
140#define INIT_STRCASECMP
141#define INIT_STRNCASECMP
142#endif
143
144#if SANITIZER_INTERCEPT_FREXP
145INTERCEPTOR(double, frexp, double x, int *exp) {
146  void *ctx;
147  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
148  double res = REAL(frexp)(x, exp);
149  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
150  return res;
151}
152
153#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
154#else
155#define INIT_FREXP
156#endif  // SANITIZER_INTERCEPT_FREXP
157
158#if SANITIZER_INTERCEPT_FREXPF_FREXPL
159INTERCEPTOR(float, frexpf, float x, int *exp) {
160  void *ctx;
161  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
162  float res = REAL(frexpf)(x, exp);
163  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
164  return res;
165}
166
167INTERCEPTOR(long double, frexpl, long double x, int *exp) {
168  void *ctx;
169  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
170  long double res = REAL(frexpl)(x, exp);
171  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
172  return res;
173}
174
175#define INIT_FREXPF_FREXPL           \
176  COMMON_INTERCEPT_FUNCTION(frexpf); \
177  COMMON_INTERCEPT_FUNCTION(frexpl)
178#else
179#define INIT_FREXPF_FREXPL
180#endif  // SANITIZER_INTERCEPT_FREXPF_FREXPL
181
182#if SI_NOT_WINDOWS
183static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
184                        SIZE_T iovlen, SIZE_T maxlen) {
185  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
186    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
187    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
188    maxlen -= sz;
189  }
190}
191
192static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
193                       SIZE_T iovlen, SIZE_T maxlen) {
194  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
195  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
196    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
197    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
198    maxlen -= sz;
199  }
200}
201#endif
202
203#if SANITIZER_INTERCEPT_READ
204INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
205  void *ctx;
206  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
207  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
208  SSIZE_T res = REAL(read)(fd, ptr, count);
209  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
210  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
211  return res;
212}
213#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
214#else
215#define INIT_READ
216#endif
217
218#if SANITIZER_INTERCEPT_PREAD
219INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
220  void *ctx;
221  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
222  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
223  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
224  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
225  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
226  return res;
227}
228#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
229#else
230#define INIT_PREAD
231#endif
232
233#if SANITIZER_INTERCEPT_PREAD64
234INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
235  void *ctx;
236  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
237  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
238  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
239  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
240  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
241  return res;
242}
243#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
244#else
245#define INIT_PREAD64
246#endif
247
248#if SANITIZER_INTERCEPT_READV
249INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
250                        int iovcnt) {
251  void *ctx;
252  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
253  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
254  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
255  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
256  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
257  return res;
258}
259#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
260#else
261#define INIT_READV
262#endif
263
264#if SANITIZER_INTERCEPT_PREADV
265INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
266            OFF_T offset) {
267  void *ctx;
268  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
269  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
270  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
271  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
272  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
273  return res;
274}
275#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
276#else
277#define INIT_PREADV
278#endif
279
280#if SANITIZER_INTERCEPT_PREADV64
281INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
282            OFF64_T offset) {
283  void *ctx;
284  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
285  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
286  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
287  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
288  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
289  return res;
290}
291#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
292#else
293#define INIT_PREADV64
294#endif
295
296#if SANITIZER_INTERCEPT_WRITE
297INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
298  void *ctx;
299  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
300  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
301  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
302  SSIZE_T res = REAL(write)(fd, ptr, count);
303  // FIXME: this check should be _before_ the call to REAL(write), not after
304  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
305  return res;
306}
307#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
308#else
309#define INIT_WRITE
310#endif
311
312#if SANITIZER_INTERCEPT_PWRITE
313INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
314  void *ctx;
315  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
316  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
317  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
318  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
319  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
320  return res;
321}
322#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
323#else
324#define INIT_PWRITE
325#endif
326
327#if SANITIZER_INTERCEPT_PWRITE64
328INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
329            OFF64_T offset) {
330  void *ctx;
331  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
332  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
333  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
334  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
335  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
336  return res;
337}
338#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
339#else
340#define INIT_PWRITE64
341#endif
342
343#if SANITIZER_INTERCEPT_WRITEV
344INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
345                        int iovcnt) {
346  void *ctx;
347  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
348  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
349  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
350  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
351  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
352  return res;
353}
354#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
355#else
356#define INIT_WRITEV
357#endif
358
359#if SANITIZER_INTERCEPT_PWRITEV
360INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
361            OFF_T offset) {
362  void *ctx;
363  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
364  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
365  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
366  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
367  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
368  return res;
369}
370#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
371#else
372#define INIT_PWRITEV
373#endif
374
375#if SANITIZER_INTERCEPT_PWRITEV64
376INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
377            OFF64_T offset) {
378  void *ctx;
379  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
380  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
381  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
382  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
383  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
384  return res;
385}
386#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
387#else
388#define INIT_PWRITEV64
389#endif
390
391#if SANITIZER_INTERCEPT_PRCTL
392INTERCEPTOR(int, prctl, int option, unsigned long arg2,
393            unsigned long arg3,                        // NOLINT
394            unsigned long arg4, unsigned long arg5) {  // NOLINT
395  void *ctx;
396  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
397  static const int PR_SET_NAME = 15;
398  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
399  if (option == PR_SET_NAME) {
400    char buff[16];
401    internal_strncpy(buff, (char *)arg2, 15);
402    buff[15] = 0;
403    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
404  }
405  return res;
406}
407#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
408#else
409#define INIT_PRCTL
410#endif  // SANITIZER_INTERCEPT_PRCTL
411
412#if SANITIZER_INTERCEPT_TIME
413INTERCEPTOR(unsigned long, time, unsigned long *t) {
414  void *ctx;
415  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
416  unsigned long res = REAL(time)(t);
417  if (t && res != (unsigned long)-1) {
418    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
419  }
420  return res;
421}
422#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
423#else
424#define INIT_TIME
425#endif  // SANITIZER_INTERCEPT_TIME
426
427#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
428static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
429  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
430  if (tm->tm_zone) {
431    // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
432    // can point to shared memory and tsan would report a data race.
433    COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, tm->tm_zone,
434                                        REAL(strlen(tm->tm_zone)) + 1);
435  }
436}
437INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
438  void *ctx;
439  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
440  __sanitizer_tm *res = REAL(localtime)(timep);
441  if (res) {
442    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
443    unpoison_tm(ctx, res);
444  }
445  return res;
446}
447INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
448  void *ctx;
449  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
450  __sanitizer_tm *res = REAL(localtime_r)(timep, result);
451  if (res) {
452    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
453    unpoison_tm(ctx, res);
454  }
455  return res;
456}
457INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
458  void *ctx;
459  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
460  __sanitizer_tm *res = REAL(gmtime)(timep);
461  if (res) {
462    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
463    unpoison_tm(ctx, res);
464  }
465  return res;
466}
467INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
468  void *ctx;
469  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
470  __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
471  if (res) {
472    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
473    unpoison_tm(ctx, res);
474  }
475  return res;
476}
477INTERCEPTOR(char *, ctime, unsigned long *timep) {
478  void *ctx;
479  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
480  char *res = REAL(ctime)(timep);
481  if (res) {
482    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
483    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
484  }
485  return res;
486}
487INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
488  void *ctx;
489  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
490  char *res = REAL(ctime_r)(timep, result);
491  if (res) {
492    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
493    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
494  }
495  return res;
496}
497INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
498  void *ctx;
499  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
500  char *res = REAL(asctime)(tm);
501  if (res) {
502    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
503    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
504  }
505  return res;
506}
507INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
508  void *ctx;
509  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
510  char *res = REAL(asctime_r)(tm, result);
511  if (res) {
512    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
513    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
514  }
515  return res;
516}
517#define INIT_LOCALTIME_AND_FRIENDS        \
518  COMMON_INTERCEPT_FUNCTION(localtime);   \
519  COMMON_INTERCEPT_FUNCTION(localtime_r); \
520  COMMON_INTERCEPT_FUNCTION(gmtime);      \
521  COMMON_INTERCEPT_FUNCTION(gmtime_r);    \
522  COMMON_INTERCEPT_FUNCTION(ctime);       \
523  COMMON_INTERCEPT_FUNCTION(ctime_r);     \
524  COMMON_INTERCEPT_FUNCTION(asctime);     \
525  COMMON_INTERCEPT_FUNCTION(asctime_r);
526#else
527#define INIT_LOCALTIME_AND_FRIENDS
528#endif  // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
529
530#if SANITIZER_INTERCEPT_STRPTIME
531INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
532  void *ctx;
533  COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
534  if (format)
535    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
536  char *res = REAL(strptime)(s, format, tm);
537  if (res) {
538    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, res - s);
539    // Do not call unpoison_tm here, because strptime does not, in fact,
540    // initialize the entire struct tm. For example, tm_zone pointer is left
541    // uninitialized.
542    if (tm) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
543  }
544  return res;
545}
546#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
547#else
548#define INIT_STRPTIME
549#endif
550
551#if SANITIZER_INTERCEPT_SCANF
552
553#include "sanitizer_common_interceptors_scanf.inc"
554
555#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
556  {                                                                            \
557    void *ctx;                                                                 \
558    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
559    va_list aq;                                                                \
560    va_copy(aq, ap);                                                           \
561    int res = REAL(vname)(__VA_ARGS__);                                        \
562    if (res > 0)                                                               \
563      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
564    va_end(aq);                                                                \
565    return res;                                                                \
566  }
567
568INTERCEPTOR(int, vscanf, const char *format, va_list ap)
569VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
570
571INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
572VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
573
574INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
575VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
576
577#if SANITIZER_INTERCEPT_ISOC99_SCANF
578INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
579VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
580
581INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
582            va_list ap)
583VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
584
585INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
586VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
587#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF
588
589#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
590  {                                                                            \
591    void *ctx;                                                                 \
592    va_list ap;                                                                \
593    va_start(ap, format);                                                      \
594    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap);                     \
595    int res = vname(__VA_ARGS__, ap);                                          \
596    va_end(ap);                                                                \
597    return res;                                                                \
598  }
599
600INTERCEPTOR(int, scanf, const char *format, ...)
601SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
602
603INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
604SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
605
606INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
607SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
608
609#if SANITIZER_INTERCEPT_ISOC99_SCANF
610INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
611SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
612
613INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
614SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
615
616INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
617SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
618#endif
619
620#endif
621
622#if SANITIZER_INTERCEPT_SCANF
623#define INIT_SCANF                    \
624  COMMON_INTERCEPT_FUNCTION(scanf);   \
625  COMMON_INTERCEPT_FUNCTION(sscanf);  \
626  COMMON_INTERCEPT_FUNCTION(fscanf);  \
627  COMMON_INTERCEPT_FUNCTION(vscanf);  \
628  COMMON_INTERCEPT_FUNCTION(vsscanf); \
629  COMMON_INTERCEPT_FUNCTION(vfscanf);
630#else
631#define INIT_SCANF
632#endif
633
634#if SANITIZER_INTERCEPT_ISOC99_SCANF
635#define INIT_ISOC99_SCANF                      \
636  COMMON_INTERCEPT_FUNCTION(__isoc99_scanf);   \
637  COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf);  \
638  COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf);  \
639  COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf);  \
640  COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
641  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
642#else
643#define INIT_ISOC99_SCANF
644#endif
645
646#if SANITIZER_INTERCEPT_IOCTL
647#include "sanitizer_common_interceptors_ioctl.inc"
648INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
649  void *ctx;
650  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
651
652  CHECK(ioctl_initialized);
653
654  // Note: TSan does not use common flags, and they are zero-initialized.
655  // This effectively disables ioctl handling in TSan.
656  if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
657
658  const ioctl_desc *desc = ioctl_lookup(request);
659  if (!desc) Printf("WARNING: unknown ioctl %x\n", request);
660
661  if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
662  int res = REAL(ioctl)(d, request, arg);
663  // FIXME: some ioctls have different return values for success and failure.
664  if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
665  return res;
666}
667#define INIT_IOCTL \
668  ioctl_init();    \
669  COMMON_INTERCEPT_FUNCTION(ioctl);
670#else
671#define INIT_IOCTL
672#endif
673
674#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
675INTERCEPTOR(void *, getpwnam, const char *name) {
676  void *ctx;
677  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
678  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
679  void *res = REAL(getpwnam)(name);
680  if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
681  return res;
682}
683INTERCEPTOR(void *, getpwuid, u32 uid) {
684  void *ctx;
685  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
686  void *res = REAL(getpwuid)(uid);
687  if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
688  return res;
689}
690INTERCEPTOR(void *, getgrnam, const char *name) {
691  void *ctx;
692  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
693  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
694  void *res = REAL(getgrnam)(name);
695  if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
696  return res;
697}
698INTERCEPTOR(void *, getgrgid, u32 gid) {
699  void *ctx;
700  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
701  void *res = REAL(getgrgid)(gid);
702  if (res != 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
703  return res;
704}
705#define INIT_GETPWNAM_AND_FRIENDS      \
706  COMMON_INTERCEPT_FUNCTION(getpwnam); \
707  COMMON_INTERCEPT_FUNCTION(getpwuid); \
708  COMMON_INTERCEPT_FUNCTION(getgrnam); \
709  COMMON_INTERCEPT_FUNCTION(getgrgid);
710#else
711#define INIT_GETPWNAM_AND_FRIENDS
712#endif
713
714#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
715INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd, char *buf,
716            SIZE_T buflen, void **result) {
717  void *ctx;
718  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
719  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
720  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
721  if (!res) {
722    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
723    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
724  }
725  return res;
726}
727INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd, char *buf, SIZE_T buflen,
728            void **result) {
729  void *ctx;
730  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
731  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
732  if (!res) {
733    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
734    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
735  }
736  return res;
737}
738INTERCEPTOR(int, getgrnam_r, const char *name, void *grp, char *buf,
739            SIZE_T buflen, void **result) {
740  void *ctx;
741  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
742  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
743  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
744  if (!res) {
745    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
746    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
747  }
748  return res;
749}
750INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp, char *buf, SIZE_T buflen,
751            void **result) {
752  void *ctx;
753  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
754  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
755  if (!res) {
756    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
757    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
758  }
759  return res;
760}
761#define INIT_GETPWNAM_R_AND_FRIENDS      \
762  COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
763  COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
764  COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
765  COMMON_INTERCEPT_FUNCTION(getgrgid_r);
766#else
767#define INIT_GETPWNAM_R_AND_FRIENDS
768#endif
769
770#if SANITIZER_INTERCEPT_CLOCK_GETTIME
771INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
772  void *ctx;
773  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
774  int res = REAL(clock_getres)(clk_id, tp);
775  if (!res && tp) {
776    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
777  }
778  return res;
779}
780INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
781  void *ctx;
782  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
783  int res = REAL(clock_gettime)(clk_id, tp);
784  if (!res) {
785    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
786  }
787  return res;
788}
789INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
790  void *ctx;
791  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
792  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
793  return REAL(clock_settime)(clk_id, tp);
794}
795#define INIT_CLOCK_GETTIME                  \
796  COMMON_INTERCEPT_FUNCTION(clock_getres);  \
797  COMMON_INTERCEPT_FUNCTION(clock_gettime); \
798  COMMON_INTERCEPT_FUNCTION(clock_settime);
799#else
800#define INIT_CLOCK_GETTIME
801#endif
802
803#if SANITIZER_INTERCEPT_GETITIMER
804INTERCEPTOR(int, getitimer, int which, void *curr_value) {
805  void *ctx;
806  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
807  int res = REAL(getitimer)(which, curr_value);
808  if (!res && curr_value) {
809    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
810  }
811  return res;
812}
813INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
814  void *ctx;
815  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
816  if (new_value)
817    COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
818  int res = REAL(setitimer)(which, new_value, old_value);
819  if (!res && old_value) {
820    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
821  }
822  return res;
823}
824#define INIT_GETITIMER                  \
825  COMMON_INTERCEPT_FUNCTION(getitimer); \
826  COMMON_INTERCEPT_FUNCTION(setitimer);
827#else
828#define INIT_GETITIMER
829#endif
830
831#if SANITIZER_INTERCEPT_GLOB
832static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
833  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
834  // +1 for NULL pointer at the end.
835  if (pglob->gl_pathv)
836    COMMON_INTERCEPTOR_WRITE_RANGE(
837        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
838  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
839    char *p = pglob->gl_pathv[i];
840    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
841  }
842}
843
844static THREADLOCAL __sanitizer_glob_t *pglob_copy;
845static THREADLOCAL void *glob_ctx;
846
847static void wrapped_gl_closedir(void *dir) {
848  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
849  pglob_copy->gl_closedir(dir);
850}
851
852static void *wrapped_gl_readdir(void *dir) {
853  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
854  return pglob_copy->gl_readdir(dir);
855}
856
857static void *wrapped_gl_opendir(const char *s) {
858  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
859  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
860  return pglob_copy->gl_opendir(s);
861}
862
863static int wrapped_gl_lstat(const char *s, void *st) {
864  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
865  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
866  return pglob_copy->gl_lstat(s, st);
867}
868
869static int wrapped_gl_stat(const char *s, void *st) {
870  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
871  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
872  return pglob_copy->gl_stat(s, st);
873}
874
875INTERCEPTOR(int, glob, const char *pattern, int flags,
876            int (*errfunc)(const char *epath, int eerrno),
877            __sanitizer_glob_t *pglob) {
878  void *ctx;
879  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
880  __sanitizer_glob_t glob_copy = {
881      0,                  0,                   0,
882      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
883      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
884  if (flags & glob_altdirfunc) {
885    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
886    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
887    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
888    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
889    Swap(pglob->gl_stat, glob_copy.gl_stat);
890    pglob_copy = &glob_copy;
891    glob_ctx = ctx;
892  }
893  int res = REAL(glob)(pattern, flags, errfunc, pglob);
894  if (flags & glob_altdirfunc) {
895    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
896    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
897    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
898    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
899    Swap(pglob->gl_stat, glob_copy.gl_stat);
900  }
901  pglob_copy = 0;
902  glob_ctx = 0;
903  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
904  return res;
905}
906
907INTERCEPTOR(int, glob64, const char *pattern, int flags,
908            int (*errfunc)(const char *epath, int eerrno),
909            __sanitizer_glob_t *pglob) {
910  void *ctx;
911  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
912  __sanitizer_glob_t glob_copy = {
913      0,                  0,                   0,
914      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
915      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
916  if (flags & glob_altdirfunc) {
917    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
918    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
919    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
920    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
921    Swap(pglob->gl_stat, glob_copy.gl_stat);
922    pglob_copy = &glob_copy;
923    glob_ctx = ctx;
924  }
925  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
926  if (flags & glob_altdirfunc) {
927    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
928    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
929    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
930    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
931    Swap(pglob->gl_stat, glob_copy.gl_stat);
932  }
933  pglob_copy = 0;
934  glob_ctx = 0;
935  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
936  return res;
937}
938#define INIT_GLOB                  \
939  COMMON_INTERCEPT_FUNCTION(glob); \
940  COMMON_INTERCEPT_FUNCTION(glob64);
941#else  // SANITIZER_INTERCEPT_GLOB
942#define INIT_GLOB
943#endif  // SANITIZER_INTERCEPT_GLOB
944
945#if SANITIZER_INTERCEPT_WAIT
946// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
947// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
948// details.
949INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
950  void *ctx;
951  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
952  int res = REAL(wait)(status);
953  if (res != -1 && status)
954    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
955  return res;
956}
957INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
958                        int options) {
959  void *ctx;
960  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
961  int res = REAL(waitid)(idtype, id, infop, options);
962  if (res != -1 && infop)
963    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
964  return res;
965}
966INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
967  void *ctx;
968  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
969  int res = REAL(waitpid)(pid, status, options);
970  if (res != -1 && status)
971    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
972  return res;
973}
974INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
975  void *ctx;
976  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
977  int res = REAL(wait3)(status, options, rusage);
978  if (res != -1) {
979    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
980    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
981  }
982  return res;
983}
984INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
985  void *ctx;
986  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
987  int res = REAL(wait4)(pid, status, options, rusage);
988  if (res != -1) {
989    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
990    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
991  }
992  return res;
993}
994#define INIT_WAIT                     \
995  COMMON_INTERCEPT_FUNCTION(wait);    \
996  COMMON_INTERCEPT_FUNCTION(waitid);  \
997  COMMON_INTERCEPT_FUNCTION(waitpid); \
998  COMMON_INTERCEPT_FUNCTION(wait3);   \
999  COMMON_INTERCEPT_FUNCTION(wait4);
1000#else
1001#define INIT_WAIT
1002#endif
1003
1004#if SANITIZER_INTERCEPT_INET
1005INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
1006  void *ctx;
1007  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
1008  uptr sz = __sanitizer_in_addr_sz(af);
1009  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
1010  // FIXME: figure out read size based on the address family.
1011  char *res = REAL(inet_ntop)(af, src, dst, size);
1012  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1013  return res;
1014}
1015INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
1016  void *ctx;
1017  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
1018  // FIXME: figure out read size based on the address family.
1019  int res = REAL(inet_pton)(af, src, dst);
1020  if (res == 1) {
1021    uptr sz = __sanitizer_in_addr_sz(af);
1022    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
1023  }
1024  return res;
1025}
1026#define INIT_INET                       \
1027  COMMON_INTERCEPT_FUNCTION(inet_ntop); \
1028  COMMON_INTERCEPT_FUNCTION(inet_pton);
1029#else
1030#define INIT_INET
1031#endif
1032
1033#if SANITIZER_INTERCEPT_INET
1034INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
1035  void *ctx;
1036  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
1037  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
1038  int res = REAL(inet_aton)(cp, dst);
1039  if (res != 0) {
1040    uptr sz = __sanitizer_in_addr_sz(af_inet);
1041    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
1042  }
1043  return res;
1044}
1045#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
1046#else
1047#define INIT_INET_ATON
1048#endif
1049
1050#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
1051INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
1052  void *ctx;
1053  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
1054  int res = REAL(pthread_getschedparam)(thread, policy, param);
1055  if (res == 0) {
1056    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
1057    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
1058  }
1059  return res;
1060}
1061#define INIT_PTHREAD_GETSCHEDPARAM \
1062  COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
1063#else
1064#define INIT_PTHREAD_GETSCHEDPARAM
1065#endif
1066
1067#if SANITIZER_INTERCEPT_GETADDRINFO
1068INTERCEPTOR(int, getaddrinfo, char *node, char *service,
1069            struct __sanitizer_addrinfo *hints,
1070            struct __sanitizer_addrinfo **out) {
1071  void *ctx;
1072  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
1073  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
1074  if (service)
1075    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
1076  if (hints)
1077    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
1078  int res = REAL(getaddrinfo)(node, service, hints, out);
1079  if (res == 0 && out) {
1080    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
1081    struct __sanitizer_addrinfo *p = *out;
1082    while (p) {
1083      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
1084      if (p->ai_addr)
1085        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
1086      if (p->ai_canonname)
1087        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
1088                                       REAL(strlen)(p->ai_canonname) + 1);
1089      p = p->ai_next;
1090    }
1091  }
1092  return res;
1093}
1094#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
1095#else
1096#define INIT_GETADDRINFO
1097#endif
1098
1099#if SANITIZER_INTERCEPT_GETNAMEINFO
1100INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
1101            unsigned hostlen, char *serv, unsigned servlen, int flags) {
1102  void *ctx;
1103  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
1104                           serv, servlen, flags);
1105  // FIXME: consider adding READ_RANGE(sockaddr, salen)
1106  // There is padding in in_addr that may make this too noisy
1107  int res =
1108      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
1109  if (res == 0) {
1110    if (host && hostlen)
1111      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
1112    if (serv && servlen)
1113      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
1114  }
1115  return res;
1116}
1117#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
1118#else
1119#define INIT_GETNAMEINFO
1120#endif
1121
1122#if SANITIZER_INTERCEPT_GETSOCKNAME
1123INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
1124  void *ctx;
1125  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
1126  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1127  int addrlen_in = *addrlen;
1128  int res = REAL(getsockname)(sock_fd, addr, addrlen);
1129  if (res == 0) {
1130    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
1131  }
1132  return res;
1133}
1134#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
1135#else
1136#define INIT_GETSOCKNAME
1137#endif
1138
1139#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1140static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
1141  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
1142  if (h->h_name)
1143    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
1144  char **p = h->h_aliases;
1145  while (*p) {
1146    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1147    ++p;
1148  }
1149  COMMON_INTERCEPTOR_WRITE_RANGE(
1150      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
1151  p = h->h_addr_list;
1152  while (*p) {
1153    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
1154    ++p;
1155  }
1156  COMMON_INTERCEPTOR_WRITE_RANGE(
1157      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
1158}
1159#endif
1160
1161#if SANITIZER_INTERCEPT_GETHOSTBYNAME
1162INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
1163  void *ctx;
1164  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
1165  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
1166  if (res) write_hostent(ctx, res);
1167  return res;
1168}
1169
1170INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
1171            int type) {
1172  void *ctx;
1173  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
1174  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1175  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
1176  if (res) write_hostent(ctx, res);
1177  return res;
1178}
1179
1180INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
1181  void *ctx;
1182  COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
1183  struct __sanitizer_hostent *res = REAL(gethostent)(fake);
1184  if (res) write_hostent(ctx, res);
1185  return res;
1186}
1187
1188INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
1189  void *ctx;
1190  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
1191  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
1192  if (res) write_hostent(ctx, res);
1193  return res;
1194}
1195#define INIT_GETHOSTBYNAME                  \
1196  COMMON_INTERCEPT_FUNCTION(gethostent);    \
1197  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
1198  COMMON_INTERCEPT_FUNCTION(gethostbyname); \
1199  COMMON_INTERCEPT_FUNCTION(gethostbyname2);
1200#else
1201#define INIT_GETHOSTBYNAME
1202#endif
1203
1204#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1205INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
1206            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
1207  void *ctx;
1208  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
1209                           h_errnop);
1210  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
1211  if (res == 0) {
1212    if (result) {
1213      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1214      if (*result) write_hostent(ctx, *result);
1215    }
1216    if (h_errnop)
1217      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1218  }
1219  return res;
1220}
1221
1222INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
1223            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1224            __sanitizer_hostent **result, int *h_errnop) {
1225  void *ctx;
1226  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
1227                           buflen, result, h_errnop);
1228  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1229  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
1230                                  h_errnop);
1231  if (res == 0) {
1232    if (result) {
1233      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1234      if (*result) write_hostent(ctx, *result);
1235    }
1236    if (h_errnop)
1237      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1238  }
1239  return res;
1240}
1241
1242INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
1243            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
1244            int *h_errnop) {
1245  void *ctx;
1246  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
1247                           h_errnop);
1248  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
1249  if (res == 0) {
1250    if (result) {
1251      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1252      if (*result) write_hostent(ctx, *result);
1253    }
1254    if (h_errnop)
1255      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1256  }
1257  return res;
1258}
1259
1260INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
1261            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1262            __sanitizer_hostent **result, int *h_errnop) {
1263  void *ctx;
1264  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
1265                           result, h_errnop);
1266  int res =
1267      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
1268  if (res == 0) {
1269    if (result) {
1270      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1271      if (*result) write_hostent(ctx, *result);
1272    }
1273    if (h_errnop)
1274      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1275  }
1276  return res;
1277}
1278#define INIT_GETHOSTBYNAME_R                  \
1279  COMMON_INTERCEPT_FUNCTION(gethostent_r);    \
1280  COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r); \
1281  COMMON_INTERCEPT_FUNCTION(gethostbyname_r); \
1282  COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
1283#else
1284#define INIT_GETHOSTBYNAME_R
1285#endif
1286
1287#if SANITIZER_INTERCEPT_GETSOCKOPT
1288INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
1289            int *optlen) {
1290  void *ctx;
1291  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
1292                           optlen);
1293  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
1294  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
1295  if (res == 0)
1296    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
1297  return res;
1298}
1299#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
1300#else
1301#define INIT_GETSOCKOPT
1302#endif
1303
1304#if SANITIZER_INTERCEPT_ACCEPT
1305INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
1306  void *ctx;
1307  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
1308  unsigned addrlen0;
1309  if (addrlen) {
1310    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1311    addrlen0 = *addrlen;
1312  }
1313  int fd2 = REAL(accept)(fd, addr, addrlen);
1314  if (fd2 >= 0) {
1315    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1316    if (addr && addrlen)
1317      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1318  }
1319  return fd2;
1320}
1321#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
1322#else
1323#define INIT_ACCEPT
1324#endif
1325
1326#if SANITIZER_INTERCEPT_ACCEPT4
1327INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
1328  void *ctx;
1329  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
1330  unsigned addrlen0;
1331  if (addrlen) {
1332    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1333    addrlen0 = *addrlen;
1334  }
1335  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1336  if (fd2 >= 0) {
1337    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1338    if (addr && addrlen)
1339      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1340  }
1341  return fd2;
1342}
1343#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
1344#else
1345#define INIT_ACCEPT4
1346#endif
1347
1348#if SANITIZER_INTERCEPT_MODF
1349INTERCEPTOR(double, modf, double x, double *iptr) {
1350  void *ctx;
1351  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
1352  double res = REAL(modf)(x, iptr);
1353  if (iptr) {
1354    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1355  }
1356  return res;
1357}
1358INTERCEPTOR(float, modff, float x, float *iptr) {
1359  void *ctx;
1360  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
1361  float res = REAL(modff)(x, iptr);
1362  if (iptr) {
1363    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1364  }
1365  return res;
1366}
1367INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
1368  void *ctx;
1369  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
1370  long double res = REAL(modfl)(x, iptr);
1371  if (iptr) {
1372    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1373  }
1374  return res;
1375}
1376#define INIT_MODF                   \
1377  COMMON_INTERCEPT_FUNCTION(modf);  \
1378  COMMON_INTERCEPT_FUNCTION(modff); \
1379  COMMON_INTERCEPT_FUNCTION(modfl);
1380#else
1381#define INIT_MODF
1382#endif
1383
1384#if SANITIZER_INTERCEPT_RECVMSG
1385static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
1386                         SSIZE_T maxlen) {
1387  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
1388  if (msg->msg_name && msg->msg_namelen)
1389    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
1390  if (msg->msg_iov && msg->msg_iovlen)
1391    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
1392                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
1393  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
1394  if (msg->msg_control && msg->msg_controllen)
1395    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
1396}
1397
1398INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
1399            int flags) {
1400  void *ctx;
1401  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
1402  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
1403  if (res >= 0) {
1404    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1405    if (msg) write_msghdr(ctx, msg, res);
1406  }
1407  return res;
1408}
1409#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
1410#else
1411#define INIT_RECVMSG
1412#endif
1413
1414#if SANITIZER_INTERCEPT_GETPEERNAME
1415INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
1416  void *ctx;
1417  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
1418  unsigned addr_sz;
1419  if (addrlen) addr_sz = *addrlen;
1420  int res = REAL(getpeername)(sockfd, addr, addrlen);
1421  if (!res && addr && addrlen)
1422    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
1423  return res;
1424}
1425#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
1426#else
1427#define INIT_GETPEERNAME
1428#endif
1429
1430#if SANITIZER_INTERCEPT_SYSINFO
1431INTERCEPTOR(int, sysinfo, void *info) {
1432  void *ctx;
1433  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
1434  int res = REAL(sysinfo)(info);
1435  if (!res && info)
1436    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
1437  return res;
1438}
1439#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
1440#else
1441#define INIT_SYSINFO
1442#endif
1443
1444#if SANITIZER_INTERCEPT_READDIR
1445INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
1446  void *ctx;
1447  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
1448  __sanitizer_dirent *res = REAL(readdir)(dirp);
1449  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1450  return res;
1451}
1452
1453INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
1454            __sanitizer_dirent **result) {
1455  void *ctx;
1456  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
1457  int res = REAL(readdir_r)(dirp, entry, result);
1458  if (!res) {
1459    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1460    if (*result)
1461      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1462  }
1463  return res;
1464}
1465
1466#define INIT_READDIR                  \
1467  COMMON_INTERCEPT_FUNCTION(readdir); \
1468  COMMON_INTERCEPT_FUNCTION(readdir_r);
1469#else
1470#define INIT_READDIR
1471#endif
1472
1473#if SANITIZER_INTERCEPT_READDIR64
1474INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
1475  void *ctx;
1476  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
1477  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
1478  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1479  return res;
1480}
1481
1482INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
1483            __sanitizer_dirent64 **result) {
1484  void *ctx;
1485  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
1486  int res = REAL(readdir64_r)(dirp, entry, result);
1487  if (!res) {
1488    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1489    if (*result)
1490      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1491  }
1492  return res;
1493}
1494#define INIT_READDIR64                  \
1495  COMMON_INTERCEPT_FUNCTION(readdir64); \
1496  COMMON_INTERCEPT_FUNCTION(readdir64_r);
1497#else
1498#define INIT_READDIR64
1499#endif
1500
1501#if SANITIZER_INTERCEPT_PTRACE
1502INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
1503  void *ctx;
1504  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
1505
1506  if (data) {
1507    if (request == ptrace_setregs)
1508      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
1509    else if (request == ptrace_setfpregs)
1510      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1511    else if (request == ptrace_setfpxregs)
1512      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1513    else if (request == ptrace_setsiginfo)
1514      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
1515    else if (request == ptrace_setregset) {
1516      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1517      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
1518    }
1519  }
1520
1521  uptr res = REAL(ptrace)(request, pid, addr, data);
1522
1523  if (!res && data) {
1524    // Note that PEEK* requests assing different meaning to the return value.
1525    // This function does not handle them (nor does it need to).
1526    if (request == ptrace_getregs)
1527      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
1528    else if (request == ptrace_getfpregs)
1529      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1530    else if (request == ptrace_getfpxregs)
1531      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1532    else if (request == ptrace_getsiginfo)
1533      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
1534    else if (request == ptrace_getregset) {
1535      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1536      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
1537    }
1538  }
1539  return res;
1540}
1541
1542#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
1543#else
1544#define INIT_PTRACE
1545#endif
1546
1547#if SANITIZER_INTERCEPT_SETLOCALE
1548INTERCEPTOR(char *, setlocale, int category, char *locale) {
1549  void *ctx;
1550  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
1551  if (locale)
1552    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
1553  char *res = REAL(setlocale)(category, locale);
1554  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1555  return res;
1556}
1557
1558#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
1559#else
1560#define INIT_SETLOCALE
1561#endif
1562
1563#if SANITIZER_INTERCEPT_GETCWD
1564INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
1565  void *ctx;
1566  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
1567  char *res = REAL(getcwd)(buf, size);
1568  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1569  return res;
1570}
1571#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
1572#else
1573#define INIT_GETCWD
1574#endif
1575
1576#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
1577INTERCEPTOR(char *, get_current_dir_name, int fake) {
1578  void *ctx;
1579  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
1580  char *res = REAL(get_current_dir_name)(fake);
1581  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1582  return res;
1583}
1584
1585#define INIT_GET_CURRENT_DIR_NAME \
1586  COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
1587#else
1588#define INIT_GET_CURRENT_DIR_NAME
1589#endif
1590
1591#if SANITIZER_INTERCEPT_STRTOIMAX
1592INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
1593  void *ctx;
1594  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
1595  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
1596  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1597  return res;
1598}
1599
1600INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
1601  void *ctx;
1602  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
1603  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
1604  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1605  return res;
1606}
1607
1608#define INIT_STRTOIMAX                  \
1609  COMMON_INTERCEPT_FUNCTION(strtoimax); \
1610  COMMON_INTERCEPT_FUNCTION(strtoumax);
1611#else
1612#define INIT_STRTOIMAX
1613#endif
1614
1615#if SANITIZER_INTERCEPT_MBSTOWCS
1616INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
1617  void *ctx;
1618  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
1619  SIZE_T res = REAL(mbstowcs)(dest, src, len);
1620  if (res != (SIZE_T) - 1 && dest) {
1621    SIZE_T write_cnt = res + (res < len);
1622    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1623  }
1624  return res;
1625}
1626
1627INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
1628            void *ps) {
1629  void *ctx;
1630  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
1631  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1632  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1633  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
1634  if (res != (SIZE_T)(-1) && dest && src) {
1635    // This function, and several others, may or may not write the terminating
1636    // \0 character. They write it iff they clear *src.
1637    SIZE_T write_cnt = res + !*src;
1638    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1639  }
1640  return res;
1641}
1642
1643#define INIT_MBSTOWCS                  \
1644  COMMON_INTERCEPT_FUNCTION(mbstowcs); \
1645  COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
1646#else
1647#define INIT_MBSTOWCS
1648#endif
1649
1650#if SANITIZER_INTERCEPT_MBSNRTOWCS
1651INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
1652            SIZE_T len, void *ps) {
1653  void *ctx;
1654  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
1655  if (src) {
1656    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1657    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1658  }
1659  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1660  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
1661  if (res != (SIZE_T)(-1) && dest && src) {
1662    SIZE_T write_cnt = res + !*src;
1663    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1664  }
1665  return res;
1666}
1667
1668#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
1669#else
1670#define INIT_MBSNRTOWCS
1671#endif
1672
1673#if SANITIZER_INTERCEPT_WCSTOMBS
1674INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
1675  void *ctx;
1676  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
1677  SIZE_T res = REAL(wcstombs)(dest, src, len);
1678  if (res != (SIZE_T) - 1 && dest) {
1679    SIZE_T write_cnt = res + (res < len);
1680    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1681  }
1682  return res;
1683}
1684
1685INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
1686            void *ps) {
1687  void *ctx;
1688  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
1689  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1690  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1691  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
1692  if (res != (SIZE_T) - 1 && dest && src) {
1693    SIZE_T write_cnt = res + !*src;
1694    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1695  }
1696  return res;
1697}
1698
1699#define INIT_WCSTOMBS                  \
1700  COMMON_INTERCEPT_FUNCTION(wcstombs); \
1701  COMMON_INTERCEPT_FUNCTION(wcsrtombs);
1702#else
1703#define INIT_WCSTOMBS
1704#endif
1705
1706#if SANITIZER_INTERCEPT_WCSNRTOMBS
1707INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
1708            SIZE_T len, void *ps) {
1709  void *ctx;
1710  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
1711  if (src) {
1712    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1713    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1714  }
1715  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1716  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
1717  if (res != (SIZE_T) - 1 && dest && src) {
1718    SIZE_T write_cnt = res + !*src;
1719    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1720  }
1721  return res;
1722}
1723
1724#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
1725#else
1726#define INIT_WCSNRTOMBS
1727#endif
1728
1729#if SANITIZER_INTERCEPT_TCGETATTR
1730INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
1731  void *ctx;
1732  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
1733  int res = REAL(tcgetattr)(fd, termios_p);
1734  if (!res && termios_p)
1735    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
1736  return res;
1737}
1738
1739#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
1740#else
1741#define INIT_TCGETATTR
1742#endif
1743
1744#if SANITIZER_INTERCEPT_REALPATH
1745INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
1746  void *ctx;
1747  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
1748  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1749
1750  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
1751  // version of a versioned symbol. For realpath(), this gives us something
1752  // (called __old_realpath) that does not handle NULL in the second argument.
1753  // Handle it as part of the interceptor.
1754  char *allocated_path = 0;
1755  if (!resolved_path)
1756    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
1757
1758  char *res = REAL(realpath)(path, resolved_path);
1759  if (allocated_path && !res) WRAP(free)(allocated_path);
1760  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1761  return res;
1762}
1763#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
1764#else
1765#define INIT_REALPATH
1766#endif
1767
1768#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
1769INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
1770  void *ctx;
1771  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
1772  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1773  char *res = REAL(canonicalize_file_name)(path);
1774  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1775  return res;
1776}
1777#define INIT_CANONICALIZE_FILE_NAME \
1778  COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
1779#else
1780#define INIT_CANONICALIZE_FILE_NAME
1781#endif
1782
1783#if SANITIZER_INTERCEPT_CONFSTR
1784INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
1785  void *ctx;
1786  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
1787  SIZE_T res = REAL(confstr)(name, buf, len);
1788  if (buf && res)
1789    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
1790  return res;
1791}
1792#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
1793#else
1794#define INIT_CONFSTR
1795#endif
1796
1797#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
1798INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
1799  void *ctx;
1800  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
1801  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
1802  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
1803  return res;
1804}
1805#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
1806#else
1807#define INIT_SCHED_GETAFFINITY
1808#endif
1809
1810#if SANITIZER_INTERCEPT_STRERROR
1811INTERCEPTOR(char *, strerror, int errnum) {
1812  void *ctx;
1813  COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
1814  char *res = REAL(strerror)(errnum);
1815  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1816  return res;
1817}
1818#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
1819#else
1820#define INIT_STRERROR
1821#endif
1822
1823#if SANITIZER_INTERCEPT_STRERROR_R
1824INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
1825  void *ctx;
1826  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
1827  char *res = REAL(strerror_r)(errnum, buf, buflen);
1828  // There are 2 versions of strerror_r:
1829  //  * POSIX version returns 0 on success, negative error code on failure,
1830  //    writes message to buf.
1831  //  * GNU version returns message pointer, which points to either buf or some
1832  //    static storage.
1833  SIZE_T posix_res = (SIZE_T)res;
1834  if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
1835    // POSIX version. Spec is not clear on whether buf is NULL-terminated.
1836    // At least on OSX, buf contents are valid even when the call fails.
1837    SIZE_T sz = internal_strnlen(buf, buflen);
1838    if (sz < buflen) ++sz;
1839    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
1840  } else {
1841    // GNU version.
1842    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1843  }
1844  return res;
1845}
1846#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
1847#else
1848#define INIT_STRERROR_R
1849#endif
1850
1851#if SANITIZER_INTERCEPT_SCANDIR
1852typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
1853typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
1854                                const struct __sanitizer_dirent **);
1855
1856static THREADLOCAL void *scandir_ctx;
1857static THREADLOCAL scandir_filter_f scandir_filter;
1858static THREADLOCAL scandir_compar_f scandir_compar;
1859
1860static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
1861  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 1);
1862  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, dir, dir->d_reclen);
1863  return scandir_filter(dir);
1864}
1865
1866static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
1867                                  const struct __sanitizer_dirent **b) {
1868  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 2);
1869  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, a, sizeof(*a));
1870  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *a, (*a)->d_reclen);
1871  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, b, sizeof(*b));
1872  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *b, (*b)->d_reclen);
1873  return scandir_compar(a, b);
1874}
1875
1876INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
1877            scandir_filter_f filter, scandir_compar_f compar) {
1878  void *ctx;
1879  COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
1880  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
1881  CHECK_EQ(0, scandir_ctx);
1882  scandir_ctx = ctx;
1883  scandir_filter = filter;
1884  scandir_compar = compar;
1885  int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : 0,
1886                          compar ? wrapped_scandir_compar : 0);
1887  scandir_ctx = 0;
1888  scandir_filter = 0;
1889  scandir_compar = 0;
1890  if (namelist && res > 0) {
1891    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
1892    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
1893    for (int i = 0; i < res; ++i)
1894      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
1895                                     (*namelist)[i]->d_reclen);
1896  }
1897  return res;
1898}
1899#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
1900#else
1901#define INIT_SCANDIR
1902#endif
1903
1904#if SANITIZER_INTERCEPT_SCANDIR64
1905typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
1906typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
1907                                  const struct __sanitizer_dirent64 **);
1908
1909static THREADLOCAL void *scandir64_ctx;
1910static THREADLOCAL scandir64_filter_f scandir64_filter;
1911static THREADLOCAL scandir64_compar_f scandir64_compar;
1912
1913static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
1914  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 1);
1915  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, dir, dir->d_reclen);
1916  return scandir64_filter(dir);
1917}
1918
1919static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
1920                                    const struct __sanitizer_dirent64 **b) {
1921  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 2);
1922  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, a, sizeof(*a));
1923  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *a, (*a)->d_reclen);
1924  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, b, sizeof(*b));
1925  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *b, (*b)->d_reclen);
1926  return scandir64_compar(a, b);
1927}
1928
1929INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
1930            scandir64_filter_f filter, scandir64_compar_f compar) {
1931  void *ctx;
1932  COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
1933  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
1934  CHECK_EQ(0, scandir64_ctx);
1935  scandir64_ctx = ctx;
1936  scandir64_filter = filter;
1937  scandir64_compar = compar;
1938  int res =
1939      REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : 0,
1940                      compar ? wrapped_scandir64_compar : 0);
1941  scandir64_ctx = 0;
1942  scandir64_filter = 0;
1943  scandir64_compar = 0;
1944  if (namelist && res > 0) {
1945    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
1946    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
1947    for (int i = 0; i < res; ++i)
1948      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
1949                                     (*namelist)[i]->d_reclen);
1950  }
1951  return res;
1952}
1953#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
1954#else
1955#define INIT_SCANDIR64
1956#endif
1957
1958#if SANITIZER_INTERCEPT_GETGROUPS
1959INTERCEPTOR(int, getgroups, int size, u32 *lst) {
1960  void *ctx;
1961  COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
1962  int res = REAL(getgroups)(size, lst);
1963  if (res && lst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
1964  return res;
1965}
1966#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
1967#else
1968#define INIT_GETGROUPS
1969#endif
1970
1971#if SANITIZER_INTERCEPT_POLL
1972static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
1973                        __sanitizer_nfds_t nfds) {
1974  for (unsigned i = 0; i < nfds; ++i) {
1975    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
1976    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
1977  }
1978}
1979
1980static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
1981                         __sanitizer_nfds_t nfds) {
1982  for (unsigned i = 0; i < nfds; ++i)
1983    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
1984                                   sizeof(fds[i].revents));
1985}
1986
1987INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
1988            int timeout) {
1989  void *ctx;
1990  COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
1991  if (fds && nfds) read_pollfd(ctx, fds, nfds);
1992  int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
1993  if (fds && nfds) write_pollfd(ctx, fds, nfds);
1994  return res;
1995}
1996#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
1997#else
1998#define INIT_POLL
1999#endif
2000
2001#if SANITIZER_INTERCEPT_PPOLL
2002INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
2003            void *timeout_ts, __sanitizer_sigset_t *sigmask) {
2004  void *ctx;
2005  COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
2006  if (fds && nfds) read_pollfd(ctx, fds, nfds);
2007  if (timeout_ts)
2008    COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
2009  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
2010  int res =
2011      COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
2012  if (fds && nfds) write_pollfd(ctx, fds, nfds);
2013  return res;
2014}
2015#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
2016#else
2017#define INIT_PPOLL
2018#endif
2019
2020#if SANITIZER_INTERCEPT_WORDEXP
2021INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
2022  void *ctx;
2023  COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
2024  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
2025  int res = REAL(wordexp)(s, p, flags);
2026  if (!res && p) {
2027    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
2028    if (p->we_wordc)
2029      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
2030                                     sizeof(*p->we_wordv) * p->we_wordc);
2031    for (uptr i = 0; i < p->we_wordc; ++i) {
2032      char *w = p->we_wordv[i];
2033      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
2034    }
2035  }
2036  return res;
2037}
2038#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
2039#else
2040#define INIT_WORDEXP
2041#endif
2042
2043#if SANITIZER_INTERCEPT_SIGWAIT
2044INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
2045  void *ctx;
2046  COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
2047  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2048  int res = REAL(sigwait)(set, sig);
2049  if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
2050  return res;
2051}
2052#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
2053#else
2054#define INIT_SIGWAIT
2055#endif
2056
2057#if SANITIZER_INTERCEPT_SIGWAITINFO
2058INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
2059  void *ctx;
2060  COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
2061  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2062  int res = REAL(sigwaitinfo)(set, info);
2063  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
2064  return res;
2065}
2066#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
2067#else
2068#define INIT_SIGWAITINFO
2069#endif
2070
2071#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
2072INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
2073            void *timeout) {
2074  void *ctx;
2075  COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
2076  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
2077  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2078  int res = REAL(sigtimedwait)(set, info, timeout);
2079  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
2080  return res;
2081}
2082#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
2083#else
2084#define INIT_SIGTIMEDWAIT
2085#endif
2086
2087#if SANITIZER_INTERCEPT_SIGSETOPS
2088INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
2089  void *ctx;
2090  COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
2091  int res = REAL(sigemptyset)(set);
2092  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
2093  return res;
2094}
2095
2096INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
2097  void *ctx;
2098  COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
2099  int res = REAL(sigfillset)(set);
2100  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
2101  return res;
2102}
2103#define INIT_SIGSETOPS                    \
2104  COMMON_INTERCEPT_FUNCTION(sigemptyset); \
2105  COMMON_INTERCEPT_FUNCTION(sigfillset);
2106#else
2107#define INIT_SIGSETOPS
2108#endif
2109
2110#if SANITIZER_INTERCEPT_SIGPENDING
2111INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
2112  void *ctx;
2113  COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
2114  int res = REAL(sigpending)(set);
2115  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
2116  return res;
2117}
2118#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
2119#else
2120#define INIT_SIGPENDING
2121#endif
2122
2123#if SANITIZER_INTERCEPT_SIGPROCMASK
2124INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
2125            __sanitizer_sigset_t *oldset) {
2126  void *ctx;
2127  COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
2128  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2129  int res = REAL(sigprocmask)(how, set, oldset);
2130  if (!res && oldset)
2131    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
2132  return res;
2133}
2134#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
2135#else
2136#define INIT_SIGPROCMASK
2137#endif
2138
2139#if SANITIZER_INTERCEPT_BACKTRACE
2140INTERCEPTOR(int, backtrace, void **buffer, int size) {
2141  void *ctx;
2142  COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
2143  int res = REAL(backtrace)(buffer, size);
2144  if (res && buffer)
2145    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
2146  return res;
2147}
2148
2149INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
2150  void *ctx;
2151  COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
2152  if (buffer && size)
2153    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
2154  char **res = REAL(backtrace_symbols)(buffer, size);
2155  if (res && size) {
2156    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
2157    for (int i = 0; i < size; ++i)
2158      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
2159  }
2160  return res;
2161}
2162#define INIT_BACKTRACE                  \
2163  COMMON_INTERCEPT_FUNCTION(backtrace); \
2164  COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
2165#else
2166#define INIT_BACKTRACE
2167#endif
2168
2169#if SANITIZER_INTERCEPT__EXIT
2170INTERCEPTOR(void, _exit, int status) {
2171  void *ctx;
2172  COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
2173  int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
2174  if (status == 0) status = status1;
2175  REAL(_exit)(status);
2176}
2177#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
2178#else
2179#define INIT__EXIT
2180#endif
2181
2182#if SANITIZER_INTERCEPT_PHTREAD_MUTEX
2183INTERCEPTOR(int, pthread_mutex_lock, void *m) {
2184  void *ctx;
2185  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
2186  int res = REAL(pthread_mutex_lock)(m);
2187  if (res == errno_EOWNERDEAD)
2188    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
2189  if (res == 0 || res == errno_EOWNERDEAD)
2190    COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
2191  return res;
2192}
2193
2194INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
2195  void *ctx;
2196  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
2197  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
2198  return REAL(pthread_mutex_unlock)(m);
2199}
2200
2201#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
2202#define INIT_PTHREAD_MUTEX_UNLOCK \
2203  COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
2204#else
2205#define INIT_PTHREAD_MUTEX_LOCK
2206#define INIT_PTHREAD_MUTEX_UNLOCK
2207#endif
2208
2209#if SANITIZER_INTERCEPT_PTHREAD_COND
2210INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
2211  void *ctx;
2212  COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_wait, c, m);
2213  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
2214  COMMON_INTERCEPTOR_READ_RANGE(ctx, c, pthread_cond_t_sz);
2215  int res = REAL(pthread_cond_wait)(c, m);
2216  COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
2217  return res;
2218}
2219
2220INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
2221  void *ctx;
2222  COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_init, c, a);
2223  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, c, pthread_cond_t_sz);
2224  return REAL(pthread_cond_init)(c, a);
2225}
2226
2227INTERCEPTOR(int, pthread_cond_signal, void *c) {
2228  void *ctx;
2229  COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_signal, c);
2230  COMMON_INTERCEPTOR_READ_RANGE(ctx, c, pthread_cond_t_sz);
2231  return REAL(pthread_cond_signal)(c);
2232}
2233
2234INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
2235  void *ctx;
2236  COMMON_INTERCEPTOR_ENTER(ctx, pthread_cond_broadcast, c);
2237  COMMON_INTERCEPTOR_READ_RANGE(ctx, c, pthread_cond_t_sz);
2238  return REAL(pthread_cond_broadcast)(c);
2239}
2240
2241#define INIT_PTHREAD_COND_WAIT \
2242  INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2")
2243#define INIT_PTHREAD_COND_INIT \
2244  INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2")
2245#define INIT_PTHREAD_COND_SIGNAL \
2246  INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2")
2247#define INIT_PTHREAD_COND_BROADCAST \
2248  INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2")
2249#else
2250#define INIT_PTHREAD_COND_WAIT
2251#define INIT_PTHREAD_COND_INIT
2252#define INIT_PTHREAD_COND_SIGNAL
2253#define INIT_PTHREAD_COND_BROADCAST
2254#endif
2255
2256#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
2257static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
2258  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
2259  if (mnt->mnt_fsname)
2260    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
2261                                   REAL(strlen)(mnt->mnt_fsname) + 1);
2262  if (mnt->mnt_dir)
2263    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
2264                                   REAL(strlen)(mnt->mnt_dir) + 1);
2265  if (mnt->mnt_type)
2266    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
2267                                   REAL(strlen)(mnt->mnt_type) + 1);
2268  if (mnt->mnt_opts)
2269    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
2270                                   REAL(strlen)(mnt->mnt_opts) + 1);
2271}
2272#endif
2273
2274#if SANITIZER_INTERCEPT_GETMNTENT
2275INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
2276  void *ctx;
2277  COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
2278  __sanitizer_mntent *res = REAL(getmntent)(fp);
2279  if (res) write_mntent(ctx, res);
2280  return res;
2281}
2282#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
2283#else
2284#define INIT_GETMNTENT
2285#endif
2286
2287#if SANITIZER_INTERCEPT_GETMNTENT_R
2288INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
2289            __sanitizer_mntent *mntbuf, char *buf, int buflen) {
2290  void *ctx;
2291  COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
2292  __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
2293  if (res) write_mntent(ctx, res);
2294  return res;
2295}
2296#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
2297#else
2298#define INIT_GETMNTENT_R
2299#endif
2300
2301#if SANITIZER_INTERCEPT_STATFS
2302INTERCEPTOR(int, statfs, char *path, void *buf) {
2303  void *ctx;
2304  COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
2305  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2306  int res = REAL(statfs)(path, buf);
2307  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
2308  return res;
2309}
2310INTERCEPTOR(int, fstatfs, int fd, void *buf) {
2311  void *ctx;
2312  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
2313  int res = REAL(fstatfs)(fd, buf);
2314  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
2315  return res;
2316}
2317#define INIT_STATFS                  \
2318  COMMON_INTERCEPT_FUNCTION(statfs); \
2319  COMMON_INTERCEPT_FUNCTION(fstatfs);
2320#else
2321#define INIT_STATFS
2322#endif
2323
2324#if SANITIZER_INTERCEPT_STATFS64
2325INTERCEPTOR(int, statfs64, char *path, void *buf) {
2326  void *ctx;
2327  COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
2328  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2329  int res = REAL(statfs64)(path, buf);
2330  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
2331  return res;
2332}
2333INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
2334  void *ctx;
2335  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
2336  int res = REAL(fstatfs64)(fd, buf);
2337  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
2338  return res;
2339}
2340#define INIT_STATFS64                  \
2341  COMMON_INTERCEPT_FUNCTION(statfs64); \
2342  COMMON_INTERCEPT_FUNCTION(fstatfs64);
2343#else
2344#define INIT_STATFS64
2345#endif
2346
2347#if SANITIZER_INTERCEPT_STATVFS
2348INTERCEPTOR(int, statvfs, char *path, void *buf) {
2349  void *ctx;
2350  COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
2351  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2352  int res = REAL(statvfs)(path, buf);
2353  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
2354  return res;
2355}
2356INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
2357  void *ctx;
2358  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
2359  int res = REAL(fstatvfs)(fd, buf);
2360  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
2361  return res;
2362}
2363#define INIT_STATVFS                  \
2364  COMMON_INTERCEPT_FUNCTION(statvfs); \
2365  COMMON_INTERCEPT_FUNCTION(fstatvfs);
2366#else
2367#define INIT_STATVFS
2368#endif
2369
2370#if SANITIZER_INTERCEPT_STATVFS64
2371INTERCEPTOR(int, statvfs64, char *path, void *buf) {
2372  void *ctx;
2373  COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
2374  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
2375  int res = REAL(statvfs64)(path, buf);
2376  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
2377  return res;
2378}
2379INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
2380  void *ctx;
2381  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
2382  int res = REAL(fstatvfs64)(fd, buf);
2383  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
2384  return res;
2385}
2386#define INIT_STATVFS64                  \
2387  COMMON_INTERCEPT_FUNCTION(statvfs64); \
2388  COMMON_INTERCEPT_FUNCTION(fstatvfs64);
2389#else
2390#define INIT_STATVFS64
2391#endif
2392
2393#if SANITIZER_INTERCEPT_INITGROUPS
2394INTERCEPTOR(int, initgroups, char *user, u32 group) {
2395  void *ctx;
2396  COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
2397  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
2398  int res = REAL(initgroups)(user, group);
2399  return res;
2400}
2401#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
2402#else
2403#define INIT_INITGROUPS
2404#endif
2405
2406#if SANITIZER_INTERCEPT_ETHER
2407INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
2408  void *ctx;
2409  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
2410  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
2411  char *res = REAL(ether_ntoa)(addr);
2412  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2413  return res;
2414}
2415INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
2416  void *ctx;
2417  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
2418  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
2419  __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
2420  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, sizeof(*res));
2421  return res;
2422}
2423INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
2424  void *ctx;
2425  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
2426  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
2427  int res = REAL(ether_ntohost)(hostname, addr);
2428  if (!res && hostname)
2429    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
2430  return res;
2431}
2432INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
2433  void *ctx;
2434  COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
2435  if (hostname)
2436    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
2437  int res = REAL(ether_hostton)(hostname, addr);
2438  if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
2439  return res;
2440}
2441INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
2442            char *hostname) {
2443  void *ctx;
2444  COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
2445  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
2446  int res = REAL(ether_line)(line, addr, hostname);
2447  if (!res) {
2448    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
2449    if (hostname)
2450      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
2451  }
2452  return res;
2453}
2454#define INIT_ETHER                          \
2455  COMMON_INTERCEPT_FUNCTION(ether_ntoa);    \
2456  COMMON_INTERCEPT_FUNCTION(ether_aton);    \
2457  COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
2458  COMMON_INTERCEPT_FUNCTION(ether_hostton); \
2459  COMMON_INTERCEPT_FUNCTION(ether_line);
2460#else
2461#define INIT_ETHER
2462#endif
2463
2464#if SANITIZER_INTERCEPT_ETHER_R
2465INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
2466  void *ctx;
2467  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
2468  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
2469  char *res = REAL(ether_ntoa_r)(addr, buf);
2470  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2471  return res;
2472}
2473INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
2474            __sanitizer_ether_addr *addr) {
2475  void *ctx;
2476  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
2477  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
2478  __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
2479  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
2480  return res;
2481}
2482#define INIT_ETHER_R                       \
2483  COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
2484  COMMON_INTERCEPT_FUNCTION(ether_aton_r);
2485#else
2486#define INIT_ETHER_R
2487#endif
2488
2489#if SANITIZER_INTERCEPT_SHMCTL
2490INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
2491  void *ctx;
2492  COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
2493  int res = REAL(shmctl)(shmid, cmd, buf);
2494  if (res >= 0) {
2495    unsigned sz = 0;
2496    if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
2497      sz = sizeof(__sanitizer_shmid_ds);
2498    else if (cmd == shmctl_ipc_info)
2499      sz = struct_shminfo_sz;
2500    else if (cmd == shmctl_shm_info)
2501      sz = struct_shm_info_sz;
2502    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
2503  }
2504  return res;
2505}
2506#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
2507#else
2508#define INIT_SHMCTL
2509#endif
2510
2511#if SANITIZER_INTERCEPT_RANDOM_R
2512INTERCEPTOR(int, random_r, void *buf, u32 *result) {
2513  void *ctx;
2514  COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
2515  int res = REAL(random_r)(buf, result);
2516  if (!res && result)
2517    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2518  return res;
2519}
2520#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
2521#else
2522#define INIT_RANDOM_R
2523#endif
2524
2525#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET || \
2526    SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED
2527#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz)                      \
2528  INTERCEPTOR(int, pthread_attr_get##what, void *attr, void *r) {   \
2529    void *ctx;                                                      \
2530    COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_get##what, attr, r); \
2531    int res = REAL(pthread_attr_get##what)(attr, r);                \
2532    if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz);      \
2533    return res;                                                     \
2534  }
2535#endif
2536
2537#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
2538INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
2539INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
2540INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
2541INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
2542INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
2543INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
2544INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
2545  void *ctx;
2546  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
2547  int res = REAL(pthread_attr_getstack)(attr, addr, size);
2548  if (!res) {
2549    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
2550    if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
2551  }
2552  return res;
2553}
2554
2555#define INIT_PTHREAD_ATTR_GET                             \
2556  COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
2557  COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize);   \
2558  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam);  \
2559  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy); \
2560  COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope);       \
2561  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize);   \
2562  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
2563#else
2564#define INIT_PTHREAD_ATTR_GET
2565#endif
2566
2567#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
2568INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
2569
2570#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
2571  COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
2572#else
2573#define INIT_PTHREAD_ATTR_GETINHERITSCHED
2574#endif
2575
2576#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
2577INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
2578            void *cpuset) {
2579  void *ctx;
2580  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
2581                           cpuset);
2582  int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
2583  if (!res && cpusetsize && cpuset)
2584    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
2585  return res;
2586}
2587
2588#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
2589  COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
2590#else
2591#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
2592#endif
2593
2594#if SANITIZER_INTERCEPT_TMPNAM
2595INTERCEPTOR(char *, tmpnam, char *s) {
2596  void *ctx;
2597  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
2598  char *res = REAL(tmpnam)(s);
2599  if (res) {
2600    if (s)
2601      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
2602    else
2603      COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2604  }
2605  return res;
2606}
2607#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
2608#else
2609#define INIT_TMPNAM
2610#endif
2611
2612#if SANITIZER_INTERCEPT_TMPNAM_R
2613INTERCEPTOR(char *, tmpnam_r, char *s) {
2614  void *ctx;
2615  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
2616  char *res = REAL(tmpnam_r)(s);
2617  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
2618  return res;
2619}
2620#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
2621#else
2622#define INIT_TMPNAM_R
2623#endif
2624
2625#if SANITIZER_INTERCEPT_TEMPNAM
2626INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
2627  void *ctx;
2628  COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
2629  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
2630  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
2631  char *res = REAL(tempnam)(dir, pfx);
2632  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2633  return res;
2634}
2635#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
2636#else
2637#define INIT_TEMPNAM
2638#endif
2639
2640#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP
2641INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
2642  void *ctx;
2643  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
2644  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
2645  return REAL(pthread_setname_np)(thread, name);
2646}
2647#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
2648#else
2649#define INIT_PTHREAD_SETNAME_NP
2650#endif
2651
2652#if SANITIZER_INTERCEPT_SINCOS
2653INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
2654  void *ctx;
2655  COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
2656  REAL(sincos)(x, sin, cos);
2657  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
2658  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
2659}
2660INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
2661  void *ctx;
2662  COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
2663  REAL(sincosf)(x, sin, cos);
2664  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
2665  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
2666}
2667INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
2668  void *ctx;
2669  COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
2670  REAL(sincosl)(x, sin, cos);
2671  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
2672  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
2673}
2674#define INIT_SINCOS                   \
2675  COMMON_INTERCEPT_FUNCTION(sincos);  \
2676  COMMON_INTERCEPT_FUNCTION(sincosf); \
2677  COMMON_INTERCEPT_FUNCTION(sincosl);
2678#else
2679#define INIT_SINCOS
2680#endif
2681
2682#if SANITIZER_INTERCEPT_REMQUO
2683INTERCEPTOR(double, remquo, double x, double y, int *quo) {
2684  void *ctx;
2685  COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
2686  double res = REAL(remquo)(x, y, quo);
2687  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
2688  return res;
2689}
2690INTERCEPTOR(float, remquof, float x, float y, int *quo) {
2691  void *ctx;
2692  COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
2693  float res = REAL(remquof)(x, y, quo);
2694  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
2695  return res;
2696}
2697INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
2698  void *ctx;
2699  COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
2700  long double res = REAL(remquol)(x, y, quo);
2701  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
2702  return res;
2703}
2704#define INIT_REMQUO                   \
2705  COMMON_INTERCEPT_FUNCTION(remquo);  \
2706  COMMON_INTERCEPT_FUNCTION(remquof); \
2707  COMMON_INTERCEPT_FUNCTION(remquol);
2708#else
2709#define INIT_REMQUO
2710#endif
2711
2712#if SANITIZER_INTERCEPT_LGAMMA
2713extern int signgam;
2714INTERCEPTOR(double, lgamma, double x) {
2715  void *ctx;
2716  COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
2717  double res = REAL(lgamma)(x);
2718  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
2719  return res;
2720}
2721INTERCEPTOR(float, lgammaf, float x) {
2722  void *ctx;
2723  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
2724  float res = REAL(lgammaf)(x);
2725  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
2726  return res;
2727}
2728INTERCEPTOR(long double, lgammal, long double x) {
2729  void *ctx;
2730  COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
2731  long double res = REAL(lgammal)(x);
2732  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
2733  return res;
2734}
2735#define INIT_LGAMMA                   \
2736  COMMON_INTERCEPT_FUNCTION(lgamma);  \
2737  COMMON_INTERCEPT_FUNCTION(lgammaf); \
2738  COMMON_INTERCEPT_FUNCTION(lgammal);
2739#else
2740#define INIT_LGAMMA
2741#endif
2742
2743#if SANITIZER_INTERCEPT_LGAMMA_R
2744INTERCEPTOR(double, lgamma_r, double x, int *signp) {
2745  void *ctx;
2746  COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
2747  double res = REAL(lgamma_r)(x, signp);
2748  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
2749  return res;
2750}
2751INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
2752  void *ctx;
2753  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
2754  float res = REAL(lgammaf_r)(x, signp);
2755  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
2756  return res;
2757}
2758INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
2759  void *ctx;
2760  COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
2761  long double res = REAL(lgammal_r)(x, signp);
2762  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
2763  return res;
2764}
2765#define INIT_LGAMMA_R                   \
2766  COMMON_INTERCEPT_FUNCTION(lgamma_r);  \
2767  COMMON_INTERCEPT_FUNCTION(lgammaf_r); \
2768  COMMON_INTERCEPT_FUNCTION(lgammal_r);
2769#else
2770#define INIT_LGAMMA_R
2771#endif
2772
2773#if SANITIZER_INTERCEPT_DRAND48_R
2774INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
2775  void *ctx;
2776  COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
2777  int res = REAL(drand48_r)(buffer, result);
2778  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2779  return res;
2780}
2781INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
2782  void *ctx;
2783  COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
2784  int res = REAL(lrand48_r)(buffer, result);
2785  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2786  return res;
2787}
2788#define INIT_DRAND48_R                  \
2789  COMMON_INTERCEPT_FUNCTION(drand48_r); \
2790  COMMON_INTERCEPT_FUNCTION(lrand48_r);
2791#else
2792#define INIT_DRAND48_R
2793#endif
2794
2795#if SANITIZER_INTERCEPT_GETLINE
2796INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
2797  void *ctx;
2798  COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
2799  SSIZE_T res = REAL(getline)(lineptr, n, stream);
2800  if (res > 0) {
2801    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
2802    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
2803    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
2804  }
2805  return res;
2806}
2807INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
2808            void *stream) {
2809  void *ctx;
2810  COMMON_INTERCEPTOR_ENTER(ctx, getdelim, lineptr, n, delim, stream);
2811  SSIZE_T res = REAL(getdelim)(lineptr, n, delim, stream);
2812  if (res > 0) {
2813    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
2814    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
2815    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
2816  }
2817  return res;
2818}
2819#define INIT_GETLINE                  \
2820  COMMON_INTERCEPT_FUNCTION(getline); \
2821  COMMON_INTERCEPT_FUNCTION(getdelim);
2822#else
2823#define INIT_GETLINE
2824#endif
2825
2826#define SANITIZER_COMMON_INTERCEPTORS_INIT \
2827  INIT_STRCMP;                             \
2828  INIT_STRNCMP;                            \
2829  INIT_STRCASECMP;                         \
2830  INIT_STRNCASECMP;                        \
2831  INIT_READ;                               \
2832  INIT_PREAD;                              \
2833  INIT_PREAD64;                            \
2834  INIT_READV;                              \
2835  INIT_PREADV;                             \
2836  INIT_PREADV64;                           \
2837  INIT_WRITE;                              \
2838  INIT_PWRITE;                             \
2839  INIT_PWRITE64;                           \
2840  INIT_WRITEV;                             \
2841  INIT_PWRITEV;                            \
2842  INIT_PWRITEV64;                          \
2843  INIT_PRCTL;                              \
2844  INIT_LOCALTIME_AND_FRIENDS;              \
2845  INIT_STRPTIME;                           \
2846  INIT_SCANF;                              \
2847  INIT_ISOC99_SCANF;                       \
2848  INIT_FREXP;                              \
2849  INIT_FREXPF_FREXPL;                      \
2850  INIT_GETPWNAM_AND_FRIENDS;               \
2851  INIT_GETPWNAM_R_AND_FRIENDS;             \
2852  INIT_CLOCK_GETTIME;                      \
2853  INIT_GETITIMER;                          \
2854  INIT_TIME;                               \
2855  INIT_GLOB;                               \
2856  INIT_WAIT;                               \
2857  INIT_INET;                               \
2858  INIT_PTHREAD_GETSCHEDPARAM;              \
2859  INIT_GETADDRINFO;                        \
2860  INIT_GETNAMEINFO;                        \
2861  INIT_GETSOCKNAME;                        \
2862  INIT_GETHOSTBYNAME;                      \
2863  INIT_GETHOSTBYNAME_R;                    \
2864  INIT_GETSOCKOPT;                         \
2865  INIT_ACCEPT;                             \
2866  INIT_ACCEPT4;                            \
2867  INIT_MODF;                               \
2868  INIT_RECVMSG;                            \
2869  INIT_GETPEERNAME;                        \
2870  INIT_IOCTL;                              \
2871  INIT_INET_ATON;                          \
2872  INIT_SYSINFO;                            \
2873  INIT_READDIR;                            \
2874  INIT_READDIR64;                          \
2875  INIT_PTRACE;                             \
2876  INIT_SETLOCALE;                          \
2877  INIT_GETCWD;                             \
2878  INIT_GET_CURRENT_DIR_NAME;               \
2879  INIT_STRTOIMAX;                          \
2880  INIT_MBSTOWCS;                           \
2881  INIT_MBSNRTOWCS;                         \
2882  INIT_WCSTOMBS;                           \
2883  INIT_WCSNRTOMBS;                         \
2884  INIT_TCGETATTR;                          \
2885  INIT_REALPATH;                           \
2886  INIT_CANONICALIZE_FILE_NAME;             \
2887  INIT_CONFSTR;                            \
2888  INIT_SCHED_GETAFFINITY;                  \
2889  INIT_STRERROR;                           \
2890  INIT_STRERROR_R;                         \
2891  INIT_SCANDIR;                            \
2892  INIT_SCANDIR64;                          \
2893  INIT_GETGROUPS;                          \
2894  INIT_POLL;                               \
2895  INIT_PPOLL;                              \
2896  INIT_WORDEXP;                            \
2897  INIT_SIGWAIT;                            \
2898  INIT_SIGWAITINFO;                        \
2899  INIT_SIGTIMEDWAIT;                       \
2900  INIT_SIGSETOPS;                          \
2901  INIT_SIGPENDING;                         \
2902  INIT_SIGPROCMASK;                        \
2903  INIT_BACKTRACE;                          \
2904  INIT__EXIT;                              \
2905  INIT_PTHREAD_MUTEX_LOCK;                 \
2906  INIT_PTHREAD_MUTEX_UNLOCK;               \
2907  INIT_PTHREAD_COND_WAIT;                  \
2908  INIT_PTHREAD_COND_INIT;                  \
2909  INIT_PTHREAD_COND_SIGNAL;                \
2910  INIT_PTHREAD_COND_BROADCAST;             \
2911  INIT_GETMNTENT;                          \
2912  INIT_GETMNTENT_R;                        \
2913  INIT_STATFS;                             \
2914  INIT_STATFS64;                           \
2915  INIT_STATVFS;                            \
2916  INIT_STATVFS64;                          \
2917  INIT_INITGROUPS;                         \
2918  INIT_ETHER;                              \
2919  INIT_ETHER_R;                            \
2920  INIT_SHMCTL;                             \
2921  INIT_RANDOM_R;                           \
2922  INIT_PTHREAD_ATTR_GET;                   \
2923  INIT_PTHREAD_ATTR_GETINHERITSCHED;       \
2924  INIT_PTHREAD_ATTR_GETAFFINITY_NP;        \
2925  INIT_TMPNAM;                             \
2926  INIT_TMPNAM_R;                           \
2927  INIT_TEMPNAM;                            \
2928  INIT_PTHREAD_SETNAME_NP;                 \
2929  INIT_SINCOS;                             \
2930  INIT_REMQUO;                             \
2931  INIT_LGAMMA;                             \
2932  INIT_LGAMMA_R;                           \
2933  INIT_DRAND48_R;                          \
2934  INIT_GETLINE;                            \
2935/**/
2936