sanitizer_common_interceptors.inc revision b2dc6137eaa16f45401a6905f5aff1e894ae0975
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) {
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  COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
770  int res = REAL(setitimer)(which, new_value, old_value);
771  if (!res && old_value) {
772    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
773  }
774  return res;
775}
776#define INIT_GETITIMER                             \
777  INTERCEPT_FUNCTION(getitimer);                   \
778  INTERCEPT_FUNCTION(setitimer);
779#else
780#define INIT_GETITIMER
781#endif
782
783#if SANITIZER_INTERCEPT_GLOB
784static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
785  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
786  // +1 for NULL pointer at the end.
787  if (pglob->gl_pathv)
788    COMMON_INTERCEPTOR_WRITE_RANGE(
789        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
790  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
791    char *p = pglob->gl_pathv[i];
792    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
793  }
794}
795
796static THREADLOCAL __sanitizer_glob_t* pglob_copy;
797static THREADLOCAL void* glob_ctx;
798
799static void wrapped_gl_closedir(void *dir) {
800  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
801  pglob_copy->gl_closedir(dir);
802}
803
804static void *wrapped_gl_readdir(void *dir) {
805  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
806  return pglob_copy->gl_readdir(dir);
807}
808
809static void *wrapped_gl_opendir(const char *s) {
810  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
811  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
812  return pglob_copy->gl_opendir(s);
813}
814
815static int wrapped_gl_lstat(const char *s, void *st) {
816  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
817  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
818  return pglob_copy->gl_lstat(s, st);
819}
820
821static int wrapped_gl_stat(const char *s, void *st) {
822  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
823  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
824  return pglob_copy->gl_stat(s, st);
825}
826
827INTERCEPTOR(int, glob, const char *pattern, int flags,
828            int (*errfunc)(const char *epath, int eerrno),
829            __sanitizer_glob_t *pglob) {
830  void *ctx;
831  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
832  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
833                                  wrapped_gl_readdir, wrapped_gl_opendir,
834                                  wrapped_gl_lstat, wrapped_gl_stat};
835  if (flags & glob_altdirfunc) {
836    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
837    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
838    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
839    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
840    Swap(pglob->gl_stat, glob_copy.gl_stat);
841    pglob_copy = &glob_copy;
842    glob_ctx = ctx;
843  }
844  int res = REAL(glob)(pattern, flags, errfunc, pglob);
845  if (flags & glob_altdirfunc) {
846    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
847    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
848    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
849    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
850    Swap(pglob->gl_stat, glob_copy.gl_stat);
851  }
852  pglob_copy = 0;
853  glob_ctx = 0;
854  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
855  return res;
856}
857
858INTERCEPTOR(int, glob64, const char *pattern, int flags,
859            int (*errfunc)(const char *epath, int eerrno),
860            __sanitizer_glob_t *pglob) {
861  void *ctx;
862  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
863  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
864                                  wrapped_gl_readdir, wrapped_gl_opendir,
865                                  wrapped_gl_lstat, wrapped_gl_stat};
866  if (flags & glob_altdirfunc) {
867    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
868    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
869    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
870    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
871    Swap(pglob->gl_stat, glob_copy.gl_stat);
872    pglob_copy = &glob_copy;
873    glob_ctx = ctx;
874  }
875  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
876  if (flags & glob_altdirfunc) {
877    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
878    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
879    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
880    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
881    Swap(pglob->gl_stat, glob_copy.gl_stat);
882  }
883  pglob_copy = 0;
884  glob_ctx = 0;
885  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
886  return res;
887}
888#define INIT_GLOB           \
889  INTERCEPT_FUNCTION(glob); \
890  INTERCEPT_FUNCTION(glob64);
891#else  // SANITIZER_INTERCEPT_GLOB
892#define INIT_GLOB
893#endif  // SANITIZER_INTERCEPT_GLOB
894
895#if SANITIZER_INTERCEPT_WAIT
896// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
897// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
898// details.
899INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
900  void *ctx;
901  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
902  int res = REAL(wait)(status);
903  if (res != -1 && status)
904    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
905  return res;
906}
907INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
908  int options) {
909  void *ctx;
910  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
911  int res = REAL(waitid)(idtype, id, infop, options);
912  if (res != -1 && infop)
913    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
914  return res;
915}
916INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
917  void *ctx;
918  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
919  int res = REAL(waitpid)(pid, status, options);
920  if (res != -1 && status)
921    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
922  return res;
923}
924INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
925  void *ctx;
926  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
927  int res = REAL(wait3)(status, options, rusage);
928  if (res != -1) {
929    if (status)
930      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
931    if (rusage)
932      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
933  }
934  return res;
935}
936INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
937  void *ctx;
938  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
939  int res = REAL(wait4)(pid, status, options, rusage);
940  if (res != -1) {
941    if (status)
942      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
943    if (rusage)
944      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
945  }
946  return res;
947}
948#define INIT_WAIT                                \
949  INTERCEPT_FUNCTION(wait);                      \
950  INTERCEPT_FUNCTION(waitid);                    \
951  INTERCEPT_FUNCTION(waitpid);                   \
952  INTERCEPT_FUNCTION(wait3);                     \
953  INTERCEPT_FUNCTION(wait4);
954#else
955#define INIT_WAIT
956#endif
957
958#if SANITIZER_INTERCEPT_INET
959INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
960  void *ctx;
961  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
962  uptr sz = __sanitizer_in_addr_sz(af);
963  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
964  // FIXME: figure out read size based on the address family.
965  char *res = REAL(inet_ntop)(af, src, dst, size);
966  if (res)
967    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
968  return res;
969}
970INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
971  void *ctx;
972  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
973  // FIXME: figure out read size based on the address family.
974  int res = REAL(inet_pton)(af, src, dst);
975  if (res == 1) {
976    uptr sz = __sanitizer_in_addr_sz(af);
977    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
978  }
979  return res;
980}
981#define INIT_INET                                \
982  INTERCEPT_FUNCTION(inet_ntop);                 \
983  INTERCEPT_FUNCTION(inet_pton);
984#else
985#define INIT_INET
986#endif
987
988#if SANITIZER_INTERCEPT_INET
989INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
990  void *ctx;
991  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
992  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
993  int res = REAL(inet_aton)(cp, dst);
994  if (res != 0) {
995    uptr sz = __sanitizer_in_addr_sz(af_inet);
996    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
997  }
998  return res;
999}
1000#define INIT_INET_ATON INTERCEPT_FUNCTION(inet_aton);
1001#else
1002#define INIT_INET_ATON
1003#endif
1004
1005#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
1006INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
1007  void *ctx;
1008  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
1009  int res = REAL(pthread_getschedparam)(thread, policy, param);
1010  if (res == 0) {
1011    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
1012    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
1013  }
1014  return res;
1015}
1016#define INIT_PTHREAD_GETSCHEDPARAM INTERCEPT_FUNCTION(pthread_getschedparam);
1017#else
1018#define INIT_PTHREAD_GETSCHEDPARAM
1019#endif
1020
1021#if SANITIZER_INTERCEPT_GETADDRINFO
1022INTERCEPTOR(int, getaddrinfo, char *node, char *service,
1023            struct __sanitizer_addrinfo *hints,
1024            struct __sanitizer_addrinfo **out) {
1025  void *ctx;
1026  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
1027  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
1028  if (service)
1029    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
1030  if (hints)
1031    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
1032  int res = REAL(getaddrinfo)(node, service, hints, out);
1033  if (res == 0 && out) {
1034    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
1035    struct __sanitizer_addrinfo *p = *out;
1036    while (p) {
1037      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
1038      if (p->ai_addr)
1039        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
1040      if (p->ai_canonname)
1041        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
1042                                       REAL(strlen)(p->ai_canonname) + 1);
1043      p = p->ai_next;
1044    }
1045  }
1046  return res;
1047}
1048#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
1049#else
1050#define INIT_GETADDRINFO
1051#endif
1052
1053#if SANITIZER_INTERCEPT_GETNAMEINFO
1054INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
1055            unsigned hostlen, char *serv, unsigned servlen, int flags) {
1056  void *ctx;
1057  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
1058                           serv, servlen, flags);
1059  // FIXME: consider adding READ_RANGE(sockaddr, salen)
1060  // There is padding in in_addr that may make this too noisy
1061  int res =
1062      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
1063  if (res == 0) {
1064    if (host && hostlen)
1065      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
1066    if (serv && servlen)
1067      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
1068  }
1069  return res;
1070}
1071#define INIT_GETNAMEINFO INTERCEPT_FUNCTION(getnameinfo);
1072#else
1073#define INIT_GETNAMEINFO
1074#endif
1075
1076#if SANITIZER_INTERCEPT_GETSOCKNAME
1077INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
1078  void *ctx;
1079  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
1080  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1081  int addrlen_in = *addrlen;
1082  int res = REAL(getsockname)(sock_fd, addr, addrlen);
1083  if (res == 0) {
1084    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
1085  }
1086  return res;
1087}
1088#define INIT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname);
1089#else
1090#define INIT_GETSOCKNAME
1091#endif
1092
1093#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1094static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
1095  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
1096  if (h->h_name)
1097    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
1098  char **p = h->h_aliases;
1099  while (*p) {
1100    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1101    ++p;
1102  }
1103  COMMON_INTERCEPTOR_WRITE_RANGE(
1104      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
1105  p = h->h_addr_list;
1106  while (*p) {
1107    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
1108    ++p;
1109  }
1110  COMMON_INTERCEPTOR_WRITE_RANGE(
1111      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
1112}
1113#endif
1114
1115#if SANITIZER_INTERCEPT_GETHOSTBYNAME
1116INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
1117  void *ctx;
1118  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
1119  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
1120  if (res) write_hostent(ctx, res);
1121  return res;
1122}
1123
1124INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
1125            int type) {
1126  void *ctx;
1127  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
1128  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1129  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
1130  if (res) write_hostent(ctx, res);
1131  return res;
1132}
1133
1134INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
1135  void *ctx;
1136  COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
1137  struct __sanitizer_hostent *res = REAL(gethostent)();
1138  if (res) write_hostent(ctx, res);
1139  return res;
1140}
1141
1142INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
1143  void *ctx;
1144  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
1145  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
1146  if (res) write_hostent(ctx, res);
1147  return res;
1148}
1149#define INIT_GETHOSTBYNAME           \
1150  INTERCEPT_FUNCTION(gethostent);    \
1151  INTERCEPT_FUNCTION(gethostbyaddr); \
1152  INTERCEPT_FUNCTION(gethostbyname); \
1153  INTERCEPT_FUNCTION(gethostbyname2);
1154#else
1155#define INIT_GETHOSTBYNAME
1156#endif
1157
1158#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1159INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
1160            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
1161  void *ctx;
1162  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
1163                           h_errnop);
1164  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
1165  if (res == 0) {
1166    if (result) {
1167      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1168      if (*result) write_hostent(ctx, *result);
1169    }
1170    if (h_errnop)
1171      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1172  }
1173  return res;
1174}
1175
1176INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
1177            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1178            __sanitizer_hostent **result, int *h_errnop) {
1179  void *ctx;
1180  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
1181                           buflen, result, h_errnop);
1182  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1183  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
1184                                  h_errnop);
1185  if (res == 0) {
1186    if (result) {
1187      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1188      if (*result) write_hostent(ctx, *result);
1189    }
1190    if (h_errnop)
1191      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1192  }
1193  return res;
1194}
1195
1196INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
1197            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
1198            int *h_errnop) {
1199  void *ctx;
1200  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
1201                           h_errnop);
1202  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
1203  if (res == 0) {
1204    if (result) {
1205      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1206      if (*result) write_hostent(ctx, *result);
1207    }
1208    if (h_errnop)
1209      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1210  }
1211  return res;
1212}
1213
1214INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
1215            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1216            __sanitizer_hostent **result, int *h_errnop) {
1217  void *ctx;
1218  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
1219                           result, h_errnop);
1220  int res =
1221      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
1222  if (res == 0) {
1223    if (result) {
1224      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1225      if (*result) write_hostent(ctx, *result);
1226    }
1227    if (h_errnop)
1228      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1229  }
1230  return res;
1231}
1232#define INIT_GETHOSTBYNAME_R           \
1233  INTERCEPT_FUNCTION(gethostent_r);    \
1234  INTERCEPT_FUNCTION(gethostbyaddr_r); \
1235  INTERCEPT_FUNCTION(gethostbyname_r); \
1236  INTERCEPT_FUNCTION(gethostbyname2_r);
1237#else
1238#define INIT_GETHOSTBYNAME_R
1239#endif
1240
1241#if SANITIZER_INTERCEPT_GETSOCKOPT
1242INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
1243            int *optlen) {
1244  void *ctx;
1245  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
1246                           optlen);
1247  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
1248  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
1249  if (res == 0)
1250    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
1251  return res;
1252}
1253#define INIT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt);
1254#else
1255#define INIT_GETSOCKOPT
1256#endif
1257
1258#if SANITIZER_INTERCEPT_ACCEPT
1259INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
1260  void *ctx;
1261  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
1262  unsigned addrlen0;
1263  if (addrlen) {
1264    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1265    addrlen0 = *addrlen;
1266  }
1267  int fd2 = REAL(accept)(fd, addr, addrlen);
1268  if (fd2 >= 0) {
1269    if (fd >= 0)
1270      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1271    if (addr && addrlen)
1272      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1273  }
1274  return fd2;
1275}
1276#define INIT_ACCEPT INTERCEPT_FUNCTION(accept);
1277#else
1278#define INIT_ACCEPT
1279#endif
1280
1281#if SANITIZER_INTERCEPT_ACCEPT4
1282INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
1283  void *ctx;
1284  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
1285  unsigned addrlen0;
1286  if (addrlen) {
1287    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1288    addrlen0 = *addrlen;
1289  }
1290  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1291  if (fd2 >= 0) {
1292    if (fd >= 0)
1293      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1294    if (addr && addrlen)
1295      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1296  }
1297  return fd2;
1298}
1299#define INIT_ACCEPT4 INTERCEPT_FUNCTION(accept4);
1300#else
1301#define INIT_ACCEPT4
1302#endif
1303
1304#if SANITIZER_INTERCEPT_MODF
1305INTERCEPTOR(double, modf, double x, double *iptr) {
1306  void *ctx;
1307  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
1308  double res = REAL(modf)(x, iptr);
1309  if (iptr) {
1310    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1311  }
1312  return res;
1313}
1314INTERCEPTOR(float, modff, float x, float *iptr) {
1315  void *ctx;
1316  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
1317  float res = REAL(modff)(x, iptr);
1318  if (iptr) {
1319    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1320  }
1321  return res;
1322}
1323INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
1324  void *ctx;
1325  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
1326  long double res = REAL(modfl)(x, iptr);
1327  if (iptr) {
1328    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1329  }
1330  return res;
1331}
1332#define INIT_MODF            \
1333  INTERCEPT_FUNCTION(modf);  \
1334  INTERCEPT_FUNCTION(modff); \
1335  INTERCEPT_FUNCTION(modfl);
1336#else
1337#define INIT_MODF
1338#endif
1339
1340#if SANITIZER_INTERCEPT_RECVMSG
1341static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
1342                         SSIZE_T maxlen) {
1343  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
1344  if (msg->msg_name)
1345    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name,
1346                                   REAL(strlen)((char *)msg->msg_name) + 1);
1347  if (msg->msg_iov)
1348    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
1349                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
1350  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
1351  if (msg->msg_control)
1352    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
1353}
1354
1355INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
1356            int flags) {
1357  void *ctx;
1358  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
1359  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
1360  if (res >= 0) {
1361    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1362    if (msg) write_msghdr(ctx, msg, res);
1363  }
1364  return res;
1365}
1366#define INIT_RECVMSG INTERCEPT_FUNCTION(recvmsg);
1367#else
1368#define INIT_RECVMSG
1369#endif
1370
1371#if SANITIZER_INTERCEPT_GETPEERNAME
1372INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
1373  void *ctx;
1374  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
1375  unsigned addr_sz;
1376  if (addrlen) addr_sz = *addrlen;
1377  int res = REAL(getpeername)(sockfd, addr, addrlen);
1378  if (!res && addr && addrlen)
1379    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
1380  return res;
1381}
1382#define INIT_GETPEERNAME INTERCEPT_FUNCTION(getpeername);
1383#else
1384#define INIT_GETPEERNAME
1385#endif
1386
1387#if SANITIZER_INTERCEPT_SYSINFO
1388INTERCEPTOR(int, sysinfo, void *info) {
1389  void *ctx;
1390  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
1391  int res = REAL(sysinfo)(info);
1392  if (!res && info)
1393    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
1394  return res;
1395}
1396#define INIT_SYSINFO INTERCEPT_FUNCTION(sysinfo);
1397#else
1398#define INIT_SYSINFO
1399#endif
1400
1401#if SANITIZER_INTERCEPT_READDIR
1402INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
1403  void *ctx;
1404  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
1405  __sanitizer_dirent *res = REAL(readdir)(dirp);
1406  if (res)
1407    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1408  return res;
1409}
1410
1411INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
1412            __sanitizer_dirent **result) {
1413  void *ctx;
1414  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
1415  int res = REAL(readdir_r)(dirp, entry, result);
1416  if (!res) {
1417    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1418    if (*result)
1419      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1420  }
1421  return res;
1422}
1423
1424#define INIT_READDIR           \
1425  INTERCEPT_FUNCTION(readdir); \
1426  INTERCEPT_FUNCTION(readdir_r);
1427#else
1428#define INIT_READDIR
1429#endif
1430
1431#if SANITIZER_INTERCEPT_READDIR64
1432INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
1433  void *ctx;
1434  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
1435  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
1436  if (res)
1437    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1438  return res;
1439}
1440
1441INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
1442            __sanitizer_dirent64 **result) {
1443  void *ctx;
1444  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
1445  int res = REAL(readdir64_r)(dirp, entry, result);
1446  if (!res) {
1447    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1448    if (*result)
1449      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1450  }
1451  return res;
1452}
1453#define INIT_READDIR64           \
1454  INTERCEPT_FUNCTION(readdir64); \
1455  INTERCEPT_FUNCTION(readdir64_r);
1456#else
1457#define INIT_READDIR64
1458#endif
1459
1460#if SANITIZER_INTERCEPT_PTRACE
1461INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
1462  void *ctx;
1463  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
1464
1465  if (data) {
1466    if (request == ptrace_setregs)
1467      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
1468    else if (request == ptrace_setfpregs)
1469      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1470    else if (request == ptrace_setfpxregs)
1471      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1472    else if (request == ptrace_setsiginfo)
1473      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
1474    else if (request == ptrace_setregset) {
1475      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1476      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
1477    }
1478  }
1479
1480  uptr res = REAL(ptrace)(request, pid, addr, data);
1481
1482  if (!res && data) {
1483    // Note that PEEK* requests assing different meaning to the return value.
1484    // This function does not handle them (nor does it need to).
1485    if (request == ptrace_getregs)
1486      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
1487    else if (request == ptrace_getfpregs)
1488      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1489    else if (request == ptrace_getfpxregs)
1490      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1491    else if (request == ptrace_getsiginfo)
1492      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
1493    else if (request == ptrace_getregset) {
1494      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1495      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
1496    }
1497  }
1498  return res;
1499}
1500
1501#define INIT_PTRACE           \
1502  INTERCEPT_FUNCTION(ptrace);
1503#else
1504#define INIT_PTRACE
1505#endif
1506
1507#if SANITIZER_INTERCEPT_SETLOCALE
1508INTERCEPTOR(char *, setlocale, int category, char *locale) {
1509  void *ctx;
1510  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
1511  if (locale)
1512    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
1513  char *res = REAL(setlocale)(category, locale);
1514  if (res)
1515    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1516  return res;
1517}
1518
1519#define INIT_SETLOCALE           \
1520  INTERCEPT_FUNCTION(setlocale);
1521#else
1522#define INIT_SETLOCALE
1523#endif
1524
1525#if SANITIZER_INTERCEPT_GETCWD
1526INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
1527  void *ctx;
1528  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
1529  char *res = REAL(getcwd)(buf, size);
1530  if (res)
1531    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1532  return res;
1533}
1534#define INIT_GETCWD           \
1535  INTERCEPT_FUNCTION(getcwd);
1536#else
1537#define INIT_GETCWD
1538#endif
1539
1540#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
1541INTERCEPTOR(char *, get_current_dir_name) {
1542  void *ctx;
1543  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name);
1544  char *res = REAL(get_current_dir_name)();
1545  if (res)
1546    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1547  return res;
1548}
1549
1550#define INIT_GET_CURRENT_DIR_NAME           \
1551  INTERCEPT_FUNCTION(get_current_dir_name);
1552#else
1553#define INIT_GET_CURRENT_DIR_NAME
1554#endif
1555
1556#if SANITIZER_INTERCEPT_STRTOIMAX
1557INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
1558  void *ctx;
1559  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
1560  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
1561  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1562  return res;
1563}
1564
1565INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
1566  void *ctx;
1567  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
1568  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
1569  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1570  return res;
1571}
1572
1573#define INIT_STRTOIMAX           \
1574  INTERCEPT_FUNCTION(strtoimax); \
1575  INTERCEPT_FUNCTION(strtoumax);
1576#else
1577#define INIT_STRTOIMAX
1578#endif
1579
1580#if SANITIZER_INTERCEPT_MBSTOWCS
1581INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
1582  void *ctx;
1583  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
1584  SIZE_T res = REAL(mbstowcs)(dest, src, len);
1585  if (res != (SIZE_T) - 1 && dest) {
1586    SIZE_T write_cnt = res + (res < len);
1587    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1588  }
1589  return res;
1590}
1591
1592INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
1593            void *ps) {
1594  void *ctx;
1595  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
1596  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1597  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1598  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
1599  if (res != (SIZE_T)(-1) && dest && src) {
1600    // This function, and several others, may or may not write the terminating
1601    // \0 character. They write it iff they clear *src.
1602    SIZE_T write_cnt = res + !*src;
1603    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1604  }
1605  return res;
1606}
1607
1608#define INIT_MBSTOWCS           \
1609  INTERCEPT_FUNCTION(mbstowcs); \
1610  INTERCEPT_FUNCTION(mbsrtowcs);
1611#else
1612#define INIT_MBSTOWCS
1613#endif
1614
1615#if SANITIZER_INTERCEPT_MBSNRTOWCS
1616INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
1617            SIZE_T len, void *ps) {
1618  void *ctx;
1619  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
1620  if (src) {
1621    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1622    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1623  }
1624  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1625  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
1626  if (res != (SIZE_T)(-1) && dest && src) {
1627    SIZE_T write_cnt = res + !*src;
1628    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1629  }
1630  return res;
1631}
1632
1633#define INIT_MBSNRTOWCS INTERCEPT_FUNCTION(mbsnrtowcs);
1634#else
1635#define INIT_MBSNRTOWCS
1636#endif
1637
1638#if SANITIZER_INTERCEPT_WCSTOMBS
1639INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
1640  void *ctx;
1641  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
1642  SIZE_T res = REAL(wcstombs)(dest, src, len);
1643  if (res != (SIZE_T) - 1 && dest) {
1644    SIZE_T write_cnt = res + (res < len);
1645    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1646  }
1647  return res;
1648}
1649
1650INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
1651            void *ps) {
1652  void *ctx;
1653  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
1654  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1655  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1656  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
1657  if (res != (SIZE_T) - 1 && dest && src) {
1658    SIZE_T write_cnt = res + !*src;
1659    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1660  }
1661  return res;
1662}
1663
1664#define INIT_WCSTOMBS           \
1665  INTERCEPT_FUNCTION(wcstombs); \
1666  INTERCEPT_FUNCTION(wcsrtombs);
1667#else
1668#define INIT_WCSTOMBS
1669#endif
1670
1671#if SANITIZER_INTERCEPT_WCSNRTOMBS
1672INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
1673            SIZE_T len, void *ps) {
1674  void *ctx;
1675  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
1676  if (src) {
1677    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1678    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1679  }
1680  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
1681  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
1682  if (res != (SIZE_T) - 1 && dest && src) {
1683    SIZE_T write_cnt = res + !*src;
1684    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1685  }
1686  return res;
1687}
1688
1689#define INIT_WCSNRTOMBS INTERCEPT_FUNCTION(wcsnrtombs);
1690#else
1691#define INIT_WCSNRTOMBS
1692#endif
1693
1694
1695#if SANITIZER_INTERCEPT_TCGETATTR
1696INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
1697  void *ctx;
1698  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
1699  int res = REAL(tcgetattr)(fd, termios_p);
1700  if (!res && termios_p)
1701    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
1702  return res;
1703}
1704
1705#define INIT_TCGETATTR INTERCEPT_FUNCTION(tcgetattr);
1706#else
1707#define INIT_TCGETATTR
1708#endif
1709
1710
1711#if SANITIZER_INTERCEPT_REALPATH
1712INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
1713  void *ctx;
1714  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
1715  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1716
1717  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
1718  // version of a versioned symbol. For realpath(), this gives us something
1719  // (called __old_realpath) that does not handle NULL in the second argument.
1720  // Handle it as part of the interceptor.
1721  char *allocated_path = 0;
1722  if (!resolved_path)
1723    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
1724
1725  char *res = REAL(realpath)(path, resolved_path);
1726  if (allocated_path && !res)
1727    WRAP(free)(allocated_path);
1728  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1729  return res;
1730}
1731#define INIT_REALPATH INTERCEPT_FUNCTION(realpath);
1732#else
1733#define INIT_REALPATH
1734#endif
1735
1736#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
1737INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
1738  void *ctx;
1739  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
1740  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1741  char *res = REAL(canonicalize_file_name)(path);
1742  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1743  return res;
1744}
1745#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name);
1746#else
1747#define INIT_CANONICALIZE_FILE_NAME
1748#endif
1749
1750#if SANITIZER_INTERCEPT_CONFSTR
1751INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
1752  void *ctx;
1753  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
1754  SIZE_T res = REAL(confstr)(name, buf, len);
1755  if (buf && res)
1756    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
1757  return res;
1758}
1759#define INIT_CONFSTR INTERCEPT_FUNCTION(confstr);
1760#else
1761#define INIT_CONFSTR
1762#endif
1763
1764#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
1765INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
1766  void *ctx;
1767  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
1768  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
1769  if (mask && !res)
1770    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
1771  return res;
1772}
1773#define INIT_SCHED_GETAFFINITY INTERCEPT_FUNCTION(sched_getaffinity);
1774#else
1775#define INIT_SCHED_GETAFFINITY
1776#endif
1777
1778#define SANITIZER_COMMON_INTERCEPTORS_INIT \
1779  INIT_STRCMP;                             \
1780  INIT_STRNCMP;                            \
1781  INIT_STRCASECMP;                         \
1782  INIT_STRNCASECMP;                        \
1783  INIT_READ;                               \
1784  INIT_PREAD;                              \
1785  INIT_PREAD64;                            \
1786  INIT_READV;                              \
1787  INIT_PREADV;                             \
1788  INIT_PREADV64;                           \
1789  INIT_WRITE;                              \
1790  INIT_PWRITE;                             \
1791  INIT_PWRITE64;                           \
1792  INIT_WRITEV;                             \
1793  INIT_PWRITEV;                            \
1794  INIT_PWRITEV64;                          \
1795  INIT_PRCTL;                              \
1796  INIT_LOCALTIME_AND_FRIENDS;              \
1797  INIT_SCANF;                              \
1798  INIT_FREXP;                              \
1799  INIT_FREXPF_FREXPL;                      \
1800  INIT_GETPWNAM_AND_FRIENDS;               \
1801  INIT_GETPWNAM_R_AND_FRIENDS;             \
1802  INIT_CLOCK_GETTIME;                      \
1803  INIT_GETITIMER;                          \
1804  INIT_TIME;                               \
1805  INIT_GLOB;                               \
1806  INIT_WAIT;                               \
1807  INIT_INET;                               \
1808  INIT_PTHREAD_GETSCHEDPARAM;              \
1809  INIT_GETADDRINFO;                        \
1810  INIT_GETNAMEINFO;                        \
1811  INIT_GETSOCKNAME;                        \
1812  INIT_GETHOSTBYNAME;                      \
1813  INIT_GETHOSTBYNAME_R;                    \
1814  INIT_GETSOCKOPT;                         \
1815  INIT_ACCEPT;                             \
1816  INIT_ACCEPT4;                            \
1817  INIT_MODF;                               \
1818  INIT_RECVMSG;                            \
1819  INIT_GETPEERNAME;                        \
1820  INIT_IOCTL;                              \
1821  INIT_INET_ATON;                          \
1822  INIT_SYSINFO;                            \
1823  INIT_READDIR;                            \
1824  INIT_READDIR64;                          \
1825  INIT_PTRACE;                             \
1826  INIT_SETLOCALE;                          \
1827  INIT_GETCWD;                             \
1828  INIT_GET_CURRENT_DIR_NAME;               \
1829  INIT_STRTOIMAX;                          \
1830  INIT_MBSTOWCS;                           \
1831  INIT_MBSNRTOWCS;                         \
1832  INIT_WCSTOMBS;                           \
1833  INIT_WCSNRTOMBS;                         \
1834  INIT_TCGETATTR;                          \
1835  INIT_REALPATH;                           \
1836  INIT_CANONICALIZE_FILE_NAME;             \
1837  INIT_CONFSTR;                            \
1838  INIT_SCHED_GETAFFINITY;
1839