sanitizer_common_interceptors.inc revision 212008328600e3b966fe5363e84d7fa824eafe77
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
406INTERCEPTOR(void *, localtime, unsigned long *timep) {
407  void *ctx;
408  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
409  void *res = REAL(localtime)(timep);
410  if (res) {
411    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
412    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
413  }
414  return res;
415}
416INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) {
417  void *ctx;
418  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
419  void *res = REAL(localtime_r)(timep, result);
420  if (res) {
421    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
422    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
423  }
424  return res;
425}
426INTERCEPTOR(void *, gmtime, unsigned long *timep) {
427  void *ctx;
428  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
429  void *res = REAL(gmtime)(timep);
430  if (res) {
431    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
432    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
433  }
434  return res;
435}
436INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) {
437  void *ctx;
438  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
439  void *res = REAL(gmtime_r)(timep, result);
440  if (res) {
441    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
442    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
443  }
444  return res;
445}
446INTERCEPTOR(char *, ctime, unsigned long *timep) {
447  void *ctx;
448  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
449  char *res = REAL(ctime)(timep);
450  if (res) {
451    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
452    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
453  }
454  return res;
455}
456INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
457  void *ctx;
458  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
459  char *res = REAL(ctime_r)(timep, result);
460  if (res) {
461    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
462    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
463  }
464  return res;
465}
466INTERCEPTOR(char *, asctime, void *tm) {
467  void *ctx;
468  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
469  char *res = REAL(asctime)(tm);
470  if (res) {
471    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
472    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
473  }
474  return res;
475}
476INTERCEPTOR(char *, asctime_r, void *tm, char *result) {
477  void *ctx;
478  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
479  char *res = REAL(asctime_r)(tm, result);
480  if (res) {
481    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
482    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
483  }
484  return res;
485}
486#define INIT_LOCALTIME_AND_FRIENDS               \
487  INTERCEPT_FUNCTION(localtime);                 \
488  INTERCEPT_FUNCTION(localtime_r);               \
489  INTERCEPT_FUNCTION(gmtime);                    \
490  INTERCEPT_FUNCTION(gmtime_r);                  \
491  INTERCEPT_FUNCTION(ctime);                     \
492  INTERCEPT_FUNCTION(ctime_r);                   \
493  INTERCEPT_FUNCTION(asctime);                   \
494  INTERCEPT_FUNCTION(asctime_r);
495#else
496#define INIT_LOCALTIME_AND_FRIENDS
497#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
498
499#if SANITIZER_INTERCEPT_SCANF
500
501#include "sanitizer_common_interceptors_scanf.inc"
502
503#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
504  {                                                                            \
505    void *ctx;                                                                 \
506    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
507    va_list aq;                                                                \
508    va_copy(aq, ap);                                                           \
509    int res = REAL(vname)(__VA_ARGS__);                                        \
510    if (res > 0)                                                               \
511      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
512    va_end(aq);                                                                \
513    return res;                                                                \
514  }
515
516INTERCEPTOR(int, vscanf, const char *format, va_list ap)
517VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
518
519INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
520VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
521
522INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
523VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
524
525#if SANITIZER_INTERCEPT_ISOC99_SCANF
526INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
527VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
528
529INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
530            va_list ap)
531VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
532
533INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
534VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
535#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF
536
537#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
538  {                                                                            \
539    void *ctx;                                                                 \
540    COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__);                          \
541    va_list ap;                                                                \
542    va_start(ap, format);                                                      \
543    int res = vname(__VA_ARGS__, ap);                                          \
544    va_end(ap);                                                                \
545    return res;                                                                \
546  }
547
548INTERCEPTOR(int, scanf, const char *format, ...)
549SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
550
551INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
552SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
553
554INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
555SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
556
557#if SANITIZER_INTERCEPT_ISOC99_SCANF
558INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
559SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
560
561INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
562SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
563
564INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
565SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
566#endif
567
568#define INIT_SCANF                                                             \
569  INTERCEPT_FUNCTION(scanf);                                                   \
570  INTERCEPT_FUNCTION(sscanf);                                                  \
571  INTERCEPT_FUNCTION(fscanf);                                                  \
572  INTERCEPT_FUNCTION(vscanf);                                                  \
573  INTERCEPT_FUNCTION(vsscanf);                                                 \
574  INTERCEPT_FUNCTION(vfscanf);                                                 \
575  INTERCEPT_FUNCTION(__isoc99_scanf);                                          \
576  INTERCEPT_FUNCTION(__isoc99_sscanf);                                         \
577  INTERCEPT_FUNCTION(__isoc99_fscanf);                                         \
578  INTERCEPT_FUNCTION(__isoc99_vscanf);                                         \
579  INTERCEPT_FUNCTION(__isoc99_vsscanf);                                        \
580  INTERCEPT_FUNCTION(__isoc99_vfscanf);
581
582#else
583#define INIT_SCANF
584#endif
585
586
587#if SANITIZER_INTERCEPT_IOCTL
588#include "sanitizer_common_interceptors_ioctl.inc"
589INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
590  void *ctx;
591  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
592
593  CHECK(ioctl_initialized);
594
595  // Note: TSan does not use common flags, and they are zero-initialized.
596  // This effectively disables ioctl handling in TSan.
597  if (!common_flags()->handle_ioctl)
598    return REAL(ioctl)(d, request, arg);
599
600  const ioctl_desc *desc = ioctl_lookup(request);
601  if (!desc)
602    Printf("WARNING: unknown ioctl %x\n", request);
603
604  if (desc)
605    ioctl_common_pre(ctx, desc, d, request, arg);
606  int res = REAL(ioctl)(d, request, arg);
607  // FIXME: some ioctls have different return values for success and failure.
608  if (desc && res != -1)
609    ioctl_common_post(ctx, desc, res, d, request, arg);
610  return res;
611}
612#define INIT_IOCTL \
613  ioctl_init();    \
614  INTERCEPT_FUNCTION(ioctl);
615#else
616#define INIT_IOCTL
617#endif
618
619
620#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
621INTERCEPTOR(void *, getpwnam, const char *name) {
622  void *ctx;
623  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
624  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
625  void *res = REAL(getpwnam)(name);
626  if (res != 0)
627    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
628  return res;
629}
630INTERCEPTOR(void *, getpwuid, u32 uid) {
631  void *ctx;
632  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
633  void *res = REAL(getpwuid)(uid);
634  if (res != 0)
635    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
636  return res;
637}
638INTERCEPTOR(void *, getgrnam, const char *name) {
639  void *ctx;
640  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
641  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
642  void *res = REAL(getgrnam)(name);
643  if (res != 0)
644    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
645  return res;
646}
647INTERCEPTOR(void *, getgrgid, u32 gid) {
648  void *ctx;
649  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
650  void *res = REAL(getgrgid)(gid);
651  if (res != 0)
652    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
653  return res;
654}
655#define INIT_GETPWNAM_AND_FRIENDS                  \
656  INTERCEPT_FUNCTION(getpwnam);                    \
657  INTERCEPT_FUNCTION(getpwuid);                    \
658  INTERCEPT_FUNCTION(getgrnam);                    \
659  INTERCEPT_FUNCTION(getgrgid);
660#else
661#define INIT_GETPWNAM_AND_FRIENDS
662#endif
663
664
665#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
666INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd,
667    char *buf, SIZE_T buflen, void **result) {
668  void *ctx;
669  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
670  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
671  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
672  if (!res) {
673    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
674    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
675  }
676  return res;
677}
678INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd,
679    char *buf, SIZE_T buflen, void **result) {
680  void *ctx;
681  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
682  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
683  if (!res) {
684    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
685    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
686  }
687  return res;
688}
689INTERCEPTOR(int, getgrnam_r, const char *name, void *grp,
690    char *buf, SIZE_T buflen, void **result) {
691  void *ctx;
692  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
693  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
694  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
695  if (!res) {
696    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
697    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
698  }
699  return res;
700}
701INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp,
702    char *buf, SIZE_T buflen, void **result) {
703  void *ctx;
704  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
705  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
706  if (!res) {
707    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
708    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
709  }
710  return res;
711}
712#define INIT_GETPWNAM_R_AND_FRIENDS                \
713  INTERCEPT_FUNCTION(getpwnam_r);                  \
714  INTERCEPT_FUNCTION(getpwuid_r);                  \
715  INTERCEPT_FUNCTION(getgrnam_r);                  \
716  INTERCEPT_FUNCTION(getgrgid_r);
717#else
718#define INIT_GETPWNAM_R_AND_FRIENDS
719#endif
720
721
722#if SANITIZER_INTERCEPT_CLOCK_GETTIME
723INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
724  void *ctx;
725  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
726  int res = REAL(clock_getres)(clk_id, tp);
727  if (!res && tp) {
728    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
729  }
730  return res;
731}
732INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
733  void *ctx;
734  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
735  int res = REAL(clock_gettime)(clk_id, tp);
736  if (!res) {
737    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
738  }
739  return res;
740}
741INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
742  void *ctx;
743  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
744  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
745  return REAL(clock_settime)(clk_id, tp);
746}
747#define INIT_CLOCK_GETTIME                         \
748  INTERCEPT_FUNCTION(clock_getres);                \
749  INTERCEPT_FUNCTION(clock_gettime);               \
750  INTERCEPT_FUNCTION(clock_settime);
751#else
752#define INIT_CLOCK_GETTIME
753#endif
754
755
756#if SANITIZER_INTERCEPT_GETITIMER
757INTERCEPTOR(int, getitimer, int which, void *curr_value) {
758  void *ctx;
759  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
760  int res = REAL(getitimer)(which, curr_value);
761  if (!res && curr_value) {
762    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
763  }
764  return res;
765}
766INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
767  void *ctx;
768  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
769  if (new_value)
770    COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
771  int res = REAL(setitimer)(which, new_value, old_value);
772  if (!res && old_value) {
773    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
774  }
775  return res;
776}
777#define INIT_GETITIMER                             \
778  INTERCEPT_FUNCTION(getitimer);                   \
779  INTERCEPT_FUNCTION(setitimer);
780#else
781#define INIT_GETITIMER
782#endif
783
784#if SANITIZER_INTERCEPT_GLOB
785static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
786  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
787  // +1 for NULL pointer at the end.
788  if (pglob->gl_pathv)
789    COMMON_INTERCEPTOR_WRITE_RANGE(
790        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
791  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
792    char *p = pglob->gl_pathv[i];
793    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
794  }
795}
796
797static THREADLOCAL __sanitizer_glob_t* pglob_copy;
798static THREADLOCAL void* glob_ctx;
799
800static void wrapped_gl_closedir(void *dir) {
801  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
802  pglob_copy->gl_closedir(dir);
803}
804
805static void *wrapped_gl_readdir(void *dir) {
806  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
807  return pglob_copy->gl_readdir(dir);
808}
809
810static void *wrapped_gl_opendir(const char *s) {
811  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
812  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
813  return pglob_copy->gl_opendir(s);
814}
815
816static int wrapped_gl_lstat(const char *s, void *st) {
817  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
818  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
819  return pglob_copy->gl_lstat(s, st);
820}
821
822static int wrapped_gl_stat(const char *s, void *st) {
823  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
824  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
825  return pglob_copy->gl_stat(s, st);
826}
827
828INTERCEPTOR(int, glob, const char *pattern, int flags,
829            int (*errfunc)(const char *epath, int eerrno),
830            __sanitizer_glob_t *pglob) {
831  void *ctx;
832  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
833  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
834                                  wrapped_gl_readdir, wrapped_gl_opendir,
835                                  wrapped_gl_lstat, wrapped_gl_stat};
836  if (flags & glob_altdirfunc) {
837    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
838    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
839    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
840    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
841    Swap(pglob->gl_stat, glob_copy.gl_stat);
842    pglob_copy = &glob_copy;
843    glob_ctx = ctx;
844  }
845  int res = REAL(glob)(pattern, flags, errfunc, pglob);
846  if (flags & glob_altdirfunc) {
847    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
848    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
849    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
850    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
851    Swap(pglob->gl_stat, glob_copy.gl_stat);
852  }
853  pglob_copy = 0;
854  glob_ctx = 0;
855  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
856  return res;
857}
858
859INTERCEPTOR(int, glob64, const char *pattern, int flags,
860            int (*errfunc)(const char *epath, int eerrno),
861            __sanitizer_glob_t *pglob) {
862  void *ctx;
863  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
864  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
865                                  wrapped_gl_readdir, wrapped_gl_opendir,
866                                  wrapped_gl_lstat, wrapped_gl_stat};
867  if (flags & glob_altdirfunc) {
868    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
869    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
870    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
871    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
872    Swap(pglob->gl_stat, glob_copy.gl_stat);
873    pglob_copy = &glob_copy;
874    glob_ctx = ctx;
875  }
876  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
877  if (flags & glob_altdirfunc) {
878    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
879    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
880    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
881    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
882    Swap(pglob->gl_stat, glob_copy.gl_stat);
883  }
884  pglob_copy = 0;
885  glob_ctx = 0;
886  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
887  return res;
888}
889#define INIT_GLOB           \
890  INTERCEPT_FUNCTION(glob); \
891  INTERCEPT_FUNCTION(glob64);
892#else  // SANITIZER_INTERCEPT_GLOB
893#define INIT_GLOB
894#endif  // SANITIZER_INTERCEPT_GLOB
895
896#if SANITIZER_INTERCEPT_WAIT
897// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
898// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
899// details.
900INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
901  void *ctx;
902  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
903  int res = REAL(wait)(status);
904  if (res != -1 && status)
905    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
906  return res;
907}
908INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
909  int options) {
910  void *ctx;
911  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
912  int res = REAL(waitid)(idtype, id, infop, options);
913  if (res != -1 && infop)
914    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
915  return res;
916}
917INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
918  void *ctx;
919  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
920  int res = REAL(waitpid)(pid, status, options);
921  if (res != -1 && status)
922    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
923  return res;
924}
925INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
926  void *ctx;
927  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
928  int res = REAL(wait3)(status, options, rusage);
929  if (res != -1) {
930    if (status)
931      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
932    if (rusage)
933      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
934  }
935  return res;
936}
937INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
938  void *ctx;
939  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
940  int res = REAL(wait4)(pid, status, options, rusage);
941  if (res != -1) {
942    if (status)
943      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
944    if (rusage)
945      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
946  }
947  return res;
948}
949#define INIT_WAIT                                \
950  INTERCEPT_FUNCTION(wait);                      \
951  INTERCEPT_FUNCTION(waitid);                    \
952  INTERCEPT_FUNCTION(waitpid);                   \
953  INTERCEPT_FUNCTION(wait3);                     \
954  INTERCEPT_FUNCTION(wait4);
955#else
956#define INIT_WAIT
957#endif
958
959#if SANITIZER_INTERCEPT_INET
960INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
961  void *ctx;
962  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
963  uptr sz = __sanitizer_in_addr_sz(af);
964  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
965  // FIXME: figure out read size based on the address family.
966  char *res = REAL(inet_ntop)(af, src, dst, size);
967  if (res)
968    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
969  return res;
970}
971INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
972  void *ctx;
973  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
974  // FIXME: figure out read size based on the address family.
975  int res = REAL(inet_pton)(af, src, dst);
976  if (res == 1) {
977    uptr sz = __sanitizer_in_addr_sz(af);
978    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
979  }
980  return res;
981}
982#define INIT_INET                                \
983  INTERCEPT_FUNCTION(inet_ntop);                 \
984  INTERCEPT_FUNCTION(inet_pton);
985#else
986#define INIT_INET
987#endif
988
989#if SANITIZER_INTERCEPT_INET
990INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
991  void *ctx;
992  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
993  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
994  int res = REAL(inet_aton)(cp, dst);
995  if (res != 0) {
996    uptr sz = __sanitizer_in_addr_sz(af_inet);
997    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
998  }
999  return res;
1000}
1001#define INIT_INET_ATON INTERCEPT_FUNCTION(inet_aton);
1002#else
1003#define INIT_INET_ATON
1004#endif
1005
1006#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
1007INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
1008  void *ctx;
1009  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
1010  int res = REAL(pthread_getschedparam)(thread, policy, param);
1011  if (res == 0) {
1012    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
1013    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
1014  }
1015  return res;
1016}
1017#define INIT_PTHREAD_GETSCHEDPARAM INTERCEPT_FUNCTION(pthread_getschedparam);
1018#else
1019#define INIT_PTHREAD_GETSCHEDPARAM
1020#endif
1021
1022#if SANITIZER_INTERCEPT_GETADDRINFO
1023INTERCEPTOR(int, getaddrinfo, char *node, char *service,
1024            struct __sanitizer_addrinfo *hints,
1025            struct __sanitizer_addrinfo **out) {
1026  void *ctx;
1027  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
1028  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
1029  if (service)
1030    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
1031  if (hints)
1032    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
1033  int res = REAL(getaddrinfo)(node, service, hints, out);
1034  if (res == 0 && out) {
1035    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
1036    struct __sanitizer_addrinfo *p = *out;
1037    while (p) {
1038      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
1039      if (p->ai_addr)
1040        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
1041      if (p->ai_canonname)
1042        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
1043                                       REAL(strlen)(p->ai_canonname) + 1);
1044      p = p->ai_next;
1045    }
1046  }
1047  return res;
1048}
1049#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
1050#else
1051#define INIT_GETADDRINFO
1052#endif
1053
1054#if SANITIZER_INTERCEPT_GETNAMEINFO
1055INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
1056            unsigned hostlen, char *serv, unsigned servlen, int flags) {
1057  void *ctx;
1058  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
1059                           serv, servlen, flags);
1060  // FIXME: consider adding READ_RANGE(sockaddr, salen)
1061  // There is padding in in_addr that may make this too noisy
1062  int res =
1063      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
1064  if (res == 0) {
1065    if (host && hostlen)
1066      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
1067    if (serv && servlen)
1068      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
1069  }
1070  return res;
1071}
1072#define INIT_GETNAMEINFO INTERCEPT_FUNCTION(getnameinfo);
1073#else
1074#define INIT_GETNAMEINFO
1075#endif
1076
1077#if SANITIZER_INTERCEPT_GETSOCKNAME
1078INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
1079  void *ctx;
1080  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
1081  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1082  int addrlen_in = *addrlen;
1083  int res = REAL(getsockname)(sock_fd, addr, addrlen);
1084  if (res == 0) {
1085    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
1086  }
1087  return res;
1088}
1089#define INIT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname);
1090#else
1091#define INIT_GETSOCKNAME
1092#endif
1093
1094#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1095static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
1096  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
1097  if (h->h_name)
1098    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
1099  char **p = h->h_aliases;
1100  while (*p) {
1101    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1102    ++p;
1103  }
1104  COMMON_INTERCEPTOR_WRITE_RANGE(
1105      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
1106  p = h->h_addr_list;
1107  while (*p) {
1108    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
1109    ++p;
1110  }
1111  COMMON_INTERCEPTOR_WRITE_RANGE(
1112      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
1113}
1114#endif
1115
1116#if SANITIZER_INTERCEPT_GETHOSTBYNAME
1117INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
1118  void *ctx;
1119  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
1120  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
1121  if (res) write_hostent(ctx, res);
1122  return res;
1123}
1124
1125INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
1126            int type) {
1127  void *ctx;
1128  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
1129  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1130  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
1131  if (res) write_hostent(ctx, res);
1132  return res;
1133}
1134
1135INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
1136  void *ctx;
1137  COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
1138  struct __sanitizer_hostent *res = REAL(gethostent)();
1139  if (res) write_hostent(ctx, res);
1140  return res;
1141}
1142
1143INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
1144  void *ctx;
1145  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
1146  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
1147  if (res) write_hostent(ctx, res);
1148  return res;
1149}
1150#define INIT_GETHOSTBYNAME           \
1151  INTERCEPT_FUNCTION(gethostent);    \
1152  INTERCEPT_FUNCTION(gethostbyaddr); \
1153  INTERCEPT_FUNCTION(gethostbyname); \
1154  INTERCEPT_FUNCTION(gethostbyname2);
1155#else
1156#define INIT_GETHOSTBYNAME
1157#endif
1158
1159#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1160INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
1161            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
1162  void *ctx;
1163  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
1164                           h_errnop);
1165  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
1166  if (res == 0) {
1167    if (result) {
1168      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1169      if (*result) write_hostent(ctx, *result);
1170    }
1171    if (h_errnop)
1172      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1173  }
1174  return res;
1175}
1176
1177INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
1178            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1179            __sanitizer_hostent **result, int *h_errnop) {
1180  void *ctx;
1181  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
1182                           buflen, result, h_errnop);
1183  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1184  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
1185                                  h_errnop);
1186  if (res == 0) {
1187    if (result) {
1188      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1189      if (*result) write_hostent(ctx, *result);
1190    }
1191    if (h_errnop)
1192      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1193  }
1194  return res;
1195}
1196
1197INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
1198            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
1199            int *h_errnop) {
1200  void *ctx;
1201  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
1202                           h_errnop);
1203  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
1204  if (res == 0) {
1205    if (result) {
1206      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1207      if (*result) write_hostent(ctx, *result);
1208    }
1209    if (h_errnop)
1210      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1211  }
1212  return res;
1213}
1214
1215INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
1216            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1217            __sanitizer_hostent **result, int *h_errnop) {
1218  void *ctx;
1219  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
1220                           result, h_errnop);
1221  int res =
1222      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
1223  if (res == 0) {
1224    if (result) {
1225      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1226      if (*result) write_hostent(ctx, *result);
1227    }
1228    if (h_errnop)
1229      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1230  }
1231  return res;
1232}
1233#define INIT_GETHOSTBYNAME_R           \
1234  INTERCEPT_FUNCTION(gethostent_r);    \
1235  INTERCEPT_FUNCTION(gethostbyaddr_r); \
1236  INTERCEPT_FUNCTION(gethostbyname_r); \
1237  INTERCEPT_FUNCTION(gethostbyname2_r);
1238#else
1239#define INIT_GETHOSTBYNAME_R
1240#endif
1241
1242#if SANITIZER_INTERCEPT_GETSOCKOPT
1243INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
1244            int *optlen) {
1245  void *ctx;
1246  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
1247                           optlen);
1248  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
1249  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
1250  if (res == 0)
1251    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
1252  return res;
1253}
1254#define INIT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt);
1255#else
1256#define INIT_GETSOCKOPT
1257#endif
1258
1259#if SANITIZER_INTERCEPT_ACCEPT
1260INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
1261  void *ctx;
1262  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
1263  unsigned addrlen0;
1264  if (addrlen) {
1265    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1266    addrlen0 = *addrlen;
1267  }
1268  int fd2 = REAL(accept)(fd, addr, addrlen);
1269  if (fd2 >= 0) {
1270    if (fd >= 0)
1271      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1272    if (addr && addrlen)
1273      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1274  }
1275  return fd2;
1276}
1277#define INIT_ACCEPT INTERCEPT_FUNCTION(accept);
1278#else
1279#define INIT_ACCEPT
1280#endif
1281
1282#if SANITIZER_INTERCEPT_ACCEPT4
1283INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
1284  void *ctx;
1285  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
1286  unsigned addrlen0;
1287  if (addrlen) {
1288    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1289    addrlen0 = *addrlen;
1290  }
1291  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1292  if (fd2 >= 0) {
1293    if (fd >= 0)
1294      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1295    if (addr && addrlen)
1296      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1297  }
1298  return fd2;
1299}
1300#define INIT_ACCEPT4 INTERCEPT_FUNCTION(accept4);
1301#else
1302#define INIT_ACCEPT4
1303#endif
1304
1305#if SANITIZER_INTERCEPT_MODF
1306INTERCEPTOR(double, modf, double x, double *iptr) {
1307  void *ctx;
1308  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
1309  double res = REAL(modf)(x, iptr);
1310  if (iptr) {
1311    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1312  }
1313  return res;
1314}
1315INTERCEPTOR(float, modff, float x, float *iptr) {
1316  void *ctx;
1317  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
1318  float res = REAL(modff)(x, iptr);
1319  if (iptr) {
1320    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1321  }
1322  return res;
1323}
1324INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
1325  void *ctx;
1326  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
1327  long double res = REAL(modfl)(x, iptr);
1328  if (iptr) {
1329    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1330  }
1331  return res;
1332}
1333#define INIT_MODF            \
1334  INTERCEPT_FUNCTION(modf);  \
1335  INTERCEPT_FUNCTION(modff); \
1336  INTERCEPT_FUNCTION(modfl);
1337#else
1338#define INIT_MODF
1339#endif
1340
1341#if SANITIZER_INTERCEPT_RECVMSG
1342static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
1343                         SSIZE_T maxlen) {
1344  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
1345  if (msg->msg_name)
1346    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name,
1347                                   REAL(strlen)((char *)msg->msg_name) + 1);
1348  if (msg->msg_iov)
1349    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
1350                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
1351  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
1352  if (msg->msg_control)
1353    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
1354}
1355
1356INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
1357            int flags) {
1358  void *ctx;
1359  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
1360  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
1361  if (res >= 0) {
1362    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1363    if (msg) write_msghdr(ctx, msg, res);
1364  }
1365  return res;
1366}
1367#define INIT_RECVMSG INTERCEPT_FUNCTION(recvmsg);
1368#else
1369#define INIT_RECVMSG
1370#endif
1371
1372#if SANITIZER_INTERCEPT_GETPEERNAME
1373INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
1374  void *ctx;
1375  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
1376  unsigned addr_sz;
1377  if (addrlen) addr_sz = *addrlen;
1378  int res = REAL(getpeername)(sockfd, addr, addrlen);
1379  if (!res && addr && addrlen)
1380    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
1381  return res;
1382}
1383#define INIT_GETPEERNAME INTERCEPT_FUNCTION(getpeername);
1384#else
1385#define INIT_GETPEERNAME
1386#endif
1387
1388#if SANITIZER_INTERCEPT_SYSINFO
1389INTERCEPTOR(int, sysinfo, void *info) {
1390  void *ctx;
1391  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
1392  int res = REAL(sysinfo)(info);
1393  if (!res && info)
1394    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
1395  return res;
1396}
1397#define INIT_SYSINFO INTERCEPT_FUNCTION(sysinfo);
1398#else
1399#define INIT_SYSINFO
1400#endif
1401
1402#if SANITIZER_INTERCEPT_READDIR
1403INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
1404  void *ctx;
1405  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
1406  __sanitizer_dirent *res = REAL(readdir)(dirp);
1407  if (res)
1408    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1409  return res;
1410}
1411
1412INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
1413            __sanitizer_dirent **result) {
1414  void *ctx;
1415  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
1416  int res = REAL(readdir_r)(dirp, entry, result);
1417  if (!res) {
1418    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1419    if (*result)
1420      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1421  }
1422  return res;
1423}
1424
1425#define INIT_READDIR           \
1426  INTERCEPT_FUNCTION(readdir); \
1427  INTERCEPT_FUNCTION(readdir_r);
1428#else
1429#define INIT_READDIR
1430#endif
1431
1432#if SANITIZER_INTERCEPT_READDIR64
1433INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
1434  void *ctx;
1435  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
1436  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
1437  if (res)
1438    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1439  return res;
1440}
1441
1442INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
1443            __sanitizer_dirent64 **result) {
1444  void *ctx;
1445  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
1446  int res = REAL(readdir64_r)(dirp, entry, result);
1447  if (!res) {
1448    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1449    if (*result)
1450      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1451  }
1452  return res;
1453}
1454#define INIT_READDIR64           \
1455  INTERCEPT_FUNCTION(readdir64); \
1456  INTERCEPT_FUNCTION(readdir64_r);
1457#else
1458#define INIT_READDIR64
1459#endif
1460
1461#if SANITIZER_INTERCEPT_PTRACE
1462INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
1463  void *ctx;
1464  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
1465
1466  if (data) {
1467    if (request == ptrace_setregs)
1468      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
1469    else if (request == ptrace_setfpregs)
1470      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1471    else if (request == ptrace_setfpxregs)
1472      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1473    else if (request == ptrace_setsiginfo)
1474      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
1475    else if (request == ptrace_setregset) {
1476      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1477      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
1478    }
1479  }
1480
1481  uptr res = REAL(ptrace)(request, pid, addr, data);
1482
1483  if (!res && data) {
1484    // Note that PEEK* requests assing different meaning to the return value.
1485    // This function does not handle them (nor does it need to).
1486    if (request == ptrace_getregs)
1487      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
1488    else if (request == ptrace_getfpregs)
1489      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1490    else if (request == ptrace_getfpxregs)
1491      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1492    else if (request == ptrace_getsiginfo)
1493      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
1494    else if (request == ptrace_getregset) {
1495      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1496      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
1497    }
1498  }
1499  return res;
1500}
1501
1502#define INIT_PTRACE           \
1503  INTERCEPT_FUNCTION(ptrace);
1504#else
1505#define INIT_PTRACE
1506#endif
1507
1508#if SANITIZER_INTERCEPT_SETLOCALE
1509INTERCEPTOR(char *, setlocale, int category, char *locale) {
1510  void *ctx;
1511  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
1512  if (locale)
1513    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
1514  char *res = REAL(setlocale)(category, locale);
1515  if (res)
1516    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1517  return res;
1518}
1519
1520#define INIT_SETLOCALE           \
1521  INTERCEPT_FUNCTION(setlocale);
1522#else
1523#define INIT_SETLOCALE
1524#endif
1525
1526#if SANITIZER_INTERCEPT_GETCWD
1527INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
1528  void *ctx;
1529  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
1530  char *res = REAL(getcwd)(buf, size);
1531  if (res)
1532    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1533  return res;
1534}
1535#define INIT_GETCWD           \
1536  INTERCEPT_FUNCTION(getcwd);
1537#else
1538#define INIT_GETCWD
1539#endif
1540
1541#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
1542INTERCEPTOR(char *, get_current_dir_name) {
1543  void *ctx;
1544  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name);
1545  char *res = REAL(get_current_dir_name)();
1546  if (res)
1547    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1548  return res;
1549}
1550
1551#define INIT_GET_CURRENT_DIR_NAME           \
1552  INTERCEPT_FUNCTION(get_current_dir_name);
1553#else
1554#define INIT_GET_CURRENT_DIR_NAME
1555#endif
1556
1557#if SANITIZER_INTERCEPT_STRTOIMAX
1558INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
1559  void *ctx;
1560  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
1561  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
1562  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1563  return res;
1564}
1565
1566INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
1567  void *ctx;
1568  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
1569  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
1570  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1571  return res;
1572}
1573
1574#define INIT_STRTOIMAX           \
1575  INTERCEPT_FUNCTION(strtoimax); \
1576  INTERCEPT_FUNCTION(strtoumax);
1577#else
1578#define INIT_STRTOIMAX
1579#endif
1580
1581#if SANITIZER_INTERCEPT_MBSTOWCS
1582INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
1583  void *ctx;
1584  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
1585  SIZE_T res = REAL(mbstowcs)(dest, src, len);
1586  if (res != (SIZE_T) - 1 && dest) {
1587    SIZE_T write_cnt = res + (res < len);
1588    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1589  }
1590  return res;
1591}
1592
1593INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
1594            void *ps) {
1595  void *ctx;
1596  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
1597  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1598  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1599  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
1600  if (res != (SIZE_T)(-1) && dest && src) {
1601    // This function, and several others, may or may not write the terminating
1602    // \0 character. They write it iff they clear *src.
1603    SIZE_T write_cnt = res + !*src;
1604    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1605  }
1606  return res;
1607}
1608
1609#define INIT_MBSTOWCS           \
1610  INTERCEPT_FUNCTION(mbstowcs); \
1611  INTERCEPT_FUNCTION(mbsrtowcs);
1612#else
1613#define INIT_MBSTOWCS
1614#endif
1615
1616#if SANITIZER_INTERCEPT_MBSNRTOWCS
1617INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
1618            SIZE_T len, void *ps) {
1619  void *ctx;
1620  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
1621  if (src) {
1622    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1623    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1624  }
1625  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1626  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
1627  if (res != (SIZE_T)(-1) && dest && src) {
1628    SIZE_T write_cnt = res + !*src;
1629    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1630  }
1631  return res;
1632}
1633
1634#define INIT_MBSNRTOWCS INTERCEPT_FUNCTION(mbsnrtowcs);
1635#else
1636#define INIT_MBSNRTOWCS
1637#endif
1638
1639#if SANITIZER_INTERCEPT_WCSTOMBS
1640INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
1641  void *ctx;
1642  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
1643  SIZE_T res = REAL(wcstombs)(dest, src, len);
1644  if (res != (SIZE_T) - 1 && dest) {
1645    SIZE_T write_cnt = res + (res < len);
1646    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1647  }
1648  return res;
1649}
1650
1651INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
1652            void *ps) {
1653  void *ctx;
1654  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
1655  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1656  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1657  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
1658  if (res != (SIZE_T) - 1 && dest && src) {
1659    SIZE_T write_cnt = res + !*src;
1660    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1661  }
1662  return res;
1663}
1664
1665#define INIT_WCSTOMBS           \
1666  INTERCEPT_FUNCTION(wcstombs); \
1667  INTERCEPT_FUNCTION(wcsrtombs);
1668#else
1669#define INIT_WCSTOMBS
1670#endif
1671
1672#if SANITIZER_INTERCEPT_WCSNRTOMBS
1673INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
1674            SIZE_T len, void *ps) {
1675  void *ctx;
1676  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
1677  if (src) {
1678    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1679    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1680  }
1681  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1682  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
1683  if (res != (SIZE_T) - 1 && dest && src) {
1684    SIZE_T write_cnt = res + !*src;
1685    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1686  }
1687  return res;
1688}
1689
1690#define INIT_WCSNRTOMBS INTERCEPT_FUNCTION(wcsnrtombs);
1691#else
1692#define INIT_WCSNRTOMBS
1693#endif
1694
1695
1696#if SANITIZER_INTERCEPT_TCGETATTR
1697INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
1698  void *ctx;
1699  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
1700  int res = REAL(tcgetattr)(fd, termios_p);
1701  if (!res && termios_p)
1702    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
1703  return res;
1704}
1705
1706#define INIT_TCGETATTR INTERCEPT_FUNCTION(tcgetattr);
1707#else
1708#define INIT_TCGETATTR
1709#endif
1710
1711
1712#if SANITIZER_INTERCEPT_REALPATH
1713INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
1714  void *ctx;
1715  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
1716  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1717
1718  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
1719  // version of a versioned symbol. For realpath(), this gives us something
1720  // (called __old_realpath) that does not handle NULL in the second argument.
1721  // Handle it as part of the interceptor.
1722  char *allocated_path = 0;
1723  if (!resolved_path)
1724    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
1725
1726  char *res = REAL(realpath)(path, resolved_path);
1727  if (allocated_path && !res)
1728    WRAP(free)(allocated_path);
1729  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1730  return res;
1731}
1732#define INIT_REALPATH INTERCEPT_FUNCTION(realpath);
1733#else
1734#define INIT_REALPATH
1735#endif
1736
1737#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
1738INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
1739  void *ctx;
1740  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
1741  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1742  char *res = REAL(canonicalize_file_name)(path);
1743  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1744  return res;
1745}
1746#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name);
1747#else
1748#define INIT_CANONICALIZE_FILE_NAME
1749#endif
1750
1751#if SANITIZER_INTERCEPT_CONFSTR
1752INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
1753  void *ctx;
1754  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
1755  SIZE_T res = REAL(confstr)(name, buf, len);
1756  if (buf && res)
1757    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
1758  return res;
1759}
1760#define INIT_CONFSTR INTERCEPT_FUNCTION(confstr);
1761#else
1762#define INIT_CONFSTR
1763#endif
1764
1765#define SANITIZER_COMMON_INTERCEPTORS_INIT \
1766  INIT_STRCMP;                             \
1767  INIT_STRNCMP;                            \
1768  INIT_STRCASECMP;                         \
1769  INIT_STRNCASECMP;                        \
1770  INIT_READ;                               \
1771  INIT_PREAD;                              \
1772  INIT_PREAD64;                            \
1773  INIT_READV;                              \
1774  INIT_PREADV;                             \
1775  INIT_PREADV64;                           \
1776  INIT_WRITE;                              \
1777  INIT_PWRITE;                             \
1778  INIT_PWRITE64;                           \
1779  INIT_WRITEV;                             \
1780  INIT_PWRITEV;                            \
1781  INIT_PWRITEV64;                          \
1782  INIT_PRCTL;                              \
1783  INIT_LOCALTIME_AND_FRIENDS;              \
1784  INIT_SCANF;                              \
1785  INIT_FREXP;                              \
1786  INIT_FREXPF_FREXPL;                      \
1787  INIT_GETPWNAM_AND_FRIENDS;               \
1788  INIT_GETPWNAM_R_AND_FRIENDS;             \
1789  INIT_CLOCK_GETTIME;                      \
1790  INIT_GETITIMER;                          \
1791  INIT_TIME;                               \
1792  INIT_GLOB;                               \
1793  INIT_WAIT;                               \
1794  INIT_INET;                               \
1795  INIT_PTHREAD_GETSCHEDPARAM;              \
1796  INIT_GETADDRINFO;                        \
1797  INIT_GETNAMEINFO;                        \
1798  INIT_GETSOCKNAME;                        \
1799  INIT_GETHOSTBYNAME;                      \
1800  INIT_GETHOSTBYNAME_R;                    \
1801  INIT_GETSOCKOPT;                         \
1802  INIT_ACCEPT;                             \
1803  INIT_ACCEPT4;                            \
1804  INIT_MODF;                               \
1805  INIT_RECVMSG;                            \
1806  INIT_GETPEERNAME;                        \
1807  INIT_IOCTL;                              \
1808  INIT_INET_ATON;                          \
1809  INIT_SYSINFO;                            \
1810  INIT_READDIR;                            \
1811  INIT_READDIR64;                          \
1812  INIT_PTRACE;                             \
1813  INIT_SETLOCALE;                          \
1814  INIT_GETCWD;                             \
1815  INIT_GET_CURRENT_DIR_NAME;               \
1816  INIT_STRTOIMAX;                          \
1817  INIT_MBSTOWCS;                           \
1818  INIT_MBSNRTOWCS;                         \
1819  INIT_WCSTOMBS;                           \
1820  INIT_WCSNRTOMBS;                         \
1821  INIT_TCGETATTR;                          \
1822  INIT_REALPATH;                           \
1823  INIT_CANONICALIZE_FILE_NAME;             \
1824  INIT_CONFSTR;
1825