sanitizer_common_interceptors.inc revision cf39032f101dfb3b97b1dfc7b6d03f5d89dff266
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_FD_ACQUIRE
19//   COMMON_INTERCEPTOR_FD_RELEASE
20//   COMMON_INTERCEPTOR_SET_THREAD_NAME
21//===----------------------------------------------------------------------===//
22#include "interception/interception.h"
23#include "sanitizer_platform_interceptors.h"
24
25#include <stdarg.h>
26
27#if SANITIZER_WINDOWS
28#define va_copy(dst, src) ((dst) = (src))
29#endif // _WIN32
30
31#if SANITIZER_INTERCEPT_STRCMP
32static inline int CharCmpX(unsigned char c1, unsigned char c2) {
33  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
34}
35
36INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
37  void *ctx;
38  COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
39  unsigned char c1, c2;
40  uptr i;
41  for (i = 0; ; i++) {
42    c1 = (unsigned char)s1[i];
43    c2 = (unsigned char)s2[i];
44    if (c1 != c2 || c1 == '\0') break;
45  }
46  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
47  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
48  return CharCmpX(c1, c2);
49}
50
51INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
52  void *ctx;
53  COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
54  unsigned char c1 = 0, c2 = 0;
55  uptr i;
56  for (i = 0; i < size; i++) {
57    c1 = (unsigned char)s1[i];
58    c2 = (unsigned char)s2[i];
59    if (c1 != c2 || c1 == '\0') break;
60  }
61  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
62  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
63  return CharCmpX(c1, c2);
64}
65
66#define INIT_STRCMP INTERCEPT_FUNCTION(strcmp)
67#define INIT_STRNCMP INTERCEPT_FUNCTION(strncmp)
68#else
69#define INIT_STRCMP
70#define INIT_STRNCMP
71#endif
72
73#if SANITIZER_INTERCEPT_STRCASECMP
74static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
75  int c1_low = ToLower(c1);
76  int c2_low = ToLower(c2);
77  return c1_low - c2_low;
78}
79
80INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
81  void *ctx;
82  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
83  unsigned char c1 = 0, c2 = 0;
84  uptr i;
85  for (i = 0; ; i++) {
86    c1 = (unsigned char)s1[i];
87    c2 = (unsigned char)s2[i];
88    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0')
89      break;
90  }
91  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
92  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
93  return CharCaseCmp(c1, c2);
94}
95
96INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
97  void *ctx;
98  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
99  unsigned char c1 = 0, c2 = 0;
100  uptr i;
101  for (i = 0; i < n; i++) {
102    c1 = (unsigned char)s1[i];
103    c2 = (unsigned char)s2[i];
104    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0')
105      break;
106  }
107  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
108  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
109  return CharCaseCmp(c1, c2);
110}
111
112#define INIT_STRCASECMP INTERCEPT_FUNCTION(strcasecmp)
113#define INIT_STRNCASECMP INTERCEPT_FUNCTION(strncasecmp)
114#else
115#define INIT_STRCASECMP
116#define INIT_STRNCASECMP
117#endif
118
119#if SANITIZER_INTERCEPT_FREXP
120INTERCEPTOR(double, frexp, double x, int *exp) {
121  void *ctx;
122  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
123  double res = REAL(frexp)(x, exp);
124  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
125  return res;
126}
127
128#define INIT_FREXP INTERCEPT_FUNCTION(frexp);
129#else
130#define INIT_FREXP
131#endif // SANITIZER_INTERCEPT_FREXP
132
133#if SANITIZER_INTERCEPT_FREXPF_FREXPL
134INTERCEPTOR(float, frexpf, float x, int *exp) {
135  void *ctx;
136  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
137  float res = REAL(frexpf)(x, exp);
138  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
139  return res;
140}
141
142INTERCEPTOR(long double, frexpl, long double x, int *exp) {
143  void *ctx;
144  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
145  long double res = REAL(frexpl)(x, exp);
146  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
147  return res;
148}
149
150#define INIT_FREXPF_FREXPL                       \
151  INTERCEPT_FUNCTION(frexpf);                    \
152  INTERCEPT_FUNCTION(frexpl)
153#else
154#define INIT_FREXPF_FREXPL
155#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
156
157#if SI_NOT_WINDOWS
158static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
159                        SIZE_T iovlen, SIZE_T maxlen) {
160  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
161    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
162    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
163    maxlen -= sz;
164  }
165}
166
167static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
168                       SIZE_T iovlen, SIZE_T maxlen) {
169  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
170  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
171    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
172    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
173    maxlen -= sz;
174  }
175}
176#endif
177
178#if SANITIZER_INTERCEPT_READ
179INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
180  void *ctx;
181  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
182  SSIZE_T res = REAL(read)(fd, ptr, count);
183  if (res > 0)
184    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
185  if (res >= 0 && fd >= 0)
186    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
187  return res;
188}
189#define INIT_READ INTERCEPT_FUNCTION(read)
190#else
191#define INIT_READ
192#endif
193
194#if SANITIZER_INTERCEPT_PREAD
195INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
196  void *ctx;
197  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
198  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
199  if (res > 0)
200    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
201  if (res >= 0 && fd >= 0)
202    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
203  return res;
204}
205#define INIT_PREAD INTERCEPT_FUNCTION(pread)
206#else
207#define INIT_PREAD
208#endif
209
210#if SANITIZER_INTERCEPT_PREAD64
211INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
212  void *ctx;
213  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
214  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
215  if (res > 0)
216    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
217  if (res >= 0 && fd >= 0)
218    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
219  return res;
220}
221#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
222#else
223#define INIT_PREAD64
224#endif
225
226#if SANITIZER_INTERCEPT_READV
227INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
228                        int iovcnt) {
229  void *ctx;
230  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
231  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
232  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
233  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
234  return res;
235}
236#define INIT_READV INTERCEPT_FUNCTION(readv)
237#else
238#define INIT_READV
239#endif
240
241#if SANITIZER_INTERCEPT_PREADV
242INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
243            OFF_T offset) {
244  void *ctx;
245  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
246  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
247  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
248  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
249  return res;
250}
251#define INIT_PREADV INTERCEPT_FUNCTION(preadv)
252#else
253#define INIT_PREADV
254#endif
255
256#if SANITIZER_INTERCEPT_PREADV64
257INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
258            OFF64_T offset) {
259  void *ctx;
260  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
261  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
262  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
263  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
264  return res;
265}
266#define INIT_PREADV64 INTERCEPT_FUNCTION(preadv64)
267#else
268#define INIT_PREADV64
269#endif
270
271#if SANITIZER_INTERCEPT_WRITE
272INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
273  void *ctx;
274  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
275  if (fd >= 0)
276    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
277  SSIZE_T res = REAL(write)(fd, ptr, count);
278  // FIXME: this check should be _before_ the call to REAL(write), not after
279  if (res > 0)
280    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
281  return res;
282}
283#define INIT_WRITE INTERCEPT_FUNCTION(write)
284#else
285#define INIT_WRITE
286#endif
287
288#if SANITIZER_INTERCEPT_PWRITE
289INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
290  void *ctx;
291  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
292  if (fd >= 0)
293    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
294  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
295  if (res > 0)
296    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
297  return res;
298}
299#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
300#else
301#define INIT_PWRITE
302#endif
303
304#if SANITIZER_INTERCEPT_PWRITE64
305INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
306            OFF64_T offset) {
307  void *ctx;
308  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
309  if (fd >= 0)
310    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
311  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
312  if (res > 0)
313    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
314  return res;
315}
316#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
317#else
318#define INIT_PWRITE64
319#endif
320
321#if SANITIZER_INTERCEPT_WRITEV
322INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
323                        int iovcnt) {
324  void *ctx;
325  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
326  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
327  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
328  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
329  return res;
330}
331#define INIT_WRITEV INTERCEPT_FUNCTION(writev)
332#else
333#define INIT_WRITEV
334#endif
335
336#if SANITIZER_INTERCEPT_PWRITEV
337INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
338            OFF_T offset) {
339  void *ctx;
340  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
341  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
342  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
343  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
344  return res;
345}
346#define INIT_PWRITEV INTERCEPT_FUNCTION(pwritev)
347#else
348#define INIT_PWRITEV
349#endif
350
351#if SANITIZER_INTERCEPT_PWRITEV64
352INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
353            OFF64_T offset) {
354  void *ctx;
355  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
356  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
357  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
358  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
359  return res;
360}
361#define INIT_PWRITEV64 INTERCEPT_FUNCTION(pwritev64)
362#else
363#define INIT_PWRITEV64
364#endif
365
366#if SANITIZER_INTERCEPT_PRCTL
367INTERCEPTOR(int, prctl, int option,
368            unsigned long arg2, unsigned long arg3,   // NOLINT
369            unsigned long arg4, unsigned long arg5) { // NOLINT
370  void *ctx;
371  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
372  static const int PR_SET_NAME = 15;
373  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
374  if (option == PR_SET_NAME) {
375    char buff[16];
376    internal_strncpy(buff, (char *)arg2, 15);
377    buff[15] = 0;
378    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
379  }
380  return res;
381}
382#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
383#else
384#define INIT_PRCTL
385#endif // SANITIZER_INTERCEPT_PRCTL
386
387
388#if SANITIZER_INTERCEPT_TIME
389INTERCEPTOR(unsigned long, time, unsigned long *t) {
390  void *ctx;
391  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
392  unsigned long res = REAL(time)(t);
393  if (t && res != (unsigned long)-1) {
394    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
395  }
396  return res;
397}
398#define INIT_TIME                                \
399  INTERCEPT_FUNCTION(time);
400#else
401#define INIT_TIME
402#endif // SANITIZER_INTERCEPT_TIME
403
404
405#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
406static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
407  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
408  if (tm->tm_zone)
409    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm->tm_zone,
410                                   REAL(strlen(tm->tm_zone)) + 1);
411}
412
413INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
414  void *ctx;
415  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
416  __sanitizer_tm *res = REAL(localtime)(timep);
417  if (res) {
418    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
419    unpoison_tm(ctx, res);
420  }
421  return res;
422}
423INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
424  void *ctx;
425  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
426  __sanitizer_tm *res = REAL(localtime_r)(timep, result);
427  if (res) {
428    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
429    unpoison_tm(ctx, res);
430  }
431  return res;
432}
433INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
434  void *ctx;
435  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
436  __sanitizer_tm *res = REAL(gmtime)(timep);
437  if (res) {
438    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
439    unpoison_tm(ctx, res);
440  }
441  return res;
442}
443INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
444  void *ctx;
445  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
446  __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
447  if (res) {
448    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
449    unpoison_tm(ctx, res);
450  }
451  return res;
452}
453INTERCEPTOR(char *, ctime, unsigned long *timep) {
454  void *ctx;
455  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
456  char *res = REAL(ctime)(timep);
457  if (res) {
458    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
459    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
460  }
461  return res;
462}
463INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
464  void *ctx;
465  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
466  char *res = REAL(ctime_r)(timep, result);
467  if (res) {
468    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
469    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
470  }
471  return res;
472}
473INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
474  void *ctx;
475  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
476  char *res = REAL(asctime)(tm);
477  if (res) {
478    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
479    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
480  }
481  return res;
482}
483INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
484  void *ctx;
485  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
486  char *res = REAL(asctime_r)(tm, result);
487  if (res) {
488    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
489    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
490  }
491  return res;
492}
493#define INIT_LOCALTIME_AND_FRIENDS               \
494  INTERCEPT_FUNCTION(localtime);                 \
495  INTERCEPT_FUNCTION(localtime_r);               \
496  INTERCEPT_FUNCTION(gmtime);                    \
497  INTERCEPT_FUNCTION(gmtime_r);                  \
498  INTERCEPT_FUNCTION(ctime);                     \
499  INTERCEPT_FUNCTION(ctime_r);                   \
500  INTERCEPT_FUNCTION(asctime);                   \
501  INTERCEPT_FUNCTION(asctime_r);
502#else
503#define INIT_LOCALTIME_AND_FRIENDS
504#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
505
506#if SANITIZER_INTERCEPT_SCANF
507
508#include "sanitizer_common_interceptors_scanf.inc"
509
510#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
511  {                                                                            \
512    void *ctx;                                                                 \
513    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
514    va_list aq;                                                                \
515    va_copy(aq, ap);                                                           \
516    int res = REAL(vname)(__VA_ARGS__);                                        \
517    if (res > 0)                                                               \
518      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
519    va_end(aq);                                                                \
520    return res;                                                                \
521  }
522
523INTERCEPTOR(int, vscanf, const char *format, va_list ap)
524VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
525
526INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
527VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
528
529INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
530VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
531
532#if SANITIZER_INTERCEPT_ISOC99_SCANF
533INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
534VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
535
536INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
537            va_list ap)
538VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
539
540INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
541VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
542#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF
543
544#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
545  {                                                                            \
546    void *ctx;                                                                 \
547    va_list ap;                                                                \
548    va_start(ap, format);                                                      \
549    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap);                     \
550    int res = vname(__VA_ARGS__, ap);                                          \
551    va_end(ap);                                                                \
552    return res;                                                                \
553  }
554
555INTERCEPTOR(int, scanf, const char *format, ...)
556SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
557
558INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
559SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
560
561INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
562SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
563
564#if SANITIZER_INTERCEPT_ISOC99_SCANF
565INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
566SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
567
568INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
569SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
570
571INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
572SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
573#endif
574
575#endif
576
577#if SANITIZER_INTERCEPT_SCANF
578#define INIT_SCANF             \
579  INTERCEPT_FUNCTION(scanf);   \
580  INTERCEPT_FUNCTION(sscanf);  \
581  INTERCEPT_FUNCTION(fscanf);  \
582  INTERCEPT_FUNCTION(vscanf);  \
583  INTERCEPT_FUNCTION(vsscanf); \
584  INTERCEPT_FUNCTION(vfscanf);
585#else
586#define INIT_SCANF
587#endif
588
589#if SANITIZER_INTERCEPT_ISOC99_SCANF
590#define INIT_ISOC99_SCANF               \
591  INTERCEPT_FUNCTION(__isoc99_scanf);   \
592  INTERCEPT_FUNCTION(__isoc99_sscanf);  \
593  INTERCEPT_FUNCTION(__isoc99_fscanf);  \
594  INTERCEPT_FUNCTION(__isoc99_vscanf);  \
595  INTERCEPT_FUNCTION(__isoc99_vsscanf); \
596  INTERCEPT_FUNCTION(__isoc99_vfscanf);
597#else
598#define INIT_ISOC99_SCANF
599#endif
600
601#if SANITIZER_INTERCEPT_IOCTL
602#include "sanitizer_common_interceptors_ioctl.inc"
603INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
604  void *ctx;
605  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
606
607  CHECK(ioctl_initialized);
608
609  // Note: TSan does not use common flags, and they are zero-initialized.
610  // This effectively disables ioctl handling in TSan.
611  if (!common_flags()->handle_ioctl)
612    return REAL(ioctl)(d, request, arg);
613
614  const ioctl_desc *desc = ioctl_lookup(request);
615  if (!desc)
616    Printf("WARNING: unknown ioctl %x\n", request);
617
618  if (desc)
619    ioctl_common_pre(ctx, desc, d, request, arg);
620  int res = REAL(ioctl)(d, request, arg);
621  // FIXME: some ioctls have different return values for success and failure.
622  if (desc && res != -1)
623    ioctl_common_post(ctx, desc, res, d, request, arg);
624  return res;
625}
626#define INIT_IOCTL \
627  ioctl_init();    \
628  INTERCEPT_FUNCTION(ioctl);
629#else
630#define INIT_IOCTL
631#endif
632
633
634#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
635INTERCEPTOR(void *, getpwnam, const char *name) {
636  void *ctx;
637  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
638  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
639  void *res = REAL(getpwnam)(name);
640  if (res != 0)
641    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
642  return res;
643}
644INTERCEPTOR(void *, getpwuid, u32 uid) {
645  void *ctx;
646  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
647  void *res = REAL(getpwuid)(uid);
648  if (res != 0)
649    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
650  return res;
651}
652INTERCEPTOR(void *, getgrnam, const char *name) {
653  void *ctx;
654  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
655  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
656  void *res = REAL(getgrnam)(name);
657  if (res != 0)
658    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
659  return res;
660}
661INTERCEPTOR(void *, getgrgid, u32 gid) {
662  void *ctx;
663  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
664  void *res = REAL(getgrgid)(gid);
665  if (res != 0)
666    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
667  return res;
668}
669#define INIT_GETPWNAM_AND_FRIENDS                  \
670  INTERCEPT_FUNCTION(getpwnam);                    \
671  INTERCEPT_FUNCTION(getpwuid);                    \
672  INTERCEPT_FUNCTION(getgrnam);                    \
673  INTERCEPT_FUNCTION(getgrgid);
674#else
675#define INIT_GETPWNAM_AND_FRIENDS
676#endif
677
678
679#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
680INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd,
681    char *buf, SIZE_T buflen, void **result) {
682  void *ctx;
683  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
684  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
685  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
686  if (!res) {
687    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
688    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
689  }
690  return res;
691}
692INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd,
693    char *buf, SIZE_T buflen, void **result) {
694  void *ctx;
695  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
696  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
697  if (!res) {
698    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
699    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
700  }
701  return res;
702}
703INTERCEPTOR(int, getgrnam_r, const char *name, void *grp,
704    char *buf, SIZE_T buflen, void **result) {
705  void *ctx;
706  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
707  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
708  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
709  if (!res) {
710    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
711    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
712  }
713  return res;
714}
715INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp,
716    char *buf, SIZE_T buflen, void **result) {
717  void *ctx;
718  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
719  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
720  if (!res) {
721    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
722    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
723  }
724  return res;
725}
726#define INIT_GETPWNAM_R_AND_FRIENDS                \
727  INTERCEPT_FUNCTION(getpwnam_r);                  \
728  INTERCEPT_FUNCTION(getpwuid_r);                  \
729  INTERCEPT_FUNCTION(getgrnam_r);                  \
730  INTERCEPT_FUNCTION(getgrgid_r);
731#else
732#define INIT_GETPWNAM_R_AND_FRIENDS
733#endif
734
735
736#if SANITIZER_INTERCEPT_CLOCK_GETTIME
737INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
738  void *ctx;
739  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
740  int res = REAL(clock_getres)(clk_id, tp);
741  if (!res && tp) {
742    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
743  }
744  return res;
745}
746INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
747  void *ctx;
748  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
749  int res = REAL(clock_gettime)(clk_id, tp);
750  if (!res) {
751    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
752  }
753  return res;
754}
755INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
756  void *ctx;
757  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
758  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
759  return REAL(clock_settime)(clk_id, tp);
760}
761#define INIT_CLOCK_GETTIME                         \
762  INTERCEPT_FUNCTION(clock_getres);                \
763  INTERCEPT_FUNCTION(clock_gettime);               \
764  INTERCEPT_FUNCTION(clock_settime);
765#else
766#define INIT_CLOCK_GETTIME
767#endif
768
769
770#if SANITIZER_INTERCEPT_GETITIMER
771INTERCEPTOR(int, getitimer, int which, void *curr_value) {
772  void *ctx;
773  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
774  int res = REAL(getitimer)(which, curr_value);
775  if (!res && curr_value) {
776    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
777  }
778  return res;
779}
780INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
781  void *ctx;
782  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
783  if (new_value)
784    COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
785  int res = REAL(setitimer)(which, new_value, old_value);
786  if (!res && old_value) {
787    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
788  }
789  return res;
790}
791#define INIT_GETITIMER                             \
792  INTERCEPT_FUNCTION(getitimer);                   \
793  INTERCEPT_FUNCTION(setitimer);
794#else
795#define INIT_GETITIMER
796#endif
797
798#if SANITIZER_INTERCEPT_GLOB
799static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
800  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
801  // +1 for NULL pointer at the end.
802  if (pglob->gl_pathv)
803    COMMON_INTERCEPTOR_WRITE_RANGE(
804        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
805  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
806    char *p = pglob->gl_pathv[i];
807    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
808  }
809}
810
811static THREADLOCAL __sanitizer_glob_t* pglob_copy;
812static THREADLOCAL void* glob_ctx;
813
814static void wrapped_gl_closedir(void *dir) {
815  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
816  pglob_copy->gl_closedir(dir);
817}
818
819static void *wrapped_gl_readdir(void *dir) {
820  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
821  return pglob_copy->gl_readdir(dir);
822}
823
824static void *wrapped_gl_opendir(const char *s) {
825  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
826  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
827  return pglob_copy->gl_opendir(s);
828}
829
830static int wrapped_gl_lstat(const char *s, void *st) {
831  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
832  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
833  return pglob_copy->gl_lstat(s, st);
834}
835
836static int wrapped_gl_stat(const char *s, void *st) {
837  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
838  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
839  return pglob_copy->gl_stat(s, st);
840}
841
842INTERCEPTOR(int, glob, const char *pattern, int flags,
843            int (*errfunc)(const char *epath, int eerrno),
844            __sanitizer_glob_t *pglob) {
845  void *ctx;
846  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
847  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
848                                  wrapped_gl_readdir, wrapped_gl_opendir,
849                                  wrapped_gl_lstat, wrapped_gl_stat};
850  if (flags & glob_altdirfunc) {
851    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
852    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
853    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
854    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
855    Swap(pglob->gl_stat, glob_copy.gl_stat);
856    pglob_copy = &glob_copy;
857    glob_ctx = ctx;
858  }
859  int res = REAL(glob)(pattern, flags, errfunc, pglob);
860  if (flags & glob_altdirfunc) {
861    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
862    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
863    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
864    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
865    Swap(pglob->gl_stat, glob_copy.gl_stat);
866  }
867  pglob_copy = 0;
868  glob_ctx = 0;
869  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
870  return res;
871}
872
873INTERCEPTOR(int, glob64, const char *pattern, int flags,
874            int (*errfunc)(const char *epath, int eerrno),
875            __sanitizer_glob_t *pglob) {
876  void *ctx;
877  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
878  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
879                                  wrapped_gl_readdir, wrapped_gl_opendir,
880                                  wrapped_gl_lstat, wrapped_gl_stat};
881  if (flags & glob_altdirfunc) {
882    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
883    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
884    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
885    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
886    Swap(pglob->gl_stat, glob_copy.gl_stat);
887    pglob_copy = &glob_copy;
888    glob_ctx = ctx;
889  }
890  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
891  if (flags & glob_altdirfunc) {
892    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
893    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
894    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
895    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
896    Swap(pglob->gl_stat, glob_copy.gl_stat);
897  }
898  pglob_copy = 0;
899  glob_ctx = 0;
900  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
901  return res;
902}
903#define INIT_GLOB           \
904  INTERCEPT_FUNCTION(glob); \
905  INTERCEPT_FUNCTION(glob64);
906#else  // SANITIZER_INTERCEPT_GLOB
907#define INIT_GLOB
908#endif  // SANITIZER_INTERCEPT_GLOB
909
910#if SANITIZER_INTERCEPT_WAIT
911// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
912// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
913// details.
914INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
915  void *ctx;
916  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
917  int res = REAL(wait)(status);
918  if (res != -1 && status)
919    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
920  return res;
921}
922INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
923  int options) {
924  void *ctx;
925  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
926  int res = REAL(waitid)(idtype, id, infop, options);
927  if (res != -1 && infop)
928    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
929  return res;
930}
931INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
932  void *ctx;
933  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
934  int res = REAL(waitpid)(pid, status, options);
935  if (res != -1 && status)
936    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
937  return res;
938}
939INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
940  void *ctx;
941  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
942  int res = REAL(wait3)(status, options, rusage);
943  if (res != -1) {
944    if (status)
945      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
946    if (rusage)
947      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
948  }
949  return res;
950}
951INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
952  void *ctx;
953  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
954  int res = REAL(wait4)(pid, status, options, rusage);
955  if (res != -1) {
956    if (status)
957      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
958    if (rusage)
959      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
960  }
961  return res;
962}
963#define INIT_WAIT                                \
964  INTERCEPT_FUNCTION(wait);                      \
965  INTERCEPT_FUNCTION(waitid);                    \
966  INTERCEPT_FUNCTION(waitpid);                   \
967  INTERCEPT_FUNCTION(wait3);                     \
968  INTERCEPT_FUNCTION(wait4);
969#else
970#define INIT_WAIT
971#endif
972
973#if SANITIZER_INTERCEPT_INET
974INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
975  void *ctx;
976  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
977  uptr sz = __sanitizer_in_addr_sz(af);
978  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
979  // FIXME: figure out read size based on the address family.
980  char *res = REAL(inet_ntop)(af, src, dst, size);
981  if (res)
982    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
983  return res;
984}
985INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
986  void *ctx;
987  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
988  // FIXME: figure out read size based on the address family.
989  int res = REAL(inet_pton)(af, src, dst);
990  if (res == 1) {
991    uptr sz = __sanitizer_in_addr_sz(af);
992    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
993  }
994  return res;
995}
996#define INIT_INET                                \
997  INTERCEPT_FUNCTION(inet_ntop);                 \
998  INTERCEPT_FUNCTION(inet_pton);
999#else
1000#define INIT_INET
1001#endif
1002
1003#if SANITIZER_INTERCEPT_INET
1004INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
1005  void *ctx;
1006  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
1007  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
1008  int res = REAL(inet_aton)(cp, dst);
1009  if (res != 0) {
1010    uptr sz = __sanitizer_in_addr_sz(af_inet);
1011    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
1012  }
1013  return res;
1014}
1015#define INIT_INET_ATON INTERCEPT_FUNCTION(inet_aton);
1016#else
1017#define INIT_INET_ATON
1018#endif
1019
1020#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
1021INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
1022  void *ctx;
1023  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
1024  int res = REAL(pthread_getschedparam)(thread, policy, param);
1025  if (res == 0) {
1026    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
1027    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
1028  }
1029  return res;
1030}
1031#define INIT_PTHREAD_GETSCHEDPARAM INTERCEPT_FUNCTION(pthread_getschedparam);
1032#else
1033#define INIT_PTHREAD_GETSCHEDPARAM
1034#endif
1035
1036#if SANITIZER_INTERCEPT_GETADDRINFO
1037INTERCEPTOR(int, getaddrinfo, char *node, char *service,
1038            struct __sanitizer_addrinfo *hints,
1039            struct __sanitizer_addrinfo **out) {
1040  void *ctx;
1041  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
1042  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
1043  if (service)
1044    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
1045  if (hints)
1046    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
1047  int res = REAL(getaddrinfo)(node, service, hints, out);
1048  if (res == 0 && out) {
1049    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
1050    struct __sanitizer_addrinfo *p = *out;
1051    while (p) {
1052      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
1053      if (p->ai_addr)
1054        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
1055      if (p->ai_canonname)
1056        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
1057                                       REAL(strlen)(p->ai_canonname) + 1);
1058      p = p->ai_next;
1059    }
1060  }
1061  return res;
1062}
1063#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
1064#else
1065#define INIT_GETADDRINFO
1066#endif
1067
1068#if SANITIZER_INTERCEPT_GETNAMEINFO
1069INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
1070            unsigned hostlen, char *serv, unsigned servlen, int flags) {
1071  void *ctx;
1072  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
1073                           serv, servlen, flags);
1074  // FIXME: consider adding READ_RANGE(sockaddr, salen)
1075  // There is padding in in_addr that may make this too noisy
1076  int res =
1077      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
1078  if (res == 0) {
1079    if (host && hostlen)
1080      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
1081    if (serv && servlen)
1082      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
1083  }
1084  return res;
1085}
1086#define INIT_GETNAMEINFO INTERCEPT_FUNCTION(getnameinfo);
1087#else
1088#define INIT_GETNAMEINFO
1089#endif
1090
1091#if SANITIZER_INTERCEPT_GETSOCKNAME
1092INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
1093  void *ctx;
1094  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
1095  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1096  int addrlen_in = *addrlen;
1097  int res = REAL(getsockname)(sock_fd, addr, addrlen);
1098  if (res == 0) {
1099    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
1100  }
1101  return res;
1102}
1103#define INIT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname);
1104#else
1105#define INIT_GETSOCKNAME
1106#endif
1107
1108#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1109static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
1110  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
1111  if (h->h_name)
1112    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
1113  char **p = h->h_aliases;
1114  while (*p) {
1115    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1116    ++p;
1117  }
1118  COMMON_INTERCEPTOR_WRITE_RANGE(
1119      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
1120  p = h->h_addr_list;
1121  while (*p) {
1122    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
1123    ++p;
1124  }
1125  COMMON_INTERCEPTOR_WRITE_RANGE(
1126      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
1127}
1128#endif
1129
1130#if SANITIZER_INTERCEPT_GETHOSTBYNAME
1131INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
1132  void *ctx;
1133  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
1134  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
1135  if (res) write_hostent(ctx, res);
1136  return res;
1137}
1138
1139INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
1140            int type) {
1141  void *ctx;
1142  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
1143  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1144  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
1145  if (res) write_hostent(ctx, res);
1146  return res;
1147}
1148
1149INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
1150  void *ctx;
1151  COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
1152  struct __sanitizer_hostent *res = REAL(gethostent)(fake);
1153  if (res) write_hostent(ctx, res);
1154  return res;
1155}
1156
1157INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
1158  void *ctx;
1159  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
1160  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
1161  if (res) write_hostent(ctx, res);
1162  return res;
1163}
1164#define INIT_GETHOSTBYNAME           \
1165  INTERCEPT_FUNCTION(gethostent);    \
1166  INTERCEPT_FUNCTION(gethostbyaddr); \
1167  INTERCEPT_FUNCTION(gethostbyname); \
1168  INTERCEPT_FUNCTION(gethostbyname2);
1169#else
1170#define INIT_GETHOSTBYNAME
1171#endif
1172
1173#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1174INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
1175            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
1176  void *ctx;
1177  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
1178                           h_errnop);
1179  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
1180  if (res == 0) {
1181    if (result) {
1182      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1183      if (*result) write_hostent(ctx, *result);
1184    }
1185    if (h_errnop)
1186      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1187  }
1188  return res;
1189}
1190
1191INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
1192            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1193            __sanitizer_hostent **result, int *h_errnop) {
1194  void *ctx;
1195  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
1196                           buflen, result, h_errnop);
1197  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1198  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
1199                                  h_errnop);
1200  if (res == 0) {
1201    if (result) {
1202      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1203      if (*result) write_hostent(ctx, *result);
1204    }
1205    if (h_errnop)
1206      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1207  }
1208  return res;
1209}
1210
1211INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
1212            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
1213            int *h_errnop) {
1214  void *ctx;
1215  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
1216                           h_errnop);
1217  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
1218  if (res == 0) {
1219    if (result) {
1220      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1221      if (*result) write_hostent(ctx, *result);
1222    }
1223    if (h_errnop)
1224      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1225  }
1226  return res;
1227}
1228
1229INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
1230            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1231            __sanitizer_hostent **result, int *h_errnop) {
1232  void *ctx;
1233  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
1234                           result, h_errnop);
1235  int res =
1236      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
1237  if (res == 0) {
1238    if (result) {
1239      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1240      if (*result) write_hostent(ctx, *result);
1241    }
1242    if (h_errnop)
1243      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1244  }
1245  return res;
1246}
1247#define INIT_GETHOSTBYNAME_R           \
1248  INTERCEPT_FUNCTION(gethostent_r);    \
1249  INTERCEPT_FUNCTION(gethostbyaddr_r); \
1250  INTERCEPT_FUNCTION(gethostbyname_r); \
1251  INTERCEPT_FUNCTION(gethostbyname2_r);
1252#else
1253#define INIT_GETHOSTBYNAME_R
1254#endif
1255
1256#if SANITIZER_INTERCEPT_GETSOCKOPT
1257INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
1258            int *optlen) {
1259  void *ctx;
1260  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
1261                           optlen);
1262  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
1263  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
1264  if (res == 0)
1265    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
1266  return res;
1267}
1268#define INIT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt);
1269#else
1270#define INIT_GETSOCKOPT
1271#endif
1272
1273#if SANITIZER_INTERCEPT_ACCEPT
1274INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
1275  void *ctx;
1276  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
1277  unsigned addrlen0;
1278  if (addrlen) {
1279    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1280    addrlen0 = *addrlen;
1281  }
1282  int fd2 = REAL(accept)(fd, addr, addrlen);
1283  if (fd2 >= 0) {
1284    if (fd >= 0)
1285      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1286    if (addr && addrlen)
1287      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1288  }
1289  return fd2;
1290}
1291#define INIT_ACCEPT INTERCEPT_FUNCTION(accept);
1292#else
1293#define INIT_ACCEPT
1294#endif
1295
1296#if SANITIZER_INTERCEPT_ACCEPT4
1297INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
1298  void *ctx;
1299  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
1300  unsigned addrlen0;
1301  if (addrlen) {
1302    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1303    addrlen0 = *addrlen;
1304  }
1305  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1306  if (fd2 >= 0) {
1307    if (fd >= 0)
1308      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1309    if (addr && addrlen)
1310      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1311  }
1312  return fd2;
1313}
1314#define INIT_ACCEPT4 INTERCEPT_FUNCTION(accept4);
1315#else
1316#define INIT_ACCEPT4
1317#endif
1318
1319#if SANITIZER_INTERCEPT_MODF
1320INTERCEPTOR(double, modf, double x, double *iptr) {
1321  void *ctx;
1322  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
1323  double res = REAL(modf)(x, iptr);
1324  if (iptr) {
1325    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1326  }
1327  return res;
1328}
1329INTERCEPTOR(float, modff, float x, float *iptr) {
1330  void *ctx;
1331  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
1332  float res = REAL(modff)(x, iptr);
1333  if (iptr) {
1334    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1335  }
1336  return res;
1337}
1338INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
1339  void *ctx;
1340  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
1341  long double res = REAL(modfl)(x, iptr);
1342  if (iptr) {
1343    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1344  }
1345  return res;
1346}
1347#define INIT_MODF            \
1348  INTERCEPT_FUNCTION(modf);  \
1349  INTERCEPT_FUNCTION(modff); \
1350  INTERCEPT_FUNCTION(modfl);
1351#else
1352#define INIT_MODF
1353#endif
1354
1355#if SANITIZER_INTERCEPT_RECVMSG
1356static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
1357                         SSIZE_T maxlen) {
1358  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
1359  if (msg->msg_name)
1360    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name,
1361                                   REAL(strlen)((char *)msg->msg_name) + 1);
1362  if (msg->msg_iov)
1363    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
1364                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
1365  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
1366  if (msg->msg_control)
1367    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
1368}
1369
1370INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
1371            int flags) {
1372  void *ctx;
1373  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
1374  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
1375  if (res >= 0) {
1376    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1377    if (msg) write_msghdr(ctx, msg, res);
1378  }
1379  return res;
1380}
1381#define INIT_RECVMSG INTERCEPT_FUNCTION(recvmsg);
1382#else
1383#define INIT_RECVMSG
1384#endif
1385
1386#if SANITIZER_INTERCEPT_GETPEERNAME
1387INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
1388  void *ctx;
1389  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
1390  unsigned addr_sz;
1391  if (addrlen) addr_sz = *addrlen;
1392  int res = REAL(getpeername)(sockfd, addr, addrlen);
1393  if (!res && addr && addrlen)
1394    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
1395  return res;
1396}
1397#define INIT_GETPEERNAME INTERCEPT_FUNCTION(getpeername);
1398#else
1399#define INIT_GETPEERNAME
1400#endif
1401
1402#if SANITIZER_INTERCEPT_SYSINFO
1403INTERCEPTOR(int, sysinfo, void *info) {
1404  void *ctx;
1405  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
1406  int res = REAL(sysinfo)(info);
1407  if (!res && info)
1408    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
1409  return res;
1410}
1411#define INIT_SYSINFO INTERCEPT_FUNCTION(sysinfo);
1412#else
1413#define INIT_SYSINFO
1414#endif
1415
1416#if SANITIZER_INTERCEPT_READDIR
1417INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
1418  void *ctx;
1419  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
1420  __sanitizer_dirent *res = REAL(readdir)(dirp);
1421  if (res)
1422    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1423  return res;
1424}
1425
1426INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
1427            __sanitizer_dirent **result) {
1428  void *ctx;
1429  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
1430  int res = REAL(readdir_r)(dirp, entry, result);
1431  if (!res) {
1432    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1433    if (*result)
1434      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1435  }
1436  return res;
1437}
1438
1439#define INIT_READDIR           \
1440  INTERCEPT_FUNCTION(readdir); \
1441  INTERCEPT_FUNCTION(readdir_r);
1442#else
1443#define INIT_READDIR
1444#endif
1445
1446#if SANITIZER_INTERCEPT_READDIR64
1447INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
1448  void *ctx;
1449  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
1450  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
1451  if (res)
1452    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1453  return res;
1454}
1455
1456INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
1457            __sanitizer_dirent64 **result) {
1458  void *ctx;
1459  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
1460  int res = REAL(readdir64_r)(dirp, entry, result);
1461  if (!res) {
1462    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1463    if (*result)
1464      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1465  }
1466  return res;
1467}
1468#define INIT_READDIR64           \
1469  INTERCEPT_FUNCTION(readdir64); \
1470  INTERCEPT_FUNCTION(readdir64_r);
1471#else
1472#define INIT_READDIR64
1473#endif
1474
1475#if SANITIZER_INTERCEPT_PTRACE
1476INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
1477  void *ctx;
1478  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
1479
1480  if (data) {
1481    if (request == ptrace_setregs)
1482      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
1483    else if (request == ptrace_setfpregs)
1484      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1485    else if (request == ptrace_setfpxregs)
1486      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1487    else if (request == ptrace_setsiginfo)
1488      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
1489    else if (request == ptrace_setregset) {
1490      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1491      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
1492    }
1493  }
1494
1495  uptr res = REAL(ptrace)(request, pid, addr, data);
1496
1497  if (!res && data) {
1498    // Note that PEEK* requests assing different meaning to the return value.
1499    // This function does not handle them (nor does it need to).
1500    if (request == ptrace_getregs)
1501      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
1502    else if (request == ptrace_getfpregs)
1503      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1504    else if (request == ptrace_getfpxregs)
1505      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1506    else if (request == ptrace_getsiginfo)
1507      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
1508    else if (request == ptrace_getregset) {
1509      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1510      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
1511    }
1512  }
1513  return res;
1514}
1515
1516#define INIT_PTRACE           \
1517  INTERCEPT_FUNCTION(ptrace);
1518#else
1519#define INIT_PTRACE
1520#endif
1521
1522#if SANITIZER_INTERCEPT_SETLOCALE
1523INTERCEPTOR(char *, setlocale, int category, char *locale) {
1524  void *ctx;
1525  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
1526  if (locale)
1527    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
1528  char *res = REAL(setlocale)(category, locale);
1529  if (res)
1530    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1531  return res;
1532}
1533
1534#define INIT_SETLOCALE           \
1535  INTERCEPT_FUNCTION(setlocale);
1536#else
1537#define INIT_SETLOCALE
1538#endif
1539
1540#if SANITIZER_INTERCEPT_GETCWD
1541INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
1542  void *ctx;
1543  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
1544  char *res = REAL(getcwd)(buf, size);
1545  if (res)
1546    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1547  return res;
1548}
1549#define INIT_GETCWD           \
1550  INTERCEPT_FUNCTION(getcwd);
1551#else
1552#define INIT_GETCWD
1553#endif
1554
1555#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
1556INTERCEPTOR(char *, get_current_dir_name, int fake) {
1557  void *ctx;
1558  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
1559  char *res = REAL(get_current_dir_name)(fake);
1560  if (res)
1561    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1562  return res;
1563}
1564
1565#define INIT_GET_CURRENT_DIR_NAME           \
1566  INTERCEPT_FUNCTION(get_current_dir_name);
1567#else
1568#define INIT_GET_CURRENT_DIR_NAME
1569#endif
1570
1571#if SANITIZER_INTERCEPT_STRTOIMAX
1572INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
1573  void *ctx;
1574  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
1575  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
1576  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1577  return res;
1578}
1579
1580INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
1581  void *ctx;
1582  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
1583  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
1584  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1585  return res;
1586}
1587
1588#define INIT_STRTOIMAX           \
1589  INTERCEPT_FUNCTION(strtoimax); \
1590  INTERCEPT_FUNCTION(strtoumax);
1591#else
1592#define INIT_STRTOIMAX
1593#endif
1594
1595#if SANITIZER_INTERCEPT_MBSTOWCS
1596INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
1597  void *ctx;
1598  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
1599  SIZE_T res = REAL(mbstowcs)(dest, src, len);
1600  if (res != (SIZE_T) - 1 && dest) {
1601    SIZE_T write_cnt = res + (res < len);
1602    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1603  }
1604  return res;
1605}
1606
1607INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
1608            void *ps) {
1609  void *ctx;
1610  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
1611  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1612  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1613  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
1614  if (res != (SIZE_T)(-1) && dest && src) {
1615    // This function, and several others, may or may not write the terminating
1616    // \0 character. They write it iff they clear *src.
1617    SIZE_T write_cnt = res + !*src;
1618    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1619  }
1620  return res;
1621}
1622
1623#define INIT_MBSTOWCS           \
1624  INTERCEPT_FUNCTION(mbstowcs); \
1625  INTERCEPT_FUNCTION(mbsrtowcs);
1626#else
1627#define INIT_MBSTOWCS
1628#endif
1629
1630#if SANITIZER_INTERCEPT_MBSNRTOWCS
1631INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
1632            SIZE_T len, void *ps) {
1633  void *ctx;
1634  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
1635  if (src) {
1636    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1637    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1638  }
1639  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1640  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
1641  if (res != (SIZE_T)(-1) && dest && src) {
1642    SIZE_T write_cnt = res + !*src;
1643    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1644  }
1645  return res;
1646}
1647
1648#define INIT_MBSNRTOWCS INTERCEPT_FUNCTION(mbsnrtowcs);
1649#else
1650#define INIT_MBSNRTOWCS
1651#endif
1652
1653#if SANITIZER_INTERCEPT_WCSTOMBS
1654INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
1655  void *ctx;
1656  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
1657  SIZE_T res = REAL(wcstombs)(dest, src, len);
1658  if (res != (SIZE_T) - 1 && dest) {
1659    SIZE_T write_cnt = res + (res < len);
1660    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1661  }
1662  return res;
1663}
1664
1665INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
1666            void *ps) {
1667  void *ctx;
1668  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
1669  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1670  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1671  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
1672  if (res != (SIZE_T) - 1 && dest && src) {
1673    SIZE_T write_cnt = res + !*src;
1674    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1675  }
1676  return res;
1677}
1678
1679#define INIT_WCSTOMBS           \
1680  INTERCEPT_FUNCTION(wcstombs); \
1681  INTERCEPT_FUNCTION(wcsrtombs);
1682#else
1683#define INIT_WCSTOMBS
1684#endif
1685
1686#if SANITIZER_INTERCEPT_WCSNRTOMBS
1687INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
1688            SIZE_T len, void *ps) {
1689  void *ctx;
1690  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
1691  if (src) {
1692    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1693    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1694  }
1695  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1696  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
1697  if (res != (SIZE_T) - 1 && dest && src) {
1698    SIZE_T write_cnt = res + !*src;
1699    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1700  }
1701  return res;
1702}
1703
1704#define INIT_WCSNRTOMBS INTERCEPT_FUNCTION(wcsnrtombs);
1705#else
1706#define INIT_WCSNRTOMBS
1707#endif
1708
1709
1710#if SANITIZER_INTERCEPT_TCGETATTR
1711INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
1712  void *ctx;
1713  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
1714  int res = REAL(tcgetattr)(fd, termios_p);
1715  if (!res && termios_p)
1716    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
1717  return res;
1718}
1719
1720#define INIT_TCGETATTR INTERCEPT_FUNCTION(tcgetattr);
1721#else
1722#define INIT_TCGETATTR
1723#endif
1724
1725
1726#if SANITIZER_INTERCEPT_REALPATH
1727INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
1728  void *ctx;
1729  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
1730  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1731
1732  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
1733  // version of a versioned symbol. For realpath(), this gives us something
1734  // (called __old_realpath) that does not handle NULL in the second argument.
1735  // Handle it as part of the interceptor.
1736  char *allocated_path = 0;
1737  if (!resolved_path)
1738    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
1739
1740  char *res = REAL(realpath)(path, resolved_path);
1741  if (allocated_path && !res)
1742    WRAP(free)(allocated_path);
1743  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1744  return res;
1745}
1746#define INIT_REALPATH INTERCEPT_FUNCTION(realpath);
1747#else
1748#define INIT_REALPATH
1749#endif
1750
1751#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
1752INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
1753  void *ctx;
1754  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
1755  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1756  char *res = REAL(canonicalize_file_name)(path);
1757  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1758  return res;
1759}
1760#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name);
1761#else
1762#define INIT_CANONICALIZE_FILE_NAME
1763#endif
1764
1765#if SANITIZER_INTERCEPT_CONFSTR
1766INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
1767  void *ctx;
1768  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
1769  SIZE_T res = REAL(confstr)(name, buf, len);
1770  if (buf && res)
1771    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
1772  return res;
1773}
1774#define INIT_CONFSTR INTERCEPT_FUNCTION(confstr);
1775#else
1776#define INIT_CONFSTR
1777#endif
1778
1779#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
1780INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
1781  void *ctx;
1782  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
1783  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
1784  if (mask && !res)
1785    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
1786  return res;
1787}
1788#define INIT_SCHED_GETAFFINITY INTERCEPT_FUNCTION(sched_getaffinity);
1789#else
1790#define INIT_SCHED_GETAFFINITY
1791#endif
1792
1793#if SANITIZER_INTERCEPT_STRERROR
1794INTERCEPTOR(char *, strerror, int errnum) {
1795  void *ctx;
1796  COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
1797  char *res = REAL(strerror)(errnum);
1798  if (res)
1799    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1800  return res;
1801}
1802#define INIT_STRERROR INTERCEPT_FUNCTION(strerror);
1803#else
1804#define INIT_STRERROR
1805#endif
1806
1807#if SANITIZER_INTERCEPT_STRERROR_R
1808INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
1809  void *ctx;
1810  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
1811  char *res = REAL(strerror_r)(errnum, buf, buflen);
1812  // There are 2 versions of strerror_r:
1813  //  * POSIX version returns 0 on success, negative error code on failure,
1814  //    writes message to buf.
1815  //  * GNU version returns message pointer, which points to either buf or some
1816  //    static storage.
1817  SIZE_T posix_res = (SIZE_T)res;
1818  if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
1819    // POSIX version. Spec is not clear on whether buf is NULL-terminated.
1820    // At least on OSX, buf contents are valid even when the call fails.
1821    SIZE_T sz = internal_strnlen(buf, buflen);
1822    if (sz < buflen) ++sz;
1823    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
1824  } else {
1825    // GNU version.
1826    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1827  }
1828  return res;
1829}
1830#define INIT_STRERROR_R INTERCEPT_FUNCTION(strerror_r);
1831#else
1832#define INIT_STRERROR_R
1833#endif
1834
1835#if SANITIZER_INTERCEPT_SCANDIR
1836typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
1837typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
1838                                const struct __sanitizer_dirent **);
1839
1840static THREADLOCAL void *scandir_ctx;
1841static THREADLOCAL scandir_filter_f scandir_filter;
1842static THREADLOCAL scandir_compar_f scandir_compar;
1843
1844static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
1845  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 1);
1846  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, dir, dir->d_reclen);
1847  return scandir_filter(dir);
1848}
1849
1850static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
1851                                  const struct __sanitizer_dirent **b) {
1852  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 2);
1853  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, a, sizeof(*a));
1854  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *a, (*a)->d_reclen);
1855  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, b, sizeof(*b));
1856  COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *b, (*b)->d_reclen);
1857  return scandir_compar(a, b);
1858}
1859
1860INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
1861            scandir_filter_f filter, scandir_compar_f compar) {
1862  void *ctx;
1863  COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
1864  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
1865  CHECK_EQ(0, scandir_ctx);
1866  scandir_ctx = ctx;
1867  scandir_filter = filter;
1868  scandir_compar = compar;
1869  int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : 0,
1870                          compar ? wrapped_scandir_compar : 0);
1871  scandir_ctx = 0;
1872  scandir_filter = 0;
1873  scandir_compar = 0;
1874  if (namelist && res > 0) {
1875    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
1876    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
1877    for (int i = 0; i < res; ++i)
1878      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
1879                                     (*namelist)[i]->d_reclen);
1880  }
1881  return res;
1882}
1883#define INIT_SCANDIR INTERCEPT_FUNCTION(scandir);
1884#else
1885#define INIT_SCANDIR
1886#endif
1887
1888#if SANITIZER_INTERCEPT_SCANDIR64
1889typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
1890typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
1891                                  const struct __sanitizer_dirent64 **);
1892
1893static THREADLOCAL void *scandir64_ctx;
1894static THREADLOCAL scandir64_filter_f scandir64_filter;
1895static THREADLOCAL scandir64_compar_f scandir64_compar;
1896
1897static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
1898  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 1);
1899  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, dir, dir->d_reclen);
1900  return scandir64_filter(dir);
1901}
1902
1903static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
1904                                    const struct __sanitizer_dirent64 **b) {
1905  COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 2);
1906  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, a, sizeof(*a));
1907  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *a, (*a)->d_reclen);
1908  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, b, sizeof(*b));
1909  COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *b, (*b)->d_reclen);
1910  return scandir64_compar(a, b);
1911}
1912
1913INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
1914            scandir64_filter_f filter, scandir64_compar_f compar) {
1915  void *ctx;
1916  COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
1917  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
1918  CHECK_EQ(0, scandir64_ctx);
1919  scandir64_ctx = ctx;
1920  scandir64_filter = filter;
1921  scandir64_compar = compar;
1922  int res =
1923      REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : 0,
1924                      compar ? wrapped_scandir64_compar : 0);
1925  scandir64_ctx = 0;
1926  scandir64_filter = 0;
1927  scandir64_compar = 0;
1928  if (namelist && res > 0) {
1929    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
1930    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
1931    for (int i = 0; i < res; ++i)
1932      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
1933                                     (*namelist)[i]->d_reclen);
1934  }
1935  return res;
1936}
1937#define INIT_SCANDIR64 INTERCEPT_FUNCTION(scandir64);
1938#else
1939#define INIT_SCANDIR64
1940#endif
1941
1942#if SANITIZER_INTERCEPT_GETGROUPS
1943INTERCEPTOR(int, getgroups, int size, u32 *lst) {
1944  void *ctx;
1945  COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
1946  int res = REAL(getgroups)(size, lst);
1947  if (res && lst)
1948    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
1949  return res;
1950}
1951#define INIT_GETGROUPS INTERCEPT_FUNCTION(getgroups);
1952#else
1953#define INIT_GETGROUPS
1954#endif
1955
1956#if SANITIZER_INTERCEPT_POLL
1957static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
1958                        __sanitizer_nfds_t nfds) {
1959  for (unsigned i = 0; i < nfds; ++i) {
1960    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
1961    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
1962  }
1963}
1964
1965static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
1966                         __sanitizer_nfds_t nfds) {
1967  for (unsigned i = 0; i < nfds; ++i)
1968    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
1969                                   sizeof(fds[i].revents));
1970}
1971
1972INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
1973            int timeout) {
1974  void *ctx;
1975  COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
1976  if (fds && nfds) read_pollfd(ctx, fds, nfds);
1977  int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
1978  if (fds && nfds) write_pollfd(ctx, fds, nfds);
1979  return res;
1980}
1981#define INIT_POLL INTERCEPT_FUNCTION(poll);
1982#else
1983#define INIT_POLL
1984#endif
1985
1986#if SANITIZER_INTERCEPT_PPOLL
1987INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
1988            void *timeout_ts, __sanitizer_sigset_t *sigmask) {
1989  void *ctx;
1990  COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
1991  if (fds && nfds) read_pollfd(ctx, fds, nfds);
1992  if (timeout_ts)
1993    COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
1994  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
1995  int res =
1996      COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
1997  if (fds && nfds) write_pollfd(ctx, fds, nfds);
1998  return res;
1999}
2000#define INIT_PPOLL INTERCEPT_FUNCTION(ppoll);
2001#else
2002#define INIT_PPOLL
2003#endif
2004
2005#if SANITIZER_INTERCEPT_WORDEXP
2006INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
2007  void *ctx;
2008  COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
2009  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
2010  int res = REAL(wordexp)(s, p, flags);
2011  if (!res && p) {
2012    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
2013    if (p->we_wordc)
2014      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
2015                                     sizeof(*p->we_wordv) * p->we_wordc);
2016    for (uptr i = 0; i < p->we_wordc; ++i) {
2017      char *w = p->we_wordv[i];
2018      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
2019    }
2020  }
2021  return res;
2022}
2023#define INIT_WORDEXP INTERCEPT_FUNCTION(wordexp);
2024#else
2025#define INIT_WORDEXP
2026#endif
2027
2028#if SANITIZER_INTERCEPT_SIGWAIT
2029INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
2030  void *ctx;
2031  COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
2032  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2033  int res = REAL(sigwait)(set, sig);
2034  if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
2035  return res;
2036}
2037#define INIT_SIGWAIT INTERCEPT_FUNCTION(sigwait);
2038#else
2039#define INIT_SIGWAIT
2040#endif
2041
2042#if SANITIZER_INTERCEPT_SIGWAITINFO
2043INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
2044  void *ctx;
2045  COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
2046  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2047  int res = REAL(sigwaitinfo)(set, info);
2048  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
2049  return res;
2050}
2051#define INIT_SIGWAITINFO INTERCEPT_FUNCTION(sigwaitinfo);
2052#else
2053#define INIT_SIGWAITINFO
2054#endif
2055
2056#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
2057INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
2058            void *timeout) {
2059  void *ctx;
2060  COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
2061  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
2062  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2063  int res = REAL(sigtimedwait)(set, info, timeout);
2064  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
2065  return res;
2066}
2067#define INIT_SIGTIMEDWAIT INTERCEPT_FUNCTION(sigtimedwait);
2068#else
2069#define INIT_SIGTIMEDWAIT
2070#endif
2071
2072#if SANITIZER_INTERCEPT_SIGSETOPS
2073INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
2074  void *ctx;
2075  COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
2076  int res = REAL(sigemptyset)(set);
2077  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
2078  return res;
2079}
2080
2081INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
2082  void *ctx;
2083  COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
2084  int res = REAL(sigfillset)(set);
2085  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
2086  return res;
2087}
2088#define INIT_SIGSETOPS             \
2089  INTERCEPT_FUNCTION(sigemptyset); \
2090  INTERCEPT_FUNCTION(sigfillset);
2091#else
2092#define INIT_SIGSETOPS
2093#endif
2094
2095#if SANITIZER_INTERCEPT_SIGPENDING
2096INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
2097  void *ctx;
2098  COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
2099  int res = REAL(sigpending)(set);
2100  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
2101  return res;
2102}
2103#define INIT_SIGPENDING INTERCEPT_FUNCTION(sigpending);
2104#else
2105#define INIT_SIGPENDING
2106#endif
2107
2108#if SANITIZER_INTERCEPT_SIGPROCMASK
2109INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
2110            __sanitizer_sigset_t *oldset) {
2111  void *ctx;
2112  COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
2113  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
2114  int res = REAL(sigprocmask)(how, set, oldset);
2115  if (!res && oldset)
2116    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
2117  return res;
2118}
2119#define INIT_SIGPROCMASK INTERCEPT_FUNCTION(sigprocmask);
2120#else
2121#define INIT_SIGPROCMASK
2122#endif
2123
2124#if SANITIZER_INTERCEPT_BACKTRACE
2125INTERCEPTOR(int, backtrace, void **buffer, int size) {
2126  void *ctx;
2127  COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
2128  int res = REAL(backtrace)(buffer, size);
2129  if (res && buffer)
2130    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
2131  return res;
2132}
2133
2134INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
2135  void *ctx;
2136  COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
2137  if (buffer && size)
2138    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
2139  char ** res = REAL(backtrace_symbols)(buffer, size);
2140  if (res && size) {
2141    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
2142    for (int i = 0; i < size; ++i)
2143      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
2144  }
2145  return res;
2146}
2147#define INIT_BACKTRACE           \
2148  INTERCEPT_FUNCTION(backtrace); \
2149  INTERCEPT_FUNCTION(backtrace_symbols);
2150#else
2151#define INIT_BACKTRACE
2152#endif
2153
2154#define SANITIZER_COMMON_INTERCEPTORS_INIT \
2155  INIT_STRCMP;                             \
2156  INIT_STRNCMP;                            \
2157  INIT_STRCASECMP;                         \
2158  INIT_STRNCASECMP;                        \
2159  INIT_READ;                               \
2160  INIT_PREAD;                              \
2161  INIT_PREAD64;                            \
2162  INIT_READV;                              \
2163  INIT_PREADV;                             \
2164  INIT_PREADV64;                           \
2165  INIT_WRITE;                              \
2166  INIT_PWRITE;                             \
2167  INIT_PWRITE64;                           \
2168  INIT_WRITEV;                             \
2169  INIT_PWRITEV;                            \
2170  INIT_PWRITEV64;                          \
2171  INIT_PRCTL;                              \
2172  INIT_LOCALTIME_AND_FRIENDS;              \
2173  INIT_SCANF;                              \
2174  INIT_ISOC99_SCANF;                       \
2175  INIT_FREXP;                              \
2176  INIT_FREXPF_FREXPL;                      \
2177  INIT_GETPWNAM_AND_FRIENDS;               \
2178  INIT_GETPWNAM_R_AND_FRIENDS;             \
2179  INIT_CLOCK_GETTIME;                      \
2180  INIT_GETITIMER;                          \
2181  INIT_TIME;                               \
2182  INIT_GLOB;                               \
2183  INIT_WAIT;                               \
2184  INIT_INET;                               \
2185  INIT_PTHREAD_GETSCHEDPARAM;              \
2186  INIT_GETADDRINFO;                        \
2187  INIT_GETNAMEINFO;                        \
2188  INIT_GETSOCKNAME;                        \
2189  INIT_GETHOSTBYNAME;                      \
2190  INIT_GETHOSTBYNAME_R;                    \
2191  INIT_GETSOCKOPT;                         \
2192  INIT_ACCEPT;                             \
2193  INIT_ACCEPT4;                            \
2194  INIT_MODF;                               \
2195  INIT_RECVMSG;                            \
2196  INIT_GETPEERNAME;                        \
2197  INIT_IOCTL;                              \
2198  INIT_INET_ATON;                          \
2199  INIT_SYSINFO;                            \
2200  INIT_READDIR;                            \
2201  INIT_READDIR64;                          \
2202  INIT_PTRACE;                             \
2203  INIT_SETLOCALE;                          \
2204  INIT_GETCWD;                             \
2205  INIT_GET_CURRENT_DIR_NAME;               \
2206  INIT_STRTOIMAX;                          \
2207  INIT_MBSTOWCS;                           \
2208  INIT_MBSNRTOWCS;                         \
2209  INIT_WCSTOMBS;                           \
2210  INIT_WCSNRTOMBS;                         \
2211  INIT_TCGETATTR;                          \
2212  INIT_REALPATH;                           \
2213  INIT_CANONICALIZE_FILE_NAME;             \
2214  INIT_CONFSTR;                            \
2215  INIT_SCHED_GETAFFINITY;                  \
2216  INIT_STRERROR;                           \
2217  INIT_STRERROR_R;                         \
2218  INIT_SCANDIR;                            \
2219  INIT_SCANDIR64;                          \
2220  INIT_GETGROUPS;                          \
2221  INIT_POLL;                               \
2222  INIT_PPOLL;                              \
2223  INIT_WORDEXP;                            \
2224  INIT_SIGWAIT;                            \
2225  INIT_SIGWAITINFO;                        \
2226  INIT_SIGTIMEDWAIT;                       \
2227  INIT_SIGSETOPS;                          \
2228  INIT_SIGPENDING;                         \
2229  INIT_SIGPROCMASK;                        \
2230  INIT_BACKTRACE;
2231