blob: 7ec90da3026431056fc4e83289948bac2a436695 [file] [log] [blame]
Evgeniy Stepanov4f32c0b2013-01-18 13:01:18 +00001//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
Kostya Serebryany8530e2b2012-12-12 09:54:35 +00002//
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
Kostya Serebryanyc8033192013-01-17 13:09:00 +000018// COMMON_INTERCEPTOR_FD_ACQUIRE
19// COMMON_INTERCEPTOR_FD_RELEASE
Kostya Serebryanyc20b3212013-01-18 06:43:13 +000020// COMMON_INTERCEPTOR_SET_THREAD_NAME
Kostya Serebryany8530e2b2012-12-12 09:54:35 +000021//===----------------------------------------------------------------------===//
Kostya Serebryany6afa1b02012-12-13 06:31:40 +000022#include "interception/interception.h"
Alexey Samsonov74737d52012-12-13 08:50:16 +000023#include "sanitizer_platform_interceptors.h"
Kostya Serebryanyb1cc4e42012-12-13 05:27:08 +000024
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +000025#include <stdarg.h>
26
Evgeniy Stepanov30e110e2013-03-19 14:54:17 +000027#if SANITIZER_WINDOWS
Evgeniy Stepanov348bd122013-02-11 14:08:12 +000028#define va_copy(dst, src) ((dst) = (src))
29#endif // _WIN32
30
Dmitry Vyukovbe523662013-03-26 12:40:23 +000031#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
Evgeniy Stepanov7cbbb292013-03-14 11:34:39 +000077#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
Alexey Samsonovff5d1fc2013-03-15 14:02:21 +000086#define INIT_FREXP INTERCEPT_FUNCTION(frexp);
87#else
88#define INIT_FREXP
89#endif // SANITIZER_INTERCEPT_FREXP
90
91#if SANITIZER_INTERCEPT_FREXPF_FREXPL
Evgeniy Stepanov7cbbb292013-03-14 11:34:39 +000092INTERCEPTOR(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
Alexey Samsonovff5d1fc2013-03-15 14:02:21 +0000108#define INIT_FREXPF_FREXPL \
Evgeniy Stepanov7cbbb292013-03-14 11:34:39 +0000109 INTERCEPT_FUNCTION(frexpf); \
110 INTERCEPT_FUNCTION(frexpl)
111#else
Alexey Samsonovff5d1fc2013-03-15 14:02:21 +0000112#define INIT_FREXPF_FREXPL
113#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
Evgeniy Stepanov7cbbb292013-03-14 11:34:39 +0000114
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +0000115#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
Alexey Samsonov8ffd8772012-12-13 08:36:13 +0000136#if SANITIZER_INTERCEPT_READ
Kostya Serebryany6afa1b02012-12-13 06:31:40 +0000137INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000138 void *ctx;
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000139 COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
Kostya Serebryany6afa1b02012-12-13 06:31:40 +0000140 SSIZE_T res = REAL(read)(fd, ptr, count);
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000141 if (res > 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000142 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
Kostya Serebryanyc8033192013-01-17 13:09:00 +0000143 if (res >= 0 && fd >= 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000144 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000145 return res;
146}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000147#define INIT_READ INTERCEPT_FUNCTION(read)
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000148#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000149#define INIT_READ
Alexey Samsonov8ffd8772012-12-13 08:36:13 +0000150#endif
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000151
Alexey Samsonovc333dff2012-12-13 08:10:23 +0000152#if SANITIZER_INTERCEPT_PREAD
Kostya Serebryany6afa1b02012-12-13 06:31:40 +0000153INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000154 void *ctx;
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000155 COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
Kostya Serebryany6afa1b02012-12-13 06:31:40 +0000156 SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000157 if (res > 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000158 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
Kostya Serebryanyc8033192013-01-17 13:09:00 +0000159 if (res >= 0 && fd >= 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000160 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000161 return res;
162}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000163#define INIT_PREAD INTERCEPT_FUNCTION(pread)
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000164#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000165#define INIT_PREAD
Alexey Samsonovc333dff2012-12-13 08:10:23 +0000166#endif
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000167
Kostya Serebryanyb1cc4e42012-12-13 05:27:08 +0000168#if SANITIZER_INTERCEPT_PREAD64
Kostya Serebryany6afa1b02012-12-13 06:31:40 +0000169INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000170 void *ctx;
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000171 COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
Kostya Serebryany6afa1b02012-12-13 06:31:40 +0000172 SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000173 if (res > 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000174 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
Kostya Serebryanyc8033192013-01-17 13:09:00 +0000175 if (res >= 0 && fd >= 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000176 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000177 return res;
178}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000179#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
Alexey Samsonovc333dff2012-12-13 08:10:23 +0000180#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000181#define INIT_PREAD64
Alexander Potapenko1f5e23e2012-12-12 11:52:26 +0000182#endif
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000183
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +0000184#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
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000229#if SANITIZER_INTERCEPT_WRITE
230INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000231 void *ctx;
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000232 COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000233 if (fd >= 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000234 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000235 SSIZE_T res = REAL(write)(fd, ptr, count);
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +0000236 // FIXME: this check should be _before_ the call to REAL(write), not after
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000237 if (res > 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000238 COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000239 return res;
240}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000241#define INIT_WRITE INTERCEPT_FUNCTION(write)
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000242#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000243#define INIT_WRITE
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000244#endif
245
246#if SANITIZER_INTERCEPT_PWRITE
Dmitry Vyukovf0c846b2013-01-24 07:44:21 +0000247INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000248 void *ctx;
Dmitry Vyukovf0c846b2013-01-24 07:44:21 +0000249 COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000250 if (fd >= 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000251 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
Dmitry Vyukovf0c846b2013-01-24 07:44:21 +0000252 SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000253 if (res > 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000254 COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000255 return res;
256}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000257#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000258#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000259#define INIT_PWRITE
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000260#endif
261
262#if SANITIZER_INTERCEPT_PWRITE64
Dmitry Vyukovf0c846b2013-01-24 07:44:21 +0000263INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
264 OFF64_T offset) {
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000265 void *ctx;
Dmitry Vyukovf0c846b2013-01-24 07:44:21 +0000266 COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000267 if (fd >= 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000268 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
Dmitry Vyukovf0c846b2013-01-24 07:44:21 +0000269 SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000270 if (res > 0)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000271 COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000272 return res;
273}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000274#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000275#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000276#define INIT_PWRITE64
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000277#endif
278
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +0000279#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
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000324#if SANITIZER_INTERCEPT_PRCTL
Evgeniy Stepanov69b109a2013-02-20 11:06:07 +0000325INTERCEPTOR(int, prctl, int option,
326 unsigned long arg2, unsigned long arg3, // NOLINT
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000327 unsigned long arg4, unsigned long arg5) { // NOLINT
328 void *ctx;
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000329 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000330 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];
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000334 internal_strncpy(buff, (char *)arg2, 15);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000335 buff[15] = 0;
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000336 COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000337 }
338 return res;
339}
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000340#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000341#else
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000342#define INIT_PRCTL
343#endif // SANITIZER_INTERCEPT_PRCTL
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000344
Evgeniy Stepanovfef66052013-04-08 08:25:22 +0000345
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);
Alexander Potapenko15832c22013-04-10 15:13:00 +0000351 if (t && res != (unsigned long)-1) {
Evgeniy Stepanovfef66052013-04-08 08:25:22 +0000352 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
Evgeniy Stepanov9358c582013-02-19 09:19:16 +0000363#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
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000457#if SANITIZER_INTERCEPT_SCANF
458
Evgeniy Stepanov4f32c0b2013-01-18 13:01:18 +0000459#include "sanitizer_common_interceptors_scanf.inc"
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000460
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000461#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000462 { \
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) \
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000469 scanf_common(ctx, res, allowGnuMalloc, format, aq); \
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000470 va_end(aq); \
471 return res; \
472 }
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000473
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000474INTERCEPTOR(int, vscanf, const char *format, va_list ap)
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000475VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000476
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000477INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000478VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000479
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000480INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000481VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000482
Alexander Potapenko9eab8582013-02-20 15:27:58 +0000483#if SANITIZER_INTERCEPT_ISOC99_SCANF
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000484INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000485VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000486
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000487INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
488 va_list ap)
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000489VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000490
491INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
Evgeniy Stepanovc5b4e862013-02-12 14:29:34 +0000492VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
Alexander Potapenko9eab8582013-02-20 15:27:58 +0000493#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000494
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
Alexander Potapenko9eab8582013-02-20 15:27:58 +0000515#if SANITIZER_INTERCEPT_ISOC99_SCANF
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000516INTERCEPTOR(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)
Alexander Potapenko9eab8582013-02-20 15:27:58 +0000524#endif
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000525
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000526#define INIT_SCANF \
527 INTERCEPT_FUNCTION(scanf); \
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000528 INTERCEPT_FUNCTION(sscanf); \
Evgeniy Stepanov44be70b2013-02-11 15:22:34 +0000529 INTERCEPT_FUNCTION(fscanf); \
530 INTERCEPT_FUNCTION(vscanf); \
531 INTERCEPT_FUNCTION(vsscanf); \
Evgeniy Stepanov4ae1adb2013-02-12 11:34:52 +0000532 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);
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000539
540#else
541#define INIT_SCANF
542#endif
543
Evgeniy Stepanov745dd0d2013-06-07 13:00:47 +0000544
Evgeniy Stepanov4e95e942013-06-07 13:19:33 +0000545#if SANITIZER_INTERCEPT_IOCTL
Evgeniy Stepanov745dd0d2013-06-07 13:00:47 +0000546#include "sanitizer_common_interceptors_ioctl.inc"
Evgeniy Stepanov4e95e942013-06-07 13:19:33 +0000547INTERCEPTOR(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}
Evgeniy Stepanov4ce6f792013-06-07 14:56:54 +0000570#define INIT_IOCTL \
571 ioctl_init(); \
572 INTERCEPT_FUNCTION(ioctl);
Evgeniy Stepanov4e95e942013-06-07 13:19:33 +0000573#else
574#define INIT_IOCTL
575#endif
Evgeniy Stepanov745dd0d2013-06-07 13:00:47 +0000576
577
Evgeniy Stepanov103a63e2013-04-23 12:01:20 +0000578#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000579INTERCEPTOR(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}
Evgeniy Stepanov103a63e2013-04-23 12:01:20 +0000596INTERCEPTOR(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);
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000618#else
Evgeniy Stepanov103a63e2013-04-23 12:01:20 +0000619#define INIT_GETPWNAM_AND_FRIENDS
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000620#endif
621
622
Evgeniy Stepanov103a63e2013-04-23 12:01:20 +0000623#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000624INTERCEPTOR(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}
Evgeniy Stepanov103a63e2013-04-23 12:01:20 +0000647INTERCEPTOR(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);
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000675#else
Evgeniy Stepanov103a63e2013-04-23 12:01:20 +0000676#define INIT_GETPWNAM_R_AND_FRIENDS
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000677#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);
Evgeniy Stepanov7cdae162013-04-23 11:48:31 +0000685 if (!res && tp) {
Evgeniy Stepanove4bdda52013-04-01 14:47:21 +0000686 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
Evgeniy Stepanova1c2a552013-04-09 11:35:13 +0000742#if SANITIZER_INTERCEPT_GLOB
743struct sanitizer_glob_t {
744 SIZE_T gl_pathc;
745 char **gl_pathv;
746};
747
748static void unpoison_glob_t(void *ctx, sanitizer_glob_t *pglob) {
749 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
750 // +1 for NULL pointer at the end.
751 COMMON_INTERCEPTOR_WRITE_RANGE(
752 ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
753 for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
754 char *p = pglob->gl_pathv[i];
755 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
756 }
757}
758
759INTERCEPTOR(int, glob, const char *pattern, int flags,
760 int (*errfunc)(const char *epath, int eerrno),
761 sanitizer_glob_t *pglob) {
762 void *ctx;
763 COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
764 int res = REAL(glob)(pattern, flags, errfunc, pglob);
765 if (res == 0)
766 unpoison_glob_t(ctx, pglob);
767 return res;
768}
769
770INTERCEPTOR(int, glob64, const char *pattern, int flags,
771 int (*errfunc)(const char *epath, int eerrno),
772 sanitizer_glob_t *pglob) {
773 void *ctx;
774 COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
775 int res = REAL(glob64)(pattern, flags, errfunc, pglob);
776 if (res == 0)
777 unpoison_glob_t(ctx, pglob);
778 return res;
779}
780#define INIT_GLOB \
781 INTERCEPT_FUNCTION(glob); \
782 INTERCEPT_FUNCTION(glob64);
783#else // SANITIZER_INTERCEPT_GLOB
784#define INIT_GLOB
785#endif // SANITIZER_INTERCEPT_GLOB
786
787
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000788#if SANITIZER_INTERCEPT_WAIT
Alexander Potapenko6a659df2013-05-20 13:32:35 +0000789// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
790// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
791// details.
792INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000793 void *ctx;
794 COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
795 int res = REAL(wait)(status);
Dmitry Vyukovf82eb242013-04-29 09:04:24 +0000796 if (res != -1 && status)
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000797 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
798 return res;
799}
Kostya Serebryany30e970f2013-05-22 08:54:30 +0000800INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
801 int options) {
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000802 void *ctx;
803 COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
804 int res = REAL(waitid)(idtype, id, infop, options);
Dmitry Vyukovf82eb242013-04-29 09:04:24 +0000805 if (res != -1 && infop)
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000806 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
807 return res;
808}
Alexander Potapenko6a659df2013-05-20 13:32:35 +0000809INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000810 void *ctx;
811 COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
812 int res = REAL(waitpid)(pid, status, options);
Dmitry Vyukovf82eb242013-04-29 09:04:24 +0000813 if (res != -1 && status)
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000814 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
815 return res;
816}
817INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
818 void *ctx;
819 COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
820 int res = REAL(wait3)(status, options, rusage);
821 if (res != -1) {
Dmitry Vyukovf82eb242013-04-29 09:04:24 +0000822 if (status)
823 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000824 if (rusage)
825 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
826 }
827 return res;
828}
829INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
830 void *ctx;
831 COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
832 int res = REAL(wait4)(pid, status, options, rusage);
833 if (res != -1) {
Dmitry Vyukovf82eb242013-04-29 09:04:24 +0000834 if (status)
835 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000836 if (rusage)
837 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
838 }
839 return res;
840}
841#define INIT_WAIT \
842 INTERCEPT_FUNCTION(wait); \
843 INTERCEPT_FUNCTION(waitid); \
844 INTERCEPT_FUNCTION(waitpid); \
845 INTERCEPT_FUNCTION(wait3); \
846 INTERCEPT_FUNCTION(wait4);
847#else
848#define INIT_WAIT
849#endif
850
Evgeniy Stepanov9530eb72013-04-23 14:05:15 +0000851#if SANITIZER_INTERCEPT_INET
852INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
853 void *ctx;
854 COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
855 uptr sz = __sanitizer_in_addr_sz(af);
856 if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
857 // FIXME: figure out read size based on the address family.
858 char *res = REAL(inet_ntop)(af, src, dst, size);
859 if (res)
860 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
861 return res;
862}
863INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
864 void *ctx;
865 COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
866 // FIXME: figure out read size based on the address family.
867 int res = REAL(inet_pton)(af, src, dst);
868 if (res == 1) {
869 uptr sz = __sanitizer_in_addr_sz(af);
870 if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
871 }
872 return res;
873}
874#define INIT_INET \
875 INTERCEPT_FUNCTION(inet_ntop); \
876 INTERCEPT_FUNCTION(inet_pton);
877#else
878#define INIT_INET
879#endif
880
Evgeniy Stepanov9d600872013-06-24 13:56:14 +0000881#if SANITIZER_INTERCEPT_INET
882INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
883 void *ctx;
884 COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
885 if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
886 int res = REAL(inet_aton)(cp, dst);
887 if (res != 0) {
888 uptr sz = __sanitizer_in_addr_sz(af_inet);
889 if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
890 }
891 return res;
892}
893#define INIT_INET_ATON INTERCEPT_FUNCTION(inet_aton);
894#else
895#define INIT_INET_ATON
896#endif
897
Evgeniy Stepanov56d34722013-05-21 08:12:08 +0000898#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
899INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
900 void *ctx;
901 COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
902 int res = REAL(pthread_getschedparam)(thread, policy, param);
903 if (res == 0) {
904 if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
905 if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
906 }
907 return res;
908}
909#define INIT_PTHREAD_GETSCHEDPARAM INTERCEPT_FUNCTION(pthread_getschedparam);
910#else
911#define INIT_PTHREAD_GETSCHEDPARAM
912#endif
Evgeniy Stepanov897a4ae2013-04-09 14:34:59 +0000913
Evgeniy Stepanov447ef192013-05-22 12:50:26 +0000914#if SANITIZER_INTERCEPT_GETADDRINFO
915INTERCEPTOR(int, getaddrinfo, char *node, char *service,
916 struct __sanitizer_addrinfo *hints,
917 struct __sanitizer_addrinfo **out) {
918 void *ctx;
919 COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
920 if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
921 if (service)
922 COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
923 if (hints)
924 COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
925 int res = REAL(getaddrinfo)(node, service, hints, out);
Evgeniy Stepanov3538eb82013-05-28 14:34:37 +0000926 if (res == 0 && out) {
927 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
Evgeniy Stepanov447ef192013-05-22 12:50:26 +0000928 struct __sanitizer_addrinfo *p = *out;
929 while (p) {
Evgeniy Stepanov3538eb82013-05-28 14:34:37 +0000930 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
Evgeniy Stepanov447ef192013-05-22 12:50:26 +0000931 if (p->ai_addr)
Evgeniy Stepanov512c6162013-05-29 12:33:31 +0000932 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
Evgeniy Stepanov447ef192013-05-22 12:50:26 +0000933 if (p->ai_canonname)
934 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
935 REAL(strlen)(p->ai_canonname) + 1);
936 p = p->ai_next;
937 }
938 }
939 return res;
940}
941#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
942#else
943#define INIT_GETADDRINFO
944#endif
945
Evgeniy Stepanov9f58c5c2013-05-22 13:46:22 +0000946#if SANITIZER_INTERCEPT_GETSOCKNAME
947INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
948 void *ctx;
949 COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
950 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
951 int addrlen_in = *addrlen;
952 int res = REAL(getsockname)(sock_fd, addr, addrlen);
953 if (res == 0) {
954 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
955 }
956 return res;
957}
958#define INIT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname);
959#else
960#define INIT_GETSOCKNAME
961#endif
Evgeniy Stepanov447ef192013-05-22 12:50:26 +0000962
Evgeniy Stepanov33b14852013-05-23 11:41:58 +0000963#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
Evgeniy Stepanov0a2cc372013-05-23 11:10:23 +0000964static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
965 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
966 if (h->h_name)
967 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
968 char **p = h->h_aliases;
969 while (*p) {
970 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
971 ++p;
972 }
973 COMMON_INTERCEPTOR_WRITE_RANGE(
974 ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
975 p = h->h_addr_list;
976 while (*p) {
977 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
978 ++p;
979 }
980 COMMON_INTERCEPTOR_WRITE_RANGE(
981 ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
982}
Evgeniy Stepanov33b14852013-05-23 11:41:58 +0000983#endif
Evgeniy Stepanov0a2cc372013-05-23 11:10:23 +0000984
985#if SANITIZER_INTERCEPT_GETHOSTBYNAME
986INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
987 void *ctx;
988 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
989 struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
990 if (res) write_hostent(ctx, res);
991 return res;
992}
993
994INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
995 int type) {
996 void *ctx;
997 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
998 COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
999 struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
1000 if (res) write_hostent(ctx, res);
1001 return res;
1002}
1003
1004INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
1005 void *ctx;
1006 COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
1007 struct __sanitizer_hostent *res = REAL(gethostent)();
1008 if (res) write_hostent(ctx, res);
1009 return res;
1010}
1011
1012INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
1013 void *ctx;
1014 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
1015 struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
1016 if (res) write_hostent(ctx, res);
1017 return res;
1018}
1019#define INIT_GETHOSTBYNAME \
1020 INTERCEPT_FUNCTION(gethostent); \
1021 INTERCEPT_FUNCTION(gethostbyaddr); \
1022 INTERCEPT_FUNCTION(gethostbyname); \
1023 INTERCEPT_FUNCTION(gethostbyname2);
1024#else
1025#define INIT_GETHOSTBYNAME
1026#endif
1027
1028#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
1029INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
1030 SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
1031 void *ctx;
1032 COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
1033 h_errnop);
1034 int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
1035 if (res == 0) {
1036 if (result) {
1037 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1038 if (*result) write_hostent(ctx, *result);
1039 }
1040 if (h_errnop)
1041 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1042 }
1043 return res;
1044}
1045
1046INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
1047 struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1048 __sanitizer_hostent **result, int *h_errnop) {
1049 void *ctx;
1050 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
1051 buflen, result, h_errnop);
1052 COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
1053 int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
1054 h_errnop);
1055 if (res == 0) {
1056 if (result) {
1057 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1058 if (*result) write_hostent(ctx, *result);
1059 }
1060 if (h_errnop)
1061 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1062 }
1063 return res;
1064}
1065
1066INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
1067 char *buf, SIZE_T buflen, __sanitizer_hostent **result,
1068 int *h_errnop) {
1069 void *ctx;
1070 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
1071 h_errnop);
1072 int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
1073 if (res == 0) {
1074 if (result) {
1075 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1076 if (*result) write_hostent(ctx, *result);
1077 }
1078 if (h_errnop)
1079 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1080 }
1081 return res;
1082}
1083
1084INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
1085 struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
1086 __sanitizer_hostent **result, int *h_errnop) {
1087 void *ctx;
1088 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
1089 result, h_errnop);
1090 int res =
1091 REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
1092 if (res == 0) {
1093 if (result) {
1094 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1095 if (*result) write_hostent(ctx, *result);
1096 }
1097 if (h_errnop)
1098 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
1099 }
1100 return res;
1101}
1102#define INIT_GETHOSTBYNAME_R \
1103 INTERCEPT_FUNCTION(gethostent_r); \
1104 INTERCEPT_FUNCTION(gethostbyaddr_r); \
1105 INTERCEPT_FUNCTION(gethostbyname_r); \
1106 INTERCEPT_FUNCTION(gethostbyname2_r);
1107#else
1108#define INIT_GETHOSTBYNAME_R
1109#endif
1110
Evgeniy Stepanovf32be422013-05-23 11:38:08 +00001111#if SANITIZER_INTERCEPT_GETSOCKOPT
1112INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
1113 int *optlen) {
1114 void *ctx;
1115 COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
1116 optlen);
1117 if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
1118 int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
1119 if (res == 0)
1120 if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
1121 return res;
1122}
1123#define INIT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt);
1124#else
1125#define INIT_GETSOCKOPT
1126#endif
1127
Evgeniy Stepanov9d1525e2013-05-29 09:09:58 +00001128#if SANITIZER_INTERCEPT_ACCEPT
1129INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
1130 void *ctx;
1131 COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
1132 unsigned addrlen0;
1133 if (addrlen) {
1134 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1135 addrlen0 = *addrlen;
1136 }
1137 int fd2 = REAL(accept)(fd, addr, addrlen);
1138 if (fd2 >= 0) {
1139 if (fd >= 0)
1140 COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1141 if (addr && addrlen)
1142 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1143 }
1144 return fd2;
1145}
1146#define INIT_ACCEPT INTERCEPT_FUNCTION(accept);
1147#else
1148#define INIT_ACCEPT
1149#endif
1150
1151#if SANITIZER_INTERCEPT_ACCEPT4
1152INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
1153 void *ctx;
1154 COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
1155 unsigned addrlen0;
1156 if (addrlen) {
1157 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
1158 addrlen0 = *addrlen;
1159 }
1160 int fd2 = REAL(accept4)(fd, addr, addrlen, f);
1161 if (fd2 >= 0) {
1162 if (fd >= 0)
1163 COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
1164 if (addr && addrlen)
1165 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
1166 }
1167 return fd2;
1168}
1169#define INIT_ACCEPT4 INTERCEPT_FUNCTION(accept4);
1170#else
1171#define INIT_ACCEPT4
1172#endif
1173
Evgeniy Stepanovc87088b2013-05-29 10:03:11 +00001174#if SANITIZER_INTERCEPT_MODF
1175INTERCEPTOR(double, modf, double x, double *iptr) {
1176 void *ctx;
1177 COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
1178 double res = REAL(modf)(x, iptr);
1179 if (iptr) {
1180 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1181 }
1182 return res;
1183}
1184INTERCEPTOR(float, modff, float x, float *iptr) {
1185 void *ctx;
1186 COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
1187 float res = REAL(modff)(x, iptr);
1188 if (iptr) {
1189 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1190 }
1191 return res;
1192}
1193INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
1194 void *ctx;
1195 COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
1196 long double res = REAL(modfl)(x, iptr);
1197 if (iptr) {
1198 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
1199 }
1200 return res;
1201}
1202#define INIT_MODF \
1203 INTERCEPT_FUNCTION(modf); \
1204 INTERCEPT_FUNCTION(modff); \
1205 INTERCEPT_FUNCTION(modfl);
1206#else
1207#define INIT_MODF
1208#endif
1209
Evgeniy Stepanov9666d892013-05-29 11:30:00 +00001210#if SANITIZER_INTERCEPT_RECVMSG
Evgeniy Stepanoveb7c24b2013-06-26 09:16:45 +00001211static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
1212 SSIZE_T maxlen) {
Evgeniy Stepanov9666d892013-05-29 11:30:00 +00001213 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
1214 if (msg->msg_name)
1215 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name,
1216 REAL(strlen)((char *)msg->msg_name) + 1);
1217 if (msg->msg_iov)
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +00001218 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
1219 sizeof(*msg->msg_iov) * msg->msg_iovlen);
1220 write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
Evgeniy Stepanov9666d892013-05-29 11:30:00 +00001221 if (msg->msg_control)
1222 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
1223}
1224
1225INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
1226 int flags) {
1227 void *ctx;
1228 COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
1229 SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
1230 if (res >= 0) {
1231 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +00001232 if (msg) write_msghdr(ctx, msg, res);
Evgeniy Stepanov9666d892013-05-29 11:30:00 +00001233 }
1234 return res;
1235}
1236#define INIT_RECVMSG INTERCEPT_FUNCTION(recvmsg);
1237#else
1238#define INIT_RECVMSG
1239#endif
1240
Evgeniy Stepanovbc33e132013-05-29 11:49:25 +00001241#if SANITIZER_INTERCEPT_GETPEERNAME
1242INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
1243 void *ctx;
1244 COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
1245 unsigned addr_sz;
1246 if (addrlen) addr_sz = *addrlen;
1247 int res = REAL(getpeername)(sockfd, addr, addrlen);
1248 if (!res && addr && addrlen)
1249 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
1250 return res;
1251}
1252#define INIT_GETPEERNAME INTERCEPT_FUNCTION(getpeername);
1253#else
1254#define INIT_GETPEERNAME
1255#endif
1256
Evgeniy Stepanov359d7fc2013-06-24 14:25:33 +00001257#if SANITIZER_INTERCEPT_SYSINFO
1258INTERCEPTOR(int, sysinfo, void *info) {
1259 void *ctx;
1260 COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
1261 int res = REAL(sysinfo)(info);
1262 if (!res && info)
1263 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
1264 return res;
1265}
1266#define INIT_SYSINFO INTERCEPT_FUNCTION(sysinfo);
1267#else
1268#define INIT_SYSINFO
1269#endif
1270
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001271#if SANITIZER_INTERCEPT_READDIR
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001272INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001273 void *ctx;
1274 COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001275 __sanitizer_dirent *res = REAL(readdir)(dirp);
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001276 if (res)
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001277 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001278 return res;
1279}
1280
Alexey Samsonov52d08d82013-06-28 12:13:31 +00001281INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
1282 __sanitizer_dirent **result) {
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001283 void *ctx;
1284 COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
1285 int res = REAL(readdir_r)(dirp, entry, result);
1286 if (!res) {
1287 if (result)
1288 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1289 if (entry)
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001290 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, entry, entry->d_reclen);
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001291 }
1292 return res;
1293}
1294
1295#define INIT_READDIR \
1296 INTERCEPT_FUNCTION(readdir); \
1297 INTERCEPT_FUNCTION(readdir_r);
1298#else
1299#define INIT_READDIR
1300#endif
1301
1302#if SANITIZER_INTERCEPT_READDIR64
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001303INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001304 void *ctx;
1305 COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001306 __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001307 if (res)
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001308 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001309 return res;
1310}
1311
Alexey Samsonov52d08d82013-06-28 12:13:31 +00001312INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
1313 __sanitizer_dirent64 **result) {
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001314 void *ctx;
1315 COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
1316 int res = REAL(readdir64_r)(dirp, entry, result);
1317 if (!res) {
1318 if (result)
1319 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1320 if (entry)
Evgeniy Stepanova0379b52013-06-27 09:37:27 +00001321 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, entry, entry->d_reclen);
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001322 }
1323 return res;
1324}
1325#define INIT_READDIR64 \
1326 INTERCEPT_FUNCTION(readdir64); \
1327 INTERCEPT_FUNCTION(readdir64_r);
1328#else
1329#define INIT_READDIR64
1330#endif
1331
Evgeniy Stepanov341b9e62013-06-28 11:02:43 +00001332#if SANITIZER_INTERCEPT_PTRACE
1333INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
1334 void *ctx;
1335 COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
1336
1337 if (data) {
1338 if (request == ptrace_setregs)
1339 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
1340 else if (request == ptrace_setfpregs)
1341 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1342 else if (request == ptrace_setfpxregs)
1343 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1344 else if (request == ptrace_setsiginfo)
1345 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
1346 else if (request == ptrace_setregset) {
1347 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1348 COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
1349 }
1350 }
1351
1352 uptr res = REAL(ptrace)(request, pid, addr, data);
1353
1354 if (!res && data) {
1355 // Note that PEEK* requests assing different meaning to the return value.
1356 // This function does not handle them (nor does it need to).
1357 if (request == ptrace_getregs)
1358 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
1359 else if (request == ptrace_getfpregs)
1360 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
1361 else if (request == ptrace_getfpxregs)
1362 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
1363 else if (request == ptrace_getsiginfo)
1364 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
1365 else if (request == ptrace_getregset) {
1366 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
1367 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
1368 }
1369 }
1370 return res;
1371}
1372
1373#define INIT_PTRACE \
1374 INTERCEPT_FUNCTION(ptrace);
1375#else
1376#define INIT_PTRACE
1377#endif
1378
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001379
Evgeniy Stepanov56d34722013-05-21 08:12:08 +00001380#define SANITIZER_COMMON_INTERCEPTORS_INIT \
1381 INIT_STRCASECMP; \
1382 INIT_STRNCASECMP; \
1383 INIT_READ; \
1384 INIT_PREAD; \
1385 INIT_PREAD64; \
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +00001386 INIT_READV; \
1387 INIT_PREADV; \
1388 INIT_PREADV64; \
Evgeniy Stepanov56d34722013-05-21 08:12:08 +00001389 INIT_WRITE; \
1390 INIT_PWRITE; \
1391 INIT_PWRITE64; \
Evgeniy Stepanovb916e6a2013-06-24 10:43:23 +00001392 INIT_WRITEV; \
1393 INIT_PWRITEV; \
1394 INIT_PWRITEV64; \
1395 INIT_PRCTL; \
Evgeniy Stepanov56d34722013-05-21 08:12:08 +00001396 INIT_LOCALTIME_AND_FRIENDS; \
1397 INIT_SCANF; \
1398 INIT_FREXP; \
1399 INIT_FREXPF_FREXPL; \
1400 INIT_GETPWNAM_AND_FRIENDS; \
1401 INIT_GETPWNAM_R_AND_FRIENDS; \
1402 INIT_CLOCK_GETTIME; \
1403 INIT_GETITIMER; \
1404 INIT_TIME; \
1405 INIT_GLOB; \
1406 INIT_WAIT; \
1407 INIT_INET; \
Evgeniy Stepanov447ef192013-05-22 12:50:26 +00001408 INIT_PTHREAD_GETSCHEDPARAM; \
Evgeniy Stepanov9f58c5c2013-05-22 13:46:22 +00001409 INIT_GETADDRINFO; \
Evgeniy Stepanov0a2cc372013-05-23 11:10:23 +00001410 INIT_GETSOCKNAME; \
1411 INIT_GETHOSTBYNAME; \
Evgeniy Stepanovf32be422013-05-23 11:38:08 +00001412 INIT_GETHOSTBYNAME_R; \
Evgeniy Stepanov9d1525e2013-05-29 09:09:58 +00001413 INIT_GETSOCKOPT; \
1414 INIT_ACCEPT; \
Evgeniy Stepanovc87088b2013-05-29 10:03:11 +00001415 INIT_ACCEPT4; \
Evgeniy Stepanov9666d892013-05-29 11:30:00 +00001416 INIT_MODF; \
Evgeniy Stepanovbc33e132013-05-29 11:49:25 +00001417 INIT_RECVMSG; \
Evgeniy Stepanov745dd0d2013-06-07 13:00:47 +00001418 INIT_GETPEERNAME; \
Evgeniy Stepanov9d600872013-06-24 13:56:14 +00001419 INIT_IOCTL; \
Evgeniy Stepanov359d7fc2013-06-24 14:25:33 +00001420 INIT_INET_ATON; \
Evgeniy Stepanovb5cf98f2013-06-26 15:00:53 +00001421 INIT_SYSINFO; \
1422 INIT_READDIR; \
Evgeniy Stepanov341b9e62013-06-28 11:02:43 +00001423 INIT_READDIR64; \
1424 INIT_PTRACE;