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