sanitizer_common_interceptors.inc revision e43d2108ec7622afb34b8281005a12fcdb26d6fa
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_STRCASECMP
32static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
33  int c1_low = ToLower(c1);
34  int c2_low = ToLower(c2);
35  return c1_low - c2_low;
36}
37
38INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
39  void *ctx;
40  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
41  unsigned char c1 = 0, c2 = 0;
42  uptr i;
43  for (i = 0; ; i++) {
44    c1 = (unsigned char)s1[i];
45    c2 = (unsigned char)s2[i];
46    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0')
47      break;
48  }
49  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
50  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
51  return CharCaseCmp(c1, c2);
52}
53
54INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
55  void *ctx;
56  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
57  unsigned char c1 = 0, c2 = 0;
58  uptr i;
59  for (i = 0; i < n; i++) {
60    c1 = (unsigned char)s1[i];
61    c2 = (unsigned char)s2[i];
62    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0')
63      break;
64  }
65  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
66  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
67  return CharCaseCmp(c1, c2);
68}
69
70#define INIT_STRCASECMP INTERCEPT_FUNCTION(strcasecmp)
71#define INIT_STRNCASECMP INTERCEPT_FUNCTION(strncasecmp)
72#else
73#define INIT_STRCASECMP
74#define INIT_STRNCASECMP
75#endif
76
77#if SANITIZER_INTERCEPT_FREXP
78INTERCEPTOR(double, frexp, double x, int *exp) {
79  void *ctx;
80  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
81  double res = REAL(frexp)(x, exp);
82  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
83  return res;
84}
85
86#define INIT_FREXP INTERCEPT_FUNCTION(frexp);
87#else
88#define INIT_FREXP
89#endif // SANITIZER_INTERCEPT_FREXP
90
91#if SANITIZER_INTERCEPT_FREXPF_FREXPL
92INTERCEPTOR(float, frexpf, float x, int *exp) {
93  void *ctx;
94  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
95  float res = REAL(frexpf)(x, exp);
96  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
97  return res;
98}
99
100INTERCEPTOR(long double, frexpl, long double x, int *exp) {
101  void *ctx;
102  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
103  long double res = REAL(frexpl)(x, exp);
104  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
105  return res;
106}
107
108#define INIT_FREXPF_FREXPL                       \
109  INTERCEPT_FUNCTION(frexpf);                    \
110  INTERCEPT_FUNCTION(frexpl)
111#else
112#define INIT_FREXPF_FREXPL
113#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
114
115#if SI_NOT_WINDOWS
116static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
117                        SIZE_T iovlen, SIZE_T maxlen) {
118  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
119    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
120    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
121    maxlen -= sz;
122  }
123}
124
125static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
126                       SIZE_T iovlen, SIZE_T maxlen) {
127  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
128  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
129    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
130    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
131    maxlen -= sz;
132  }
133}
134#endif
135
136#if SANITIZER_INTERCEPT_READ
137INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
138  void *ctx;
139  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
140  SSIZE_T res = REAL(read)(fd, ptr, count);
141  if (res > 0)
142    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
143  if (res >= 0 && fd >= 0)
144    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
145  return res;
146}
147#define INIT_READ INTERCEPT_FUNCTION(read)
148#else
149#define INIT_READ
150#endif
151
152#if SANITIZER_INTERCEPT_PREAD
153INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
154  void *ctx;
155  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
156  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
157  if (res > 0)
158    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
159  if (res >= 0 && fd >= 0)
160    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
161  return res;
162}
163#define INIT_PREAD INTERCEPT_FUNCTION(pread)
164#else
165#define INIT_PREAD
166#endif
167
168#if SANITIZER_INTERCEPT_PREAD64
169INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
170  void *ctx;
171  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
172  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
173  if (res > 0)
174    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
175  if (res >= 0 && fd >= 0)
176    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
177  return res;
178}
179#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
180#else
181#define INIT_PREAD64
182#endif
183
184#if SANITIZER_INTERCEPT_READV
185INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
186                        int iovcnt) {
187  void *ctx;
188  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
189  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
190  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
191  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
192  return res;
193}
194#define INIT_READV INTERCEPT_FUNCTION(readv)
195#else
196#define INIT_READV
197#endif
198
199#if SANITIZER_INTERCEPT_PREADV
200INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
201            OFF_T offset) {
202  void *ctx;
203  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
204  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
205  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
206  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
207  return res;
208}
209#define INIT_PREADV INTERCEPT_FUNCTION(preadv)
210#else
211#define INIT_PREADV
212#endif
213
214#if SANITIZER_INTERCEPT_PREADV64
215INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
216            OFF64_T offset) {
217  void *ctx;
218  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
219  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
220  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
221  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
222  return res;
223}
224#define INIT_PREADV64 INTERCEPT_FUNCTION(preadv64)
225#else
226#define INIT_PREADV64
227#endif
228
229#if SANITIZER_INTERCEPT_WRITE
230INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
231  void *ctx;
232  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
233  if (fd >= 0)
234    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
235  SSIZE_T res = REAL(write)(fd, ptr, count);
236  // FIXME: this check should be _before_ the call to REAL(write), not after
237  if (res > 0)
238    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
239  return res;
240}
241#define INIT_WRITE INTERCEPT_FUNCTION(write)
242#else
243#define INIT_WRITE
244#endif
245
246#if SANITIZER_INTERCEPT_PWRITE
247INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
248  void *ctx;
249  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
250  if (fd >= 0)
251    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
252  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
253  if (res > 0)
254    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
255  return res;
256}
257#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
258#else
259#define INIT_PWRITE
260#endif
261
262#if SANITIZER_INTERCEPT_PWRITE64
263INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
264            OFF64_T offset) {
265  void *ctx;
266  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
267  if (fd >= 0)
268    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
269  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
270  if (res > 0)
271    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
272  return res;
273}
274#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
275#else
276#define INIT_PWRITE64
277#endif
278
279#if SANITIZER_INTERCEPT_WRITEV
280INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
281                        int iovcnt) {
282  void *ctx;
283  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
284  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
285  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
286  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
287  return res;
288}
289#define INIT_WRITEV INTERCEPT_FUNCTION(writev)
290#else
291#define INIT_WRITEV
292#endif
293
294#if SANITIZER_INTERCEPT_PWRITEV
295INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
296            OFF_T offset) {
297  void *ctx;
298  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
299  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
300  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
301  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
302  return res;
303}
304#define INIT_PWRITEV INTERCEPT_FUNCTION(pwritev)
305#else
306#define INIT_PWRITEV
307#endif
308
309#if SANITIZER_INTERCEPT_PWRITEV64
310INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
311            OFF64_T offset) {
312  void *ctx;
313  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
314  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
315  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
316  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
317  return res;
318}
319#define INIT_PWRITEV64 INTERCEPT_FUNCTION(pwritev64)
320#else
321#define INIT_PWRITEV64
322#endif
323
324#if SANITIZER_INTERCEPT_PRCTL
325INTERCEPTOR(int, prctl, int option,
326            unsigned long arg2, unsigned long arg3,   // NOLINT
327            unsigned long arg4, unsigned long arg5) { // NOLINT
328  void *ctx;
329  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
330  static const int PR_SET_NAME = 15;
331  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
332  if (option == PR_SET_NAME) {
333    char buff[16];
334    internal_strncpy(buff, (char *)arg2, 15);
335    buff[15] = 0;
336    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
337  }
338  return res;
339}
340#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
341#else
342#define INIT_PRCTL
343#endif // SANITIZER_INTERCEPT_PRCTL
344
345
346#if SANITIZER_INTERCEPT_TIME
347INTERCEPTOR(unsigned long, time, unsigned long *t) {
348  void *ctx;
349  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
350  unsigned long res = REAL(time)(t);
351  if (t && res != (unsigned long)-1) {
352    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
353  }
354  return res;
355}
356#define INIT_TIME                                \
357  INTERCEPT_FUNCTION(time);
358#else
359#define INIT_TIME
360#endif // SANITIZER_INTERCEPT_TIME
361
362
363#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
364INTERCEPTOR(void *, localtime, unsigned long *timep) {
365  void *ctx;
366  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
367  void *res = REAL(localtime)(timep);
368  if (res) {
369    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
370    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
371  }
372  return res;
373}
374INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) {
375  void *ctx;
376  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
377  void *res = REAL(localtime_r)(timep, result);
378  if (res) {
379    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
380    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
381  }
382  return res;
383}
384INTERCEPTOR(void *, gmtime, unsigned long *timep) {
385  void *ctx;
386  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
387  void *res = REAL(gmtime)(timep);
388  if (res) {
389    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
390    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
391  }
392  return res;
393}
394INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) {
395  void *ctx;
396  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
397  void *res = REAL(gmtime_r)(timep, result);
398  if (res) {
399    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
400    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
401  }
402  return res;
403}
404INTERCEPTOR(char *, ctime, unsigned long *timep) {
405  void *ctx;
406  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
407  char *res = REAL(ctime)(timep);
408  if (res) {
409    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
410    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
411  }
412  return res;
413}
414INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
415  void *ctx;
416  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
417  char *res = REAL(ctime_r)(timep, result);
418  if (res) {
419    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
420    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
421  }
422  return res;
423}
424INTERCEPTOR(char *, asctime, void *tm) {
425  void *ctx;
426  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
427  char *res = REAL(asctime)(tm);
428  if (res) {
429    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
430    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
431  }
432  return res;
433}
434INTERCEPTOR(char *, asctime_r, void *tm, char *result) {
435  void *ctx;
436  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
437  char *res = REAL(asctime_r)(tm, result);
438  if (res) {
439    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
440    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
441  }
442  return res;
443}
444#define INIT_LOCALTIME_AND_FRIENDS               \
445  INTERCEPT_FUNCTION(localtime);                 \
446  INTERCEPT_FUNCTION(localtime_r);               \
447  INTERCEPT_FUNCTION(gmtime);                    \
448  INTERCEPT_FUNCTION(gmtime_r);                  \
449  INTERCEPT_FUNCTION(ctime);                     \
450  INTERCEPT_FUNCTION(ctime_r);                   \
451  INTERCEPT_FUNCTION(asctime);                   \
452  INTERCEPT_FUNCTION(asctime_r);
453#else
454#define INIT_LOCALTIME_AND_FRIENDS
455#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
456
457#if SANITIZER_INTERCEPT_SCANF
458
459#include "sanitizer_common_interceptors_scanf.inc"
460
461#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
462  {                                                                            \
463    void *ctx;                                                                 \
464    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
465    va_list aq;                                                                \
466    va_copy(aq, ap);                                                           \
467    int res = REAL(vname)(__VA_ARGS__);                                        \
468    if (res > 0)                                                               \
469      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
470    va_end(aq);                                                                \
471    return res;                                                                \
472  }
473
474INTERCEPTOR(int, vscanf, const char *format, va_list ap)
475VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
476
477INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
478VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
479
480INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
481VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
482
483#if SANITIZER_INTERCEPT_ISOC99_SCANF
484INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
485VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
486
487INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
488            va_list ap)
489VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
490
491INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
492VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
493#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF
494
495#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
496  {                                                                            \
497    void *ctx;                                                                 \
498    COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__);                          \
499    va_list ap;                                                                \
500    va_start(ap, format);                                                      \
501    int res = vname(__VA_ARGS__, ap);                                          \
502    va_end(ap);                                                                \
503    return res;                                                                \
504  }
505
506INTERCEPTOR(int, scanf, const char *format, ...)
507SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
508
509INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
510SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
511
512INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
513SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
514
515#if SANITIZER_INTERCEPT_ISOC99_SCANF
516INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
517SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
518
519INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
520SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
521
522INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
523SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
524#endif
525
526#define INIT_SCANF                                                             \
527  INTERCEPT_FUNCTION(scanf);                                                   \
528  INTERCEPT_FUNCTION(sscanf);                                                  \
529  INTERCEPT_FUNCTION(fscanf);                                                  \
530  INTERCEPT_FUNCTION(vscanf);                                                  \
531  INTERCEPT_FUNCTION(vsscanf);                                                 \
532  INTERCEPT_FUNCTION(vfscanf);                                                 \
533  INTERCEPT_FUNCTION(__isoc99_scanf);                                          \
534  INTERCEPT_FUNCTION(__isoc99_sscanf);                                         \
535  INTERCEPT_FUNCTION(__isoc99_fscanf);                                         \
536  INTERCEPT_FUNCTION(__isoc99_vscanf);                                         \
537  INTERCEPT_FUNCTION(__isoc99_vsscanf);                                        \
538  INTERCEPT_FUNCTION(__isoc99_vfscanf);
539
540#else
541#define INIT_SCANF
542#endif
543
544
545#if SANITIZER_INTERCEPT_IOCTL
546#include "sanitizer_common_interceptors_ioctl.inc"
547INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
548  void *ctx;
549  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
550
551  CHECK(ioctl_initialized);
552
553  // Note: TSan does not use common flags, and they are zero-initialized.
554  // This effectively disables ioctl handling in TSan.
555  if (!common_flags()->handle_ioctl)
556    return REAL(ioctl)(d, request, arg);
557
558  const ioctl_desc *desc = ioctl_lookup(request);
559  if (!desc)
560    Printf("WARNING: unknown ioctl %x\n", request);
561
562  if (desc)
563    ioctl_common_pre(ctx, desc, d, request, arg);
564  int res = REAL(ioctl)(d, request, arg);
565  // FIXME: some ioctls have different return values for success and failure.
566  if (desc && res != -1)
567    ioctl_common_post(ctx, desc, res, d, request, arg);
568  return res;
569}
570#define INIT_IOCTL \
571  ioctl_init();    \
572  INTERCEPT_FUNCTION(ioctl);
573#else
574#define INIT_IOCTL
575#endif
576
577
578#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
579INTERCEPTOR(void *, getpwnam, const char *name) {
580  void *ctx;
581  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
582  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
583  void *res = REAL(getpwnam)(name);
584  if (res != 0)
585    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
586  return res;
587}
588INTERCEPTOR(void *, getpwuid, u32 uid) {
589  void *ctx;
590  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
591  void *res = REAL(getpwuid)(uid);
592  if (res != 0)
593    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
594  return res;
595}
596INTERCEPTOR(void *, getgrnam, const char *name) {
597  void *ctx;
598  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
599  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
600  void *res = REAL(getgrnam)(name);
601  if (res != 0)
602    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
603  return res;
604}
605INTERCEPTOR(void *, getgrgid, u32 gid) {
606  void *ctx;
607  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
608  void *res = REAL(getgrgid)(gid);
609  if (res != 0)
610    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
611  return res;
612}
613#define INIT_GETPWNAM_AND_FRIENDS                  \
614  INTERCEPT_FUNCTION(getpwnam);                    \
615  INTERCEPT_FUNCTION(getpwuid);                    \
616  INTERCEPT_FUNCTION(getgrnam);                    \
617  INTERCEPT_FUNCTION(getgrgid);
618#else
619#define INIT_GETPWNAM_AND_FRIENDS
620#endif
621
622
623#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
624INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd,
625    char *buf, SIZE_T buflen, void **result) {
626  void *ctx;
627  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
628  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
629  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
630  if (!res) {
631    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
632    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
633  }
634  return res;
635}
636INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd,
637    char *buf, SIZE_T buflen, void **result) {
638  void *ctx;
639  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
640  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
641  if (!res) {
642    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
643    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
644  }
645  return res;
646}
647INTERCEPTOR(int, getgrnam_r, const char *name, void *grp,
648    char *buf, SIZE_T buflen, void **result) {
649  void *ctx;
650  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
651  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
652  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
653  if (!res) {
654    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
655    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
656  }
657  return res;
658}
659INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp,
660    char *buf, SIZE_T buflen, void **result) {
661  void *ctx;
662  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
663  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
664  if (!res) {
665    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
666    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
667  }
668  return res;
669}
670#define INIT_GETPWNAM_R_AND_FRIENDS                \
671  INTERCEPT_FUNCTION(getpwnam_r);                  \
672  INTERCEPT_FUNCTION(getpwuid_r);                  \
673  INTERCEPT_FUNCTION(getgrnam_r);                  \
674  INTERCEPT_FUNCTION(getgrgid_r);
675#else
676#define INIT_GETPWNAM_R_AND_FRIENDS
677#endif
678
679
680#if SANITIZER_INTERCEPT_CLOCK_GETTIME
681INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
682  void *ctx;
683  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
684  int res = REAL(clock_getres)(clk_id, tp);
685  if (!res && tp) {
686    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
687  }
688  return res;
689}
690INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
691  void *ctx;
692  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
693  int res = REAL(clock_gettime)(clk_id, tp);
694  if (!res) {
695    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
696  }
697  return res;
698}
699INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
700  void *ctx;
701  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
702  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
703  return REAL(clock_settime)(clk_id, tp);
704}
705#define INIT_CLOCK_GETTIME                         \
706  INTERCEPT_FUNCTION(clock_getres);                \
707  INTERCEPT_FUNCTION(clock_gettime);               \
708  INTERCEPT_FUNCTION(clock_settime);
709#else
710#define INIT_CLOCK_GETTIME
711#endif
712
713
714#if SANITIZER_INTERCEPT_GETITIMER
715INTERCEPTOR(int, getitimer, int which, void *curr_value) {
716  void *ctx;
717  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
718  int res = REAL(getitimer)(which, curr_value);
719  if (!res) {
720    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
721  }
722  return res;
723}
724INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
725  void *ctx;
726  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
727  COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
728  int res = REAL(setitimer)(which, new_value, old_value);
729  if (!res && old_value) {
730    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
731  }
732  return res;
733}
734#define INIT_GETITIMER                             \
735  INTERCEPT_FUNCTION(getitimer);                   \
736  INTERCEPT_FUNCTION(setitimer);
737#else
738#define INIT_GETITIMER
739#endif
740
741#if SANITIZER_INTERCEPT_GLOB
742static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
743  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
744  // +1 for NULL pointer at the end.
745  if (pglob->gl_pathv)
746    COMMON_INTERCEPTOR_WRITE_RANGE(
747        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
748  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
749    char *p = pglob->gl_pathv[i];
750    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
751  }
752}
753
754static THREADLOCAL __sanitizer_glob_t* pglob_copy;
755static THREADLOCAL void* glob_ctx;
756
757static void wrapped_gl_closedir(void *dir) {
758  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
759  pglob_copy->gl_closedir(dir);
760}
761
762static void *wrapped_gl_readdir(void *dir) {
763  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
764  return pglob_copy->gl_readdir(dir);
765}
766
767static void *wrapped_gl_opendir(const char *s) {
768  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
769  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
770  return pglob_copy->gl_opendir(s);
771}
772
773static int wrapped_gl_lstat(const char *s, void *st) {
774  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
775  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
776  return pglob_copy->gl_lstat(s, st);
777}
778
779static int wrapped_gl_stat(const char *s, void *st) {
780  COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
781  COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
782  return pglob_copy->gl_stat(s, st);
783}
784
785INTERCEPTOR(int, glob, const char *pattern, int flags,
786            int (*errfunc)(const char *epath, int eerrno),
787            __sanitizer_glob_t *pglob) {
788  void *ctx;
789  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
790  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
791                                  wrapped_gl_readdir, wrapped_gl_opendir,
792                                  wrapped_gl_lstat, wrapped_gl_stat};
793  if (flags & glob_altdirfunc) {
794    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
795    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
796    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
797    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
798    Swap(pglob->gl_stat, glob_copy.gl_stat);
799    pglob_copy = &glob_copy;
800    glob_ctx = ctx;
801  }
802  int res = REAL(glob)(pattern, flags, errfunc, pglob);
803  if (flags & glob_altdirfunc) {
804    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
805    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
806    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
807    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
808    Swap(pglob->gl_stat, glob_copy.gl_stat);
809  }
810  pglob_copy = 0;
811  glob_ctx = 0;
812  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
813  return res;
814}
815
816INTERCEPTOR(int, glob64, const char *pattern, int flags,
817            int (*errfunc)(const char *epath, int eerrno),
818            __sanitizer_glob_t *pglob) {
819  void *ctx;
820  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
821  __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
822                                  wrapped_gl_readdir, wrapped_gl_opendir,
823                                  wrapped_gl_lstat, wrapped_gl_stat};
824  if (flags & glob_altdirfunc) {
825    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
826    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
827    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
828    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
829    Swap(pglob->gl_stat, glob_copy.gl_stat);
830    pglob_copy = &glob_copy;
831    glob_ctx = ctx;
832  }
833  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
834  if (flags & glob_altdirfunc) {
835    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
836    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
837    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
838    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
839    Swap(pglob->gl_stat, glob_copy.gl_stat);
840  }
841  pglob_copy = 0;
842  glob_ctx = 0;
843  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
844  return res;
845}
846#define INIT_GLOB           \
847  INTERCEPT_FUNCTION(glob); \
848  INTERCEPT_FUNCTION(glob64);
849#else  // SANITIZER_INTERCEPT_GLOB
850#define INIT_GLOB
851#endif  // SANITIZER_INTERCEPT_GLOB
852
853#if SANITIZER_INTERCEPT_WAIT
854// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
855// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
856// details.
857INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
858  void *ctx;
859  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
860  int res = REAL(wait)(status);
861  if (res != -1 && status)
862    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
863  return res;
864}
865INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
866  int options) {
867  void *ctx;
868  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
869  int res = REAL(waitid)(idtype, id, infop, options);
870  if (res != -1 && infop)
871    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
872  return res;
873}
874INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
875  void *ctx;
876  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
877  int res = REAL(waitpid)(pid, status, options);
878  if (res != -1 && status)
879    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
880  return res;
881}
882INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
883  void *ctx;
884  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
885  int res = REAL(wait3)(status, options, rusage);
886  if (res != -1) {
887    if (status)
888      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
889    if (rusage)
890      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
891  }
892  return res;
893}
894INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
895  void *ctx;
896  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
897  int res = REAL(wait4)(pid, status, options, rusage);
898  if (res != -1) {
899    if (status)
900      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
901    if (rusage)
902      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
903  }
904  return res;
905}
906#define INIT_WAIT                                \
907  INTERCEPT_FUNCTION(wait);                      \
908  INTERCEPT_FUNCTION(waitid);                    \
909  INTERCEPT_FUNCTION(waitpid);                   \
910  INTERCEPT_FUNCTION(wait3);                     \
911  INTERCEPT_FUNCTION(wait4);
912#else
913#define INIT_WAIT
914#endif
915
916#if SANITIZER_INTERCEPT_INET
917INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
918  void *ctx;
919  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
920  uptr sz = __sanitizer_in_addr_sz(af);
921  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
922  // FIXME: figure out read size based on the address family.
923  char *res = REAL(inet_ntop)(af, src, dst, size);
924  if (res)
925    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
926  return res;
927}
928INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
929  void *ctx;
930  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
931  // FIXME: figure out read size based on the address family.
932  int res = REAL(inet_pton)(af, src, dst);
933  if (res == 1) {
934    uptr sz = __sanitizer_in_addr_sz(af);
935    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
936  }
937  return res;
938}
939#define INIT_INET                                \
940  INTERCEPT_FUNCTION(inet_ntop);                 \
941  INTERCEPT_FUNCTION(inet_pton);
942#else
943#define INIT_INET
944#endif
945
946#if SANITIZER_INTERCEPT_INET
947INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
948  void *ctx;
949  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
950  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
951  int res = REAL(inet_aton)(cp, dst);
952  if (res != 0) {
953    uptr sz = __sanitizer_in_addr_sz(af_inet);
954    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
955  }
956  return res;
957}
958#define INIT_INET_ATON INTERCEPT_FUNCTION(inet_aton);
959#else
960#define INIT_INET_ATON
961#endif
962
963#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
964INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
965  void *ctx;
966  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
967  int res = REAL(pthread_getschedparam)(thread, policy, param);
968  if (res == 0) {
969    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
970    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
971  }
972  return res;
973}
974#define INIT_PTHREAD_GETSCHEDPARAM INTERCEPT_FUNCTION(pthread_getschedparam);
975#else
976#define INIT_PTHREAD_GETSCHEDPARAM
977#endif
978
979#if SANITIZER_INTERCEPT_GETADDRINFO
980INTERCEPTOR(int, getaddrinfo, char *node, char *service,
981            struct __sanitizer_addrinfo *hints,
982            struct __sanitizer_addrinfo **out) {
983  void *ctx;
984  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
985  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
986  if (service)
987    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
988  if (hints)
989    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
990  int res = REAL(getaddrinfo)(node, service, hints, out);
991  if (res == 0 && out) {
992    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
993    struct __sanitizer_addrinfo *p = *out;
994    while (p) {
995      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
996      if (p->ai_addr)
997        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
998      if (p->ai_canonname)
999        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
1000                                       REAL(strlen)(p->ai_canonname) + 1);
1001      p = p->ai_next;
1002    }
1003  }
1004  return res;
1005}
1006#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
1007#else
1008#define INIT_GETADDRINFO
1009#endif
1010
1011#if SANITIZER_INTERCEPT_GETNAMEINFO
1012INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
1013            unsigned hostlen, char *serv, unsigned servlen, int flags) {
1014  void *ctx;
1015  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
1016                           serv, servlen, flags);
1017  // FIXME: consider adding READ_RANGE(sockaddr, salen)
1018  // There is padding in in_addr that may make this too noisy
1019  int res =
1020      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
1021  if (res == 0) {
1022    if (host && hostlen)
1023      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
1024    if (serv && servlen)
1025      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
1026  }
1027  return res;
1028}
1029#define INIT_GETNAMEINFO INTERCEPT_FUNCTION(getnameinfo);
1030#else
1031#define INIT_GETNAMEINFO
1032#endif
1033
1034#if SANITIZER_INTERCEPT_GETSOCKNAME
1035INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
1036  void *ctx;
1037  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
1038  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1039  int addrlen_in = *addrlen;
1040  int res = REAL(getsockname)(sock_fd, addr, addrlen);
1041  if (res == 0) {
1042    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
1043  }
1044  return res;
1045}
1046#define INIT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname);
1047#else
1048#define INIT_GETSOCKNAME
1049#endif
1050
1051#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1052static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
1053  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
1054  if (h->h_name)
1055    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
1056  char **p = h->h_aliases;
1057  while (*p) {
1058    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1059    ++p;
1060  }
1061  COMMON_INTERCEPTOR_WRITE_RANGE(
1062      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
1063  p = h->h_addr_list;
1064  while (*p) {
1065    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
1066    ++p;
1067  }
1068  COMMON_INTERCEPTOR_WRITE_RANGE(
1069      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
1070}
1071#endif
1072
1073#if SANITIZER_INTERCEPT_GETHOSTBYNAME
1074INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
1075  void *ctx;
1076  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
1077  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
1078  if (res) write_hostent(ctx, res);
1079  return res;
1080}
1081
1082INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
1083            int type) {
1084  void *ctx;
1085  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
1086  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1087  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
1088  if (res) write_hostent(ctx, res);
1089  return res;
1090}
1091
1092INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
1093  void *ctx;
1094  COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
1095  struct __sanitizer_hostent *res = REAL(gethostent)();
1096  if (res) write_hostent(ctx, res);
1097  return res;
1098}
1099
1100INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
1101  void *ctx;
1102  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
1103  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
1104  if (res) write_hostent(ctx, res);
1105  return res;
1106}
1107#define INIT_GETHOSTBYNAME           \
1108  INTERCEPT_FUNCTION(gethostent);    \
1109  INTERCEPT_FUNCTION(gethostbyaddr); \
1110  INTERCEPT_FUNCTION(gethostbyname); \
1111  INTERCEPT_FUNCTION(gethostbyname2);
1112#else
1113#define INIT_GETHOSTBYNAME
1114#endif
1115
1116#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1117INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
1118            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
1119  void *ctx;
1120  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
1121                           h_errnop);
1122  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
1123  if (res == 0) {
1124    if (result) {
1125      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1126      if (*result) write_hostent(ctx, *result);
1127    }
1128    if (h_errnop)
1129      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1130  }
1131  return res;
1132}
1133
1134INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
1135            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1136            __sanitizer_hostent **result, int *h_errnop) {
1137  void *ctx;
1138  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
1139                           buflen, result, h_errnop);
1140  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1141  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
1142                                  h_errnop);
1143  if (res == 0) {
1144    if (result) {
1145      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1146      if (*result) write_hostent(ctx, *result);
1147    }
1148    if (h_errnop)
1149      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1150  }
1151  return res;
1152}
1153
1154INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
1155            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
1156            int *h_errnop) {
1157  void *ctx;
1158  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
1159                           h_errnop);
1160  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
1161  if (res == 0) {
1162    if (result) {
1163      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1164      if (*result) write_hostent(ctx, *result);
1165    }
1166    if (h_errnop)
1167      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1168  }
1169  return res;
1170}
1171
1172INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
1173            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1174            __sanitizer_hostent **result, int *h_errnop) {
1175  void *ctx;
1176  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
1177                           result, h_errnop);
1178  int res =
1179      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
1180  if (res == 0) {
1181    if (result) {
1182      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1183      if (*result) write_hostent(ctx, *result);
1184    }
1185    if (h_errnop)
1186      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1187  }
1188  return res;
1189}
1190#define INIT_GETHOSTBYNAME_R           \
1191  INTERCEPT_FUNCTION(gethostent_r);    \
1192  INTERCEPT_FUNCTION(gethostbyaddr_r); \
1193  INTERCEPT_FUNCTION(gethostbyname_r); \
1194  INTERCEPT_FUNCTION(gethostbyname2_r);
1195#else
1196#define INIT_GETHOSTBYNAME_R
1197#endif
1198
1199#if SANITIZER_INTERCEPT_GETSOCKOPT
1200INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
1201            int *optlen) {
1202  void *ctx;
1203  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
1204                           optlen);
1205  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
1206  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
1207  if (res == 0)
1208    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
1209  return res;
1210}
1211#define INIT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt);
1212#else
1213#define INIT_GETSOCKOPT
1214#endif
1215
1216#if SANITIZER_INTERCEPT_ACCEPT
1217INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
1218  void *ctx;
1219  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
1220  unsigned addrlen0;
1221  if (addrlen) {
1222    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1223    addrlen0 = *addrlen;
1224  }
1225  int fd2 = REAL(accept)(fd, addr, addrlen);
1226  if (fd2 >= 0) {
1227    if (fd >= 0)
1228      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1229    if (addr && addrlen)
1230      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1231  }
1232  return fd2;
1233}
1234#define INIT_ACCEPT INTERCEPT_FUNCTION(accept);
1235#else
1236#define INIT_ACCEPT
1237#endif
1238
1239#if SANITIZER_INTERCEPT_ACCEPT4
1240INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
1241  void *ctx;
1242  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
1243  unsigned addrlen0;
1244  if (addrlen) {
1245    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1246    addrlen0 = *addrlen;
1247  }
1248  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1249  if (fd2 >= 0) {
1250    if (fd >= 0)
1251      COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1252    if (addr && addrlen)
1253      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1254  }
1255  return fd2;
1256}
1257#define INIT_ACCEPT4 INTERCEPT_FUNCTION(accept4);
1258#else
1259#define INIT_ACCEPT4
1260#endif
1261
1262#if SANITIZER_INTERCEPT_MODF
1263INTERCEPTOR(double, modf, double x, double *iptr) {
1264  void *ctx;
1265  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
1266  double res = REAL(modf)(x, iptr);
1267  if (iptr) {
1268    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1269  }
1270  return res;
1271}
1272INTERCEPTOR(float, modff, float x, float *iptr) {
1273  void *ctx;
1274  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
1275  float res = REAL(modff)(x, iptr);
1276  if (iptr) {
1277    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1278  }
1279  return res;
1280}
1281INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
1282  void *ctx;
1283  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
1284  long double res = REAL(modfl)(x, iptr);
1285  if (iptr) {
1286    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1287  }
1288  return res;
1289}
1290#define INIT_MODF            \
1291  INTERCEPT_FUNCTION(modf);  \
1292  INTERCEPT_FUNCTION(modff); \
1293  INTERCEPT_FUNCTION(modfl);
1294#else
1295#define INIT_MODF
1296#endif
1297
1298#if SANITIZER_INTERCEPT_RECVMSG
1299static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
1300                         SSIZE_T maxlen) {
1301  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
1302  if (msg->msg_name)
1303    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name,
1304                                   REAL(strlen)((char *)msg->msg_name) + 1);
1305  if (msg->msg_iov)
1306    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
1307                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
1308  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
1309  if (msg->msg_control)
1310    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
1311}
1312
1313INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
1314            int flags) {
1315  void *ctx;
1316  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
1317  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
1318  if (res >= 0) {
1319    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1320    if (msg) write_msghdr(ctx, msg, res);
1321  }
1322  return res;
1323}
1324#define INIT_RECVMSG INTERCEPT_FUNCTION(recvmsg);
1325#else
1326#define INIT_RECVMSG
1327#endif
1328
1329#if SANITIZER_INTERCEPT_GETPEERNAME
1330INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
1331  void *ctx;
1332  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
1333  unsigned addr_sz;
1334  if (addrlen) addr_sz = *addrlen;
1335  int res = REAL(getpeername)(sockfd, addr, addrlen);
1336  if (!res && addr && addrlen)
1337    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
1338  return res;
1339}
1340#define INIT_GETPEERNAME INTERCEPT_FUNCTION(getpeername);
1341#else
1342#define INIT_GETPEERNAME
1343#endif
1344
1345#if SANITIZER_INTERCEPT_SYSINFO
1346INTERCEPTOR(int, sysinfo, void *info) {
1347  void *ctx;
1348  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
1349  int res = REAL(sysinfo)(info);
1350  if (!res && info)
1351    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
1352  return res;
1353}
1354#define INIT_SYSINFO INTERCEPT_FUNCTION(sysinfo);
1355#else
1356#define INIT_SYSINFO
1357#endif
1358
1359#if SANITIZER_INTERCEPT_READDIR
1360INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
1361  void *ctx;
1362  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
1363  __sanitizer_dirent *res = REAL(readdir)(dirp);
1364  if (res)
1365    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1366  return res;
1367}
1368
1369INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
1370            __sanitizer_dirent **result) {
1371  void *ctx;
1372  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
1373  int res = REAL(readdir_r)(dirp, entry, result);
1374  if (!res) {
1375    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1376    if (*result)
1377      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1378  }
1379  return res;
1380}
1381
1382#define INIT_READDIR           \
1383  INTERCEPT_FUNCTION(readdir); \
1384  INTERCEPT_FUNCTION(readdir_r);
1385#else
1386#define INIT_READDIR
1387#endif
1388
1389#if SANITIZER_INTERCEPT_READDIR64
1390INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
1391  void *ctx;
1392  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
1393  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
1394  if (res)
1395    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
1396  return res;
1397}
1398
1399INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
1400            __sanitizer_dirent64 **result) {
1401  void *ctx;
1402  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
1403  int res = REAL(readdir64_r)(dirp, entry, result);
1404  if (!res) {
1405    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1406    if (*result)
1407      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
1408  }
1409  return res;
1410}
1411#define INIT_READDIR64           \
1412  INTERCEPT_FUNCTION(readdir64); \
1413  INTERCEPT_FUNCTION(readdir64_r);
1414#else
1415#define INIT_READDIR64
1416#endif
1417
1418#if SANITIZER_INTERCEPT_PTRACE
1419INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
1420  void *ctx;
1421  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
1422
1423  if (data) {
1424    if (request == ptrace_setregs)
1425      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
1426    else if (request == ptrace_setfpregs)
1427      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1428    else if (request == ptrace_setfpxregs)
1429      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1430    else if (request == ptrace_setsiginfo)
1431      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
1432    else if (request == ptrace_setregset) {
1433      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1434      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
1435    }
1436  }
1437
1438  uptr res = REAL(ptrace)(request, pid, addr, data);
1439
1440  if (!res && data) {
1441    // Note that PEEK* requests assing different meaning to the return value.
1442    // This function does not handle them (nor does it need to).
1443    if (request == ptrace_getregs)
1444      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
1445    else if (request == ptrace_getfpregs)
1446      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1447    else if (request == ptrace_getfpxregs)
1448      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1449    else if (request == ptrace_getsiginfo)
1450      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
1451    else if (request == ptrace_getregset) {
1452      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1453      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
1454    }
1455  }
1456  return res;
1457}
1458
1459#define INIT_PTRACE           \
1460  INTERCEPT_FUNCTION(ptrace);
1461#else
1462#define INIT_PTRACE
1463#endif
1464
1465#if SANITIZER_INTERCEPT_SETLOCALE
1466INTERCEPTOR(char *, setlocale, int category, char *locale) {
1467  void *ctx;
1468  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
1469  if (locale)
1470    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
1471  char *res = REAL(setlocale)(category, locale);
1472  if (res)
1473    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1474  return res;
1475}
1476
1477#define INIT_SETLOCALE           \
1478  INTERCEPT_FUNCTION(setlocale);
1479#else
1480#define INIT_SETLOCALE
1481#endif
1482
1483#if SANITIZER_INTERCEPT_GETCWD
1484INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
1485  void *ctx;
1486  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
1487  char *res = REAL(getcwd)(buf, size);
1488  if (res)
1489    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1490  return res;
1491}
1492#define INIT_GETCWD           \
1493  INTERCEPT_FUNCTION(getcwd);
1494#else
1495#define INIT_GETCWD
1496#endif
1497
1498#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
1499INTERCEPTOR(char *, get_current_dir_name) {
1500  void *ctx;
1501  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name);
1502  char *res = REAL(get_current_dir_name)();
1503  if (res)
1504    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1505  return res;
1506}
1507
1508#define INIT_GET_CURRENT_DIR_NAME           \
1509  INTERCEPT_FUNCTION(get_current_dir_name);
1510#else
1511#define INIT_GET_CURRENT_DIR_NAME
1512#endif
1513
1514#if SANITIZER_INTERCEPT_STRTOIMAX
1515INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
1516  void *ctx;
1517  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
1518  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
1519  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1520  return res;
1521}
1522
1523INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
1524  void *ctx;
1525  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
1526  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
1527  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
1528  return res;
1529}
1530
1531#define INIT_STRTOIMAX           \
1532  INTERCEPT_FUNCTION(strtoimax); \
1533  INTERCEPT_FUNCTION(strtoumax);
1534#else
1535#define INIT_STRTOIMAX
1536#endif
1537
1538#if SANITIZER_INTERCEPT_MBSTOWCS
1539INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
1540  void *ctx;
1541  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
1542  SIZE_T res = REAL(mbstowcs)(dest, src, len);
1543  if (res != (SIZE_T)-1 && dest) {
1544    SIZE_T write_cnt = res + (res < len);
1545    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1546  }
1547  return res;
1548}
1549
1550INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
1551            void *ps) {
1552  void *ctx;
1553  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
1554  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1555  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
1556  if (res != (SIZE_T)-1 && dest) {
1557    // Terminating '\0' is not printed iff *src is cleared.
1558    SIZE_T write_cnt = res + !(*src);
1559    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1560  }
1561  return res;
1562}
1563
1564#define INIT_MBSTOWCS           \
1565  INTERCEPT_FUNCTION(mbstowcs); \
1566  INTERCEPT_FUNCTION(mbsrtowcs);
1567#else
1568#define INIT_MBSTOWCS
1569#endif
1570
1571#if SANITIZER_INTERCEPT_MBSNRTOWCS
1572INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
1573            SIZE_T len, void *ps) {
1574  void *ctx;
1575  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
1576  if (nms) {
1577    COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1578    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1579  }
1580  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
1581  if (res != (SIZE_T)-1 && dest && nms) {
1582    // Terminating '\0' is not printed iff *src is cleared.
1583    SIZE_T write_cnt = res + !(*src);
1584    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
1585  }
1586  return res;
1587}
1588
1589#define INIT_MBSNRTOWCS INTERCEPT_FUNCTION(mbsnrtowcs);
1590#else
1591#define INIT_MBSNRTOWCS
1592#endif
1593
1594#if SANITIZER_INTERCEPT_WCSTOMBS
1595INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
1596  void *ctx;
1597  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
1598  SIZE_T res = REAL(wcstombs)(dest, src, len);
1599  if (res != (SIZE_T)-1 && dest) {
1600    SIZE_T write_cnt = res + (res < len);
1601    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1602  }
1603  return res;
1604}
1605
1606INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
1607            void *ps) {
1608  void *ctx;
1609  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
1610  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1611  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
1612  if (res != (SIZE_T)-1 && dest) {
1613    // Terminating '\0' is not printed iff *src is cleared.
1614    SIZE_T write_cnt = res + !(*src);
1615    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1616  }
1617  return res;
1618}
1619
1620#define INIT_WCSTOMBS           \
1621  INTERCEPT_FUNCTION(wcstombs); \
1622  INTERCEPT_FUNCTION(wcsrtombs);
1623#else
1624#define INIT_WCSTOMBS
1625#endif
1626
1627#if SANITIZER_INTERCEPT_WCSNRTOMBS
1628INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
1629            SIZE_T len, void *ps) {
1630  void *ctx;
1631  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
1632  if (nms) {
1633    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
1634    COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
1635  }
1636  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
1637  if (res != (SIZE_T)-1 && dest && nms) {
1638    // Terminating '\0' is not printed iff *src is cleared.
1639    SIZE_T write_cnt = res + !(*src);
1640    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
1641  }
1642  return res;
1643}
1644
1645#define INIT_WCSNRTOMBS INTERCEPT_FUNCTION(wcsnrtombs);
1646#else
1647#define INIT_WCSNRTOMBS
1648#endif
1649
1650
1651#if SANITIZER_INTERCEPT_TCGETATTR
1652INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
1653  void *ctx;
1654  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
1655  int res = REAL(tcgetattr)(fd, termios_p);
1656  if (!res && termios_p)
1657    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
1658  return res;
1659}
1660
1661#define INIT_TCGETATTR INTERCEPT_FUNCTION(tcgetattr);
1662#else
1663#define INIT_TCGETATTR
1664#endif
1665
1666
1667#if SANITIZER_INTERCEPT_REALPATH
1668INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
1669  void *ctx;
1670  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
1671  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1672
1673  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
1674  // version of a versioned symbol. For realpath(), this gives us something
1675  // (called __old_realpath) that does not handle NULL in the second argument.
1676  // Handle it as part of the interceptor.
1677  char *allocated_path = 0;
1678  if (!resolved_path)
1679    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
1680
1681  char *res = REAL(realpath)(path, resolved_path);
1682  if (allocated_path && !res)
1683    WRAP(free)(allocated_path);
1684  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1685  return res;
1686}
1687#define INIT_REALPATH INTERCEPT_FUNCTION(realpath);
1688#else
1689#define INIT_REALPATH
1690#endif
1691
1692#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
1693INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
1694  void *ctx;
1695  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
1696  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
1697  char *res = REAL(canonicalize_file_name)(path);
1698  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1699  return res;
1700}
1701#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name);
1702#else
1703#define INIT_CANONICALIZE_FILE_NAME
1704#endif
1705
1706#define SANITIZER_COMMON_INTERCEPTORS_INIT \
1707  INIT_STRCASECMP;                         \
1708  INIT_STRNCASECMP;                        \
1709  INIT_READ;                               \
1710  INIT_PREAD;                              \
1711  INIT_PREAD64;                            \
1712  INIT_READV;                              \
1713  INIT_PREADV;                             \
1714  INIT_PREADV64;                           \
1715  INIT_WRITE;                              \
1716  INIT_PWRITE;                             \
1717  INIT_PWRITE64;                           \
1718  INIT_WRITEV;                             \
1719  INIT_PWRITEV;                            \
1720  INIT_PWRITEV64;                          \
1721  INIT_PRCTL;                              \
1722  INIT_LOCALTIME_AND_FRIENDS;              \
1723  INIT_SCANF;                              \
1724  INIT_FREXP;                              \
1725  INIT_FREXPF_FREXPL;                      \
1726  INIT_GETPWNAM_AND_FRIENDS;               \
1727  INIT_GETPWNAM_R_AND_FRIENDS;             \
1728  INIT_CLOCK_GETTIME;                      \
1729  INIT_GETITIMER;                          \
1730  INIT_TIME;                               \
1731  INIT_GLOB;                               \
1732  INIT_WAIT;                               \
1733  INIT_INET;                               \
1734  INIT_PTHREAD_GETSCHEDPARAM;              \
1735  INIT_GETADDRINFO;                        \
1736  INIT_GETNAMEINFO;                        \
1737  INIT_GETSOCKNAME;                        \
1738  INIT_GETHOSTBYNAME;                      \
1739  INIT_GETHOSTBYNAME_R;                    \
1740  INIT_GETSOCKOPT;                         \
1741  INIT_ACCEPT;                             \
1742  INIT_ACCEPT4;                            \
1743  INIT_MODF;                               \
1744  INIT_RECVMSG;                            \
1745  INIT_GETPEERNAME;                        \
1746  INIT_IOCTL;                              \
1747  INIT_INET_ATON;                          \
1748  INIT_SYSINFO;                            \
1749  INIT_READDIR;                            \
1750  INIT_READDIR64;                          \
1751  INIT_PTRACE;                             \
1752  INIT_SETLOCALE;                          \
1753  INIT_GETCWD;                             \
1754  INIT_GET_CURRENT_DIR_NAME;               \
1755  INIT_STRTOIMAX;                          \
1756  INIT_MBSTOWCS;                           \
1757  INIT_MBSNRTOWCS;                         \
1758  INIT_WCSTOMBS;                           \
1759  INIT_WCSNRTOMBS;                         \
1760  INIT_TCGETATTR;                          \
1761  INIT_REALPATH;                           \
1762  INIT_CANONICALIZE_FILE_NAME;
1763