1//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Common function interceptors for tools like AddressSanitizer,
10// ThreadSanitizer, MemorySanitizer, etc.
11//
12// This file should be included into the tool's interceptor file,
13// which has to define its own macros:
14//   COMMON_INTERCEPTOR_ENTER
15//   COMMON_INTERCEPTOR_ENTER_NOIGNORE
16//   COMMON_INTERCEPTOR_READ_RANGE
17//   COMMON_INTERCEPTOR_WRITE_RANGE
18//   COMMON_INTERCEPTOR_INITIALIZE_RANGE
19//   COMMON_INTERCEPTOR_DIR_ACQUIRE
20//   COMMON_INTERCEPTOR_FD_ACQUIRE
21//   COMMON_INTERCEPTOR_FD_RELEASE
22//   COMMON_INTERCEPTOR_FD_ACCESS
23//   COMMON_INTERCEPTOR_SET_THREAD_NAME
24//   COMMON_INTERCEPTOR_DLOPEN
25//   COMMON_INTERCEPTOR_ON_EXIT
26//   COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
27//   COMMON_INTERCEPTOR_MUTEX_POST_LOCK
28//   COMMON_INTERCEPTOR_MUTEX_UNLOCK
29//   COMMON_INTERCEPTOR_MUTEX_REPAIR
30//   COMMON_INTERCEPTOR_SET_PTHREAD_NAME
31//   COMMON_INTERCEPTOR_HANDLE_RECVMSG
32//   COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
33//   COMMON_INTERCEPTOR_MEMSET_IMPL
34//   COMMON_INTERCEPTOR_MEMMOVE_IMPL
35//   COMMON_INTERCEPTOR_MEMCPY_IMPL
36//   COMMON_INTERCEPTOR_MMAP_IMPL
37//   COMMON_INTERCEPTOR_COPY_STRING
38//   COMMON_INTERCEPTOR_STRNDUP_IMPL
39//   COMMON_INTERCEPTOR_STRERROR
40//===----------------------------------------------------------------------===//
41
42#include "interception/interception.h"
43#include "sanitizer_addrhashmap.h"
44#include "sanitizer_errno.h"
45#include "sanitizer_placement_new.h"
46#include "sanitizer_platform_interceptors.h"
47#include "sanitizer_symbolizer.h"
48#include "sanitizer_tls_get_addr.h"
49
50#include <stdarg.h>
51
52#if SANITIZER_INTERCEPTOR_HOOKS
53#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
54#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
55  SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
56#else
57#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
58#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)
59
60#endif  // SANITIZER_INTERCEPTOR_HOOKS
61
62#if SANITIZER_WINDOWS && !defined(va_copy)
63#define va_copy(dst, src) ((dst) = (src))
64#endif // _WIN32
65
66#if SANITIZER_FREEBSD
67#define pthread_setname_np pthread_set_name_np
68#define inet_aton __inet_aton
69#define inet_pton __inet_pton
70#define iconv __bsd_iconv
71#endif
72
73#if SANITIZER_NETBSD
74#define clock_getres __clock_getres50
75#define clock_gettime __clock_gettime50
76#define clock_settime __clock_settime50
77#define ctime __ctime50
78#define ctime_r __ctime_r50
79#define devname __devname50
80#define fgetpos __fgetpos50
81#define fsetpos __fsetpos50
82#define fstatvfs __fstatvfs90
83#define fstatvfs1 __fstatvfs190
84#define fts_children __fts_children60
85#define fts_close __fts_close60
86#define fts_open __fts_open60
87#define fts_read __fts_read60
88#define fts_set __fts_set60
89#define getitimer __getitimer50
90#define getmntinfo __getmntinfo90
91#define getpwent __getpwent50
92#define getpwnam __getpwnam50
93#define getpwnam_r __getpwnam_r50
94#define getpwuid __getpwuid50
95#define getpwuid_r __getpwuid_r50
96#define getutent __getutent50
97#define getutxent __getutxent50
98#define getutxid __getutxid50
99#define getutxline __getutxline50
100#define getvfsstat __getvfsstat90
101#define pututxline __pututxline50
102#define glob __glob30
103#define gmtime __gmtime50
104#define gmtime_r __gmtime_r50
105#define localtime __locatime50
106#define localtime_r __localtime_r50
107#define mktime __mktime50
108#define lstat __lstat50
109#define opendir __opendir30
110#define readdir __readdir30
111#define readdir_r __readdir_r30
112#define scandir __scandir30
113#define setitimer __setitimer50
114#define setlocale __setlocale50
115#define shmctl __shmctl50
116#define sigaltstack __sigaltstack14
117#define sigemptyset __sigemptyset14
118#define sigfillset __sigfillset14
119#define sigpending __sigpending14
120#define sigprocmask __sigprocmask14
121#define sigtimedwait __sigtimedwait50
122#define stat __stat50
123#define statvfs __statvfs90
124#define statvfs1 __statvfs190
125#define time __time50
126#define times __times13
127#define unvis __unvis50
128#define wait3 __wait350
129#define wait4 __wait450
130extern const unsigned short *_ctype_tab_;
131extern const short *_toupper_tab_;
132extern const short *_tolower_tab_;
133#endif
134
135#if SANITIZER_MUSL && \
136  (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
137// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
138// time-related functions that take 64-bit time_t values.  See
139// https://musl.libc.org/time64.html
140#define adjtime __adjtime64
141#define adjtimex __adjtimex_time64
142#define aio_suspend __aio_suspend_time64
143#define clock_adjtime __clock_adjtime64
144#define clock_getres __clock_getres_time64
145#define clock_gettime __clock_gettime64
146#define clock_nanosleep __clock_nanosleep_time64
147#define clock_settime __clock_settime64
148#define cnd_timedwait __cnd_timedwait_time64
149#define ctime __ctime64
150#define ctime_r __ctime64_r
151#define difftime __difftime64
152#define dlsym __dlsym_time64
153#define fstatat __fstatat_time64
154#define fstat __fstat_time64
155#define ftime __ftime64
156#define futimens __futimens_time64
157#define futimesat __futimesat_time64
158#define futimes __futimes_time64
159#define getitimer __getitimer_time64
160#define getrusage __getrusage_time64
161#define gettimeofday __gettimeofday_time64
162#define gmtime __gmtime64
163#define gmtime_r __gmtime64_r
164#define localtime __localtime64
165#define localtime_r __localtime64_r
166#define lstat __lstat_time64
167#define lutimes __lutimes_time64
168#define mktime __mktime64
169#define mq_timedreceive __mq_timedreceive_time64
170#define mq_timedsend __mq_timedsend_time64
171#define mtx_timedlock __mtx_timedlock_time64
172#define nanosleep __nanosleep_time64
173#define ppoll __ppoll_time64
174#define pselect __pselect_time64
175#define pthread_cond_timedwait __pthread_cond_timedwait_time64
176#define pthread_mutex_timedlock __pthread_mutex_timedlock_time64
177#define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_time64
178#define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_time64
179#define pthread_timedjoin_np __pthread_timedjoin_np_time64
180#define recvmmsg __recvmmsg_time64
181#define sched_rr_get_interval __sched_rr_get_interval_time64
182#define select __select_time64
183#define semtimedop __semtimedop_time64
184#define sem_timedwait __sem_timedwait_time64
185#define setitimer __setitimer_time64
186#define settimeofday __settimeofday_time64
187#define sigtimedwait __sigtimedwait_time64
188#define stat __stat_time64
189#define stime __stime64
190#define thrd_sleep __thrd_sleep_time64
191#define timegm __timegm_time64
192#define timerfd_gettime __timerfd_gettime64
193#define timerfd_settime __timerfd_settime64
194#define timer_gettime __timer_gettime64
195#define timer_settime __timer_settime64
196#define timespec_get __timespec_get_time64
197#define time __time64
198#define utimensat __utimensat_time64
199#define utimes __utimes_time64
200#define utime __utime64
201#define wait3 __wait3_time64
202#define wait4 __wait4_time64
203#endif
204
205// Platform-specific options.
206#if SANITIZER_APPLE
207#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
208#elif SANITIZER_WINDOWS64
209#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
210#else
211#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
212#endif  // SANITIZER_APPLE
213
214#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
215#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
216#endif
217
218#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
219#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
220#endif
221
222#ifndef COMMON_INTERCEPTOR_FD_ACCESS
223#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
224#endif
225
226#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
227#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
228#endif
229
230#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
231#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
232#endif
233
234#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
235#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
236#endif
237
238#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
239#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
240#endif
241
242#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
243#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
244#endif
245
246#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
247#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
248#endif
249
250#ifndef COMMON_INTERCEPTOR_FILE_OPEN
251#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
252#endif
253
254#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
255#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
256#endif
257
258#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
259#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
260#endif
261
262#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
263#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
264#endif
265
266#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
267#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
268  COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
269#endif
270
271#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
272#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
273#endif
274
275#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n)                   \
276    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
277      common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )
278
279#ifndef COMMON_INTERCEPTOR_DLOPEN
280#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
281  ({ CheckNoDeepBind(filename, flag); REAL(dlopen)(filename, flag); })
282#endif
283
284#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
285#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
286#endif
287
288#ifndef COMMON_INTERCEPTOR_ACQUIRE
289#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
290#endif
291
292#ifndef COMMON_INTERCEPTOR_RELEASE
293#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
294#endif
295
296#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
297#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
298#endif
299
300#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
301#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
302#endif
303
304#ifdef SANITIZER_NLDBL_VERSION
305#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
306    COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
307#else
308#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
309    COMMON_INTERCEPT_FUNCTION(fn)
310#endif
311
312#if SANITIZER_GLIBC
313// If we could not find the versioned symbol, fall back to an unversioned
314// lookup. This is needed to work around a GLibc bug that causes dlsym
315// with RTLD_NEXT to return the oldest versioned symbol.
316// See https://sourceware.org/bugzilla/show_bug.cgi?id=14932.
317// For certain symbols (e.g. regexec) we have to perform a versioned lookup,
318// but that versioned symbol will only exist for architectures where the
319// oldest Glibc version pre-dates support for that architecture.
320// For example, regexec@GLIBC_2.3.4 exists on x86_64, but not RISC-V.
321// See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920.
322#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
323  COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver)
324#else
325#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
326  COMMON_INTERCEPT_FUNCTION(fn)
327#endif
328
329#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
330#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
331  {                                                       \
332    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)        \
333      return internal_memset(dst, v, size);               \
334    COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);  \
335    if (common_flags()->intercept_intrin)                 \
336      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);     \
337    return REAL(memset)(dst, v, size);                    \
338  }
339#endif
340
341#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
342#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
343  {                                                          \
344    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)           \
345      return internal_memmove(dst, src, size);               \
346    COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);  \
347    if (common_flags()->intercept_intrin) {                  \
348      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);        \
349      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);         \
350    }                                                        \
351    return REAL(memmove)(dst, src, size);                    \
352  }
353#endif
354
355#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
356#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
357  {                                                         \
358    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {        \
359      return internal_memmove(dst, src, size);              \
360    }                                                       \
361    COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);  \
362    if (common_flags()->intercept_intrin) {                 \
363      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);       \
364      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);        \
365    }                                                       \
366    return REAL(memcpy)(dst, src, size);                    \
367  }
368#endif
369
370#ifndef COMMON_INTERCEPTOR_MMAP_IMPL
371#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
372                                     off)                                  \
373  { return REAL(mmap)(addr, sz, prot, flags, fd, off); }
374#endif
375
376#ifndef COMMON_INTERCEPTOR_COPY_STRING
377#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
378#endif
379
380#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
381#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size)                         \
382  COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size);                            \
383  uptr copy_length = internal_strnlen(s, size);                               \
384  char *new_mem = (char *)WRAP(malloc)(copy_length + 1);                      \
385  if (common_flags()->intercept_strndup) {                                    \
386    COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1));       \
387  }                                                                           \
388  if (new_mem) {                                                              \
389    COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);             \
390    internal_memcpy(new_mem, s, copy_length);                                 \
391    new_mem[copy_length] = '\0';                                              \
392  }                                                                           \
393  return new_mem;
394#endif
395
396#ifndef COMMON_INTERCEPTOR_STRERROR
397#define COMMON_INTERCEPTOR_STRERROR() {}
398#endif
399
400struct FileMetadata {
401  // For open_memstream().
402  char **addr;
403  SIZE_T *size;
404};
405
406struct CommonInterceptorMetadata {
407  enum {
408    CIMT_INVALID = 0,
409    CIMT_FILE
410  } type;
411  union {
412    FileMetadata file;
413  };
414};
415
416#if SI_POSIX
417typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
418
419static MetadataHashMap *interceptor_metadata_map;
420
421UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
422                                          const FileMetadata &file) {
423  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
424  CHECK(h.created());
425  h->type = CommonInterceptorMetadata::CIMT_FILE;
426  h->file = file;
427}
428
429UNUSED static const FileMetadata *GetInterceptorMetadata(
430    __sanitizer_FILE *addr) {
431  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
432                            /* remove */ false,
433                            /* create */ false);
434  if (addr && h.exists()) {
435    CHECK(!h.created());
436    CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
437    return &h->file;
438  } else {
439    return 0;
440  }
441}
442
443UNUSED static void DeleteInterceptorMetadata(void *addr) {
444  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
445  CHECK(h.exists());
446}
447#endif  // SI_POSIX
448
449#if SANITIZER_INTERCEPT_STRLEN
450INTERCEPTOR(SIZE_T, strlen, const char *s) {
451  // Sometimes strlen is called prior to InitializeCommonInterceptors,
452  // in which case the REAL(strlen) typically used in
453  // COMMON_INTERCEPTOR_ENTER will fail.  We use internal_strlen here
454  // to handle that.
455  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
456    return internal_strlen(s);
457  void *ctx;
458  COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
459  SIZE_T result = REAL(strlen)(s);
460  if (common_flags()->intercept_strlen)
461    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
462  return result;
463}
464#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
465#else
466#define INIT_STRLEN
467#endif
468
469#if SANITIZER_INTERCEPT_STRNLEN
470INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
471  void *ctx;
472  COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
473  SIZE_T length = REAL(strnlen)(s, maxlen);
474  if (common_flags()->intercept_strlen)
475    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
476  return length;
477}
478#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
479#else
480#define INIT_STRNLEN
481#endif
482
483#if SANITIZER_INTERCEPT_STRNDUP
484INTERCEPTOR(char*, strndup, const char *s, uptr size) {
485  void *ctx;
486  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
487}
488#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
489#else
490#define INIT_STRNDUP
491#endif // SANITIZER_INTERCEPT_STRNDUP
492
493#if SANITIZER_INTERCEPT___STRNDUP
494INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
495  void *ctx;
496  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
497}
498#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
499#else
500#define INIT___STRNDUP
501#endif // SANITIZER_INTERCEPT___STRNDUP
502
503#if SANITIZER_INTERCEPT_TEXTDOMAIN
504INTERCEPTOR(char*, textdomain, const char *domainname) {
505  void *ctx;
506  COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
507  if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
508  char *domain = REAL(textdomain)(domainname);
509  if (domain) {
510    COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, internal_strlen(domain) + 1);
511  }
512  return domain;
513}
514#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
515#else
516#define INIT_TEXTDOMAIN
517#endif
518
519#if SANITIZER_INTERCEPT_STRCMP
520static inline int CharCmpX(unsigned char c1, unsigned char c2) {
521  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
522}
523
524DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
525                              const char *s1, const char *s2, int result)
526
527INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
528  void *ctx;
529  COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
530  unsigned char c1, c2;
531  uptr i;
532  for (i = 0;; i++) {
533    c1 = (unsigned char)s1[i];
534    c2 = (unsigned char)s2[i];
535    if (c1 != c2 || c1 == '\0') break;
536  }
537  if (common_flags()->intercept_strcmp) {
538    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
539    COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
540  }
541  int result = CharCmpX(c1, c2);
542  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
543                             s2, result);
544  return result;
545}
546
547DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
548                              const char *s1, const char *s2, uptr n,
549                              int result)
550
551INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
552  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
553    return internal_strncmp(s1, s2, size);
554  void *ctx;
555  COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
556  unsigned char c1 = 0, c2 = 0;
557  uptr i;
558  for (i = 0; i < size; i++) {
559    c1 = (unsigned char)s1[i];
560    c2 = (unsigned char)s2[i];
561    if (c1 != c2 || c1 == '\0') break;
562  }
563  uptr i1 = i;
564  uptr i2 = i;
565  if (common_flags()->strict_string_checks) {
566    for (; i1 < size && s1[i1]; i1++) {}
567    for (; i2 < size && s2[i2]; i2++) {}
568  }
569  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
570  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
571  int result = CharCmpX(c1, c2);
572  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
573                             s2, size, result);
574  return result;
575}
576
577#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
578#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
579#else
580#define INIT_STRCMP
581#define INIT_STRNCMP
582#endif
583
584#if SANITIZER_INTERCEPT_STRCASECMP
585static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
586  int c1_low = ToLower(c1);
587  int c2_low = ToLower(c2);
588  return c1_low - c2_low;
589}
590
591DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
592                              const char *s1, const char *s2, int result)
593
594INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
595  void *ctx;
596  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
597  unsigned char c1 = 0, c2 = 0;
598  uptr i;
599  for (i = 0;; i++) {
600    c1 = (unsigned char)s1[i];
601    c2 = (unsigned char)s2[i];
602    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
603  }
604  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
605  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
606  int result = CharCaseCmp(c1, c2);
607  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
608                             s1, s2, result);
609  return result;
610}
611
612DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
613                              const char *s1, const char *s2, uptr size,
614                              int result)
615
616INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
617  void *ctx;
618  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
619  unsigned char c1 = 0, c2 = 0;
620  uptr i;
621  for (i = 0; i < size; i++) {
622    c1 = (unsigned char)s1[i];
623    c2 = (unsigned char)s2[i];
624    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
625  }
626  uptr i1 = i;
627  uptr i2 = i;
628  if (common_flags()->strict_string_checks) {
629    for (; i1 < size && s1[i1]; i1++) {}
630    for (; i2 < size && s2[i2]; i2++) {}
631  }
632  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
633  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
634  int result = CharCaseCmp(c1, c2);
635  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
636                             s1, s2, size, result);
637  return result;
638}
639
640#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
641#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
642#else
643#define INIT_STRCASECMP
644#define INIT_STRNCASECMP
645#endif
646
647#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
648static inline void StrstrCheck(void *ctx, char *r, const char *s1,
649                               const char *s2) {
650    uptr len1 = internal_strlen(s1);
651    uptr len2 = internal_strlen(s2);
652    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
653    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
654}
655#endif
656
657#if SANITIZER_INTERCEPT_STRSTR
658
659DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
660                              const char *s1, const char *s2, char *result)
661
662INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
663  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
664    return internal_strstr(s1, s2);
665  void *ctx;
666  COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
667  char *r = REAL(strstr)(s1, s2);
668  if (common_flags()->intercept_strstr)
669    StrstrCheck(ctx, r, s1, s2);
670  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
671                             s2, r);
672  return r;
673}
674
675#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
676#else
677#define INIT_STRSTR
678#endif
679
680#if SANITIZER_INTERCEPT_STRCASESTR
681
682DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
683                              const char *s1, const char *s2, char *result)
684
685INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
686  void *ctx;
687  COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
688  char *r = REAL(strcasestr)(s1, s2);
689  if (common_flags()->intercept_strstr)
690    StrstrCheck(ctx, r, s1, s2);
691  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
692                             s1, s2, r);
693  return r;
694}
695
696#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
697#else
698#define INIT_STRCASESTR
699#endif
700
701#if SANITIZER_INTERCEPT_STRTOK
702
703INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
704  void *ctx;
705  COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
706  if (!common_flags()->intercept_strtok) {
707    return REAL(strtok)(str, delimiters);
708  }
709  if (common_flags()->strict_string_checks) {
710    // If strict_string_checks is enabled, we check the whole first argument
711    // string on the first call (strtok saves this string in a static buffer
712    // for subsequent calls). We do not need to check strtok's result.
713    // As the delimiters can change, we check them every call.
714    if (str != nullptr) {
715      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
716    }
717    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
718                                  internal_strlen(delimiters) + 1);
719    return REAL(strtok)(str, delimiters);
720  } else {
721    // However, when strict_string_checks is disabled we cannot check the
722    // whole string on the first call. Instead, we check the result string
723    // which is guaranteed to be a NULL-terminated substring of the first
724    // argument. We also conservatively check one character of str and the
725    // delimiters.
726    if (str != nullptr) {
727      COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
728    }
729    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
730    char *result = REAL(strtok)(str, delimiters);
731    if (result != nullptr) {
732      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, internal_strlen(result) + 1);
733    } else if (str != nullptr) {
734      // No delimiter were found, it's safe to assume that the entire str was
735      // scanned.
736      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
737    }
738    return result;
739  }
740}
741
742#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
743#else
744#define INIT_STRTOK
745#endif
746
747#if SANITIZER_INTERCEPT_MEMMEM
748DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
749                              const void *s1, SIZE_T len1, const void *s2,
750                              SIZE_T len2, void *result)
751
752INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
753            SIZE_T len2) {
754  void *ctx;
755  COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
756  void *r = REAL(memmem)(s1, len1, s2, len2);
757  if (common_flags()->intercept_memmem) {
758    COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
759    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
760  }
761  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
762                             s1, len1, s2, len2, r);
763  return r;
764}
765
766#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
767#else
768#define INIT_MEMMEM
769#endif  // SANITIZER_INTERCEPT_MEMMEM
770
771#if SANITIZER_INTERCEPT_STRCHR
772INTERCEPTOR(char*, strchr, const char *s, int c) {
773  void *ctx;
774  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
775    return internal_strchr(s, c);
776  COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
777  char *result = REAL(strchr)(s, c);
778  if (common_flags()->intercept_strchr) {
779    // Keep strlen as macro argument, as macro may ignore it.
780    COMMON_INTERCEPTOR_READ_STRING(ctx, s,
781      (result ? result - s : internal_strlen(s)) + 1);
782  }
783  return result;
784}
785#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
786#else
787#define INIT_STRCHR
788#endif
789
790#if SANITIZER_INTERCEPT_STRCHRNUL
791INTERCEPTOR(char*, strchrnul, const char *s, int c) {
792  void *ctx;
793  COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
794  char *result = REAL(strchrnul)(s, c);
795  uptr len = result - s + 1;
796  if (common_flags()->intercept_strchr)
797    COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
798  return result;
799}
800#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
801#else
802#define INIT_STRCHRNUL
803#endif
804
805#if SANITIZER_INTERCEPT_STRRCHR
806INTERCEPTOR(char*, strrchr, const char *s, int c) {
807  void *ctx;
808  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
809    return internal_strrchr(s, c);
810  COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
811  if (common_flags()->intercept_strchr)
812    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
813  return REAL(strrchr)(s, c);
814}
815#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
816#else
817#define INIT_STRRCHR
818#endif
819
820#if SANITIZER_INTERCEPT_STRSPN
821INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
822  void *ctx;
823  COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
824  SIZE_T r = REAL(strspn)(s1, s2);
825  if (common_flags()->intercept_strspn) {
826    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
827    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
828  }
829  return r;
830}
831
832INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
833  void *ctx;
834  COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
835  SIZE_T r = REAL(strcspn)(s1, s2);
836  if (common_flags()->intercept_strspn) {
837    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
838    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
839  }
840  return r;
841}
842
843#define INIT_STRSPN \
844  COMMON_INTERCEPT_FUNCTION(strspn); \
845  COMMON_INTERCEPT_FUNCTION(strcspn);
846#else
847#define INIT_STRSPN
848#endif
849
850#if SANITIZER_INTERCEPT_STRPBRK
851INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
852  void *ctx;
853  COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
854  char *r = REAL(strpbrk)(s1, s2);
855  if (common_flags()->intercept_strpbrk) {
856    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
857    COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
858        r ? r - s1 + 1 : internal_strlen(s1) + 1);
859  }
860  return r;
861}
862
863#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
864#else
865#define INIT_STRPBRK
866#endif
867
868#if SANITIZER_INTERCEPT_MEMSET
869INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
870  void *ctx;
871  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
872}
873
874#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
875#else
876#define INIT_MEMSET
877#endif
878
879#if SANITIZER_INTERCEPT_MEMMOVE
880INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
881  void *ctx;
882  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
883}
884
885#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
886#else
887#define INIT_MEMMOVE
888#endif
889
890#if SANITIZER_INTERCEPT_MEMCPY
891INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
892  // On OS X, calling internal_memcpy here will cause memory corruptions,
893  // because memcpy and memmove are actually aliases of the same
894  // implementation.  We need to use internal_memmove here.
895  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
896  // due to memcpy being an alias of memmove on OS X.
897  void *ctx;
898#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
899    COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
900#else
901    COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
902#endif
903}
904
905#define INIT_MEMCPY                                  \
906  do {                                               \
907    if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
908      COMMON_INTERCEPT_FUNCTION(memcpy);             \
909    } else {                                         \
910      ASSIGN_REAL(memcpy, memmove);                  \
911    }                                                \
912    CHECK(REAL(memcpy));                             \
913  } while (false)
914
915#else
916#define INIT_MEMCPY
917#endif
918
919#if SANITIZER_INTERCEPT_MEMCMP
920DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
921                              const void *s1, const void *s2, uptr n,
922                              int result)
923
924// Common code for `memcmp` and `bcmp`.
925int MemcmpInterceptorCommon(void *ctx,
926                            int (*real_fn)(const void *, const void *, uptr),
927                            const void *a1, const void *a2, uptr size) {
928  if (common_flags()->intercept_memcmp) {
929    if (common_flags()->strict_memcmp) {
930      // Check the entire regions even if the first bytes of the buffers are
931      // different.
932      COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
933      COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
934      // Fallthrough to REAL(memcmp) below.
935    } else {
936      unsigned char c1 = 0, c2 = 0;
937      const unsigned char *s1 = (const unsigned char*)a1;
938      const unsigned char *s2 = (const unsigned char*)a2;
939      uptr i;
940      for (i = 0; i < size; i++) {
941        c1 = s1[i];
942        c2 = s2[i];
943        if (c1 != c2) break;
944      }
945      COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
946      COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
947      int r = CharCmpX(c1, c2);
948      CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
949                                 a1, a2, size, r);
950      return r;
951    }
952  }
953  int result = real_fn(a1, a2, size);
954  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
955                             a2, size, result);
956  return result;
957}
958
959INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
960  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
961    return internal_memcmp(a1, a2, size);
962  void *ctx;
963  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
964  return MemcmpInterceptorCommon(ctx, REAL(memcmp), a1, a2, size);
965}
966
967#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
968#else
969#define INIT_MEMCMP
970#endif
971
972#if SANITIZER_INTERCEPT_BCMP
973INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {
974  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
975    return internal_memcmp(a1, a2, size);
976  void *ctx;
977  COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size);
978  return MemcmpInterceptorCommon(ctx, REAL(bcmp), a1, a2, size);
979}
980
981#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp)
982#else
983#define INIT_BCMP
984#endif
985
986#if SANITIZER_INTERCEPT_MEMCHR
987INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
988  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
989    return internal_memchr(s, c, n);
990  void *ctx;
991  COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
992#if SANITIZER_WINDOWS
993  void *res;
994  if (REAL(memchr)) {
995    res = REAL(memchr)(s, c, n);
996  } else {
997    res = internal_memchr(s, c, n);
998  }
999#else
1000  void *res = REAL(memchr)(s, c, n);
1001#endif
1002  uptr len = res ? (char *)res - (const char *)s + 1 : n;
1003  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
1004  return res;
1005}
1006
1007#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
1008#else
1009#define INIT_MEMCHR
1010#endif
1011
1012#if SANITIZER_INTERCEPT_MEMRCHR
1013INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
1014  void *ctx;
1015  COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
1016  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
1017  return REAL(memrchr)(s, c, n);
1018}
1019
1020#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
1021#else
1022#define INIT_MEMRCHR
1023#endif
1024
1025#if SANITIZER_INTERCEPT_FREXP
1026INTERCEPTOR(double, frexp, double x, int *exp) {
1027  void *ctx;
1028  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
1029  // Assuming frexp() always writes to |exp|.
1030  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
1031  double res = REAL(frexp)(x, exp);
1032  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
1033  return res;
1034}
1035
1036#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
1037#else
1038#define INIT_FREXP
1039#endif  // SANITIZER_INTERCEPT_FREXP
1040
1041#if SANITIZER_INTERCEPT_FREXPF_FREXPL
1042INTERCEPTOR(float, frexpf, float x, int *exp) {
1043  void *ctx;
1044  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
1045  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
1046  float res = REAL(frexpf)(x, exp);
1047  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
1048  return res;
1049}
1050
1051INTERCEPTOR(long double, frexpl, long double x, int *exp) {
1052  void *ctx;
1053  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
1054  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
1055  long double res = REAL(frexpl)(x, exp);
1056  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
1057  return res;
1058}
1059
1060#define INIT_FREXPF_FREXPL           \
1061  COMMON_INTERCEPT_FUNCTION(frexpf); \
1062  COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
1063#else
1064#define INIT_FREXPF_FREXPL
1065#endif  // SANITIZER_INTERCEPT_FREXPF_FREXPL
1066
1067#if SI_POSIX
1068static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
1069                        SIZE_T iovlen, SIZE_T maxlen) {
1070  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
1071    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
1072    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
1073    maxlen -= sz;
1074  }
1075}
1076
1077static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
1078                       SIZE_T iovlen, SIZE_T maxlen) {
1079  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
1080  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
1081    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
1082    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
1083    maxlen -= sz;
1084  }
1085}
1086#endif
1087
1088#if SANITIZER_INTERCEPT_READ
1089INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
1090  void *ctx;
1091  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
1092  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1093  // FIXME: under ASan the call below may write to freed memory and corrupt
1094  // its metadata. See
1095  // https://github.com/google/sanitizers/issues/321.
1096  SSIZE_T res = REAL(read)(fd, ptr, count);
1097  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
1098  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1099  return res;
1100}
1101#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
1102#else
1103#define INIT_READ
1104#endif
1105
1106#if SANITIZER_INTERCEPT_FREAD
1107INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
1108  // libc file streams can call user-supplied functions, see fopencookie.
1109  void *ctx;
1110  COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
1111  // FIXME: under ASan the call below may write to freed memory and corrupt
1112  // its metadata. See
1113  // https://github.com/google/sanitizers/issues/321.
1114  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
1115  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
1116  return res;
1117}
1118#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
1119#else
1120#define INIT_FREAD
1121#endif
1122
1123#if SANITIZER_INTERCEPT_PREAD
1124INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
1125  void *ctx;
1126  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
1127  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1128  // FIXME: under ASan the call below may write to freed memory and corrupt
1129  // its metadata. See
1130  // https://github.com/google/sanitizers/issues/321.
1131  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
1132  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
1133  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1134  return res;
1135}
1136#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
1137#else
1138#define INIT_PREAD
1139#endif
1140
1141#if SANITIZER_INTERCEPT_PREAD64
1142INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
1143  void *ctx;
1144  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
1145  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1146  // FIXME: under ASan the call below may write to freed memory and corrupt
1147  // its metadata. See
1148  // https://github.com/google/sanitizers/issues/321.
1149  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
1150  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
1151  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1152  return res;
1153}
1154#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
1155#else
1156#define INIT_PREAD64
1157#endif
1158
1159#if SANITIZER_INTERCEPT_READV
1160INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
1161                        int iovcnt) {
1162  void *ctx;
1163  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
1164  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1165  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
1166  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
1167  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1168  return res;
1169}
1170#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
1171#else
1172#define INIT_READV
1173#endif
1174
1175#if SANITIZER_INTERCEPT_PREADV
1176INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
1177            OFF_T offset) {
1178  void *ctx;
1179  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
1180  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1181  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
1182  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
1183  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1184  return res;
1185}
1186#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
1187#else
1188#define INIT_PREADV
1189#endif
1190
1191#if SANITIZER_INTERCEPT_PREADV64
1192INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
1193            OFF64_T offset) {
1194  void *ctx;
1195  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
1196  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1197  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
1198  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
1199  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1200  return res;
1201}
1202#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
1203#else
1204#define INIT_PREADV64
1205#endif
1206
1207#if SANITIZER_INTERCEPT_WRITE
1208INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
1209  void *ctx;
1210  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
1211  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1212  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1213  SSIZE_T res = REAL(write)(fd, ptr, count);
1214  // FIXME: this check should be _before_ the call to REAL(write), not after
1215  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
1216  return res;
1217}
1218#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
1219#else
1220#define INIT_WRITE
1221#endif
1222
1223#if SANITIZER_INTERCEPT_FWRITE
1224INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
1225  // libc file streams can call user-supplied functions, see fopencookie.
1226  void *ctx;
1227  COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
1228  SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
1229  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
1230  return res;
1231}
1232#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
1233#else
1234#define INIT_FWRITE
1235#endif
1236
1237#if SANITIZER_INTERCEPT_PWRITE
1238INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
1239  void *ctx;
1240  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
1241  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1242  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1243  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
1244  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
1245  return res;
1246}
1247#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
1248#else
1249#define INIT_PWRITE
1250#endif
1251
1252#if SANITIZER_INTERCEPT_PWRITE64
1253INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
1254            OFF64_T offset) {
1255  void *ctx;
1256  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
1257  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1258  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1259  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
1260  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
1261  return res;
1262}
1263#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
1264#else
1265#define INIT_PWRITE64
1266#endif
1267
1268#if SANITIZER_INTERCEPT_WRITEV
1269INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
1270                        int iovcnt) {
1271  void *ctx;
1272  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
1273  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1274  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1275  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
1276  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
1277  return res;
1278}
1279#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
1280#else
1281#define INIT_WRITEV
1282#endif
1283
1284#if SANITIZER_INTERCEPT_PWRITEV
1285INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
1286            OFF_T offset) {
1287  void *ctx;
1288  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
1289  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1290  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1291  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
1292  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
1293  return res;
1294}
1295#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
1296#else
1297#define INIT_PWRITEV
1298#endif
1299
1300#if SANITIZER_INTERCEPT_PWRITEV64
1301INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
1302            OFF64_T offset) {
1303  void *ctx;
1304  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
1305  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1306  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1307  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
1308  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
1309  return res;
1310}
1311#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
1312#else
1313#define INIT_PWRITEV64
1314#endif
1315
1316#if SANITIZER_INTERCEPT_FGETS
1317INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
1318  // libc file streams can call user-supplied functions, see fopencookie.
1319  void *ctx;
1320  COMMON_INTERCEPTOR_ENTER(ctx, fgets, s, size, file);
1321  // FIXME: under ASan the call below may write to freed memory and corrupt
1322  // its metadata. See
1323  // https://github.com/google/sanitizers/issues/321.
1324  char *res = REAL(fgets)(s, size, file);
1325  if (res)
1326    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
1327  return res;
1328}
1329#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
1330#else
1331#define INIT_FGETS
1332#endif
1333
1334#if SANITIZER_INTERCEPT_FPUTS
1335INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
1336  // libc file streams can call user-supplied functions, see fopencookie.
1337  void *ctx;
1338  COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
1339  if (!SANITIZER_APPLE || s) {  // `fputs(NULL, file)` is supported on Darwin.
1340    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
1341  }
1342  return REAL(fputs)(s, file);
1343}
1344#define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs)
1345#else
1346#define INIT_FPUTS
1347#endif
1348
1349#if SANITIZER_INTERCEPT_PUTS
1350INTERCEPTOR(int, puts, char *s) {
1351  // libc file streams can call user-supplied functions, see fopencookie.
1352  void *ctx;
1353  COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
1354  if (!SANITIZER_APPLE || s) {  // `puts(NULL)` is supported on Darwin.
1355    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
1356  }
1357  return REAL(puts)(s);
1358}
1359#define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts)
1360#else
1361#define INIT_PUTS
1362#endif
1363
1364#if SANITIZER_INTERCEPT_PRCTL
1365INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1366            unsigned long arg4, unsigned long arg5) {
1367  void *ctx;
1368  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
1369  static const int PR_SET_NAME = 15;
1370  static const int PR_SET_VMA = 0x53564d41;
1371  static const int PR_SCHED_CORE = 62;
1372  static const int PR_SCHED_CORE_GET = 0;
1373  if (option == PR_SET_VMA && arg2 == 0UL) {
1374    char *name = (char *)arg5;
1375    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
1376  }
1377  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
1378  if (option == PR_SET_NAME) {
1379    char buff[16];
1380    internal_strncpy(buff, (char *)arg2, 15);
1381    buff[15] = 0;
1382    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
1383  } else if (res != -1 && option == PR_SCHED_CORE && arg2 == PR_SCHED_CORE_GET) {
1384    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));
1385  }
1386  return res;
1387}
1388#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
1389#else
1390#define INIT_PRCTL
1391#endif  // SANITIZER_INTERCEPT_PRCTL
1392
1393#if SANITIZER_INTERCEPT_TIME
1394INTERCEPTOR(unsigned long, time, unsigned long *t) {
1395  void *ctx;
1396  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
1397  unsigned long local_t;
1398  unsigned long res = REAL(time)(&local_t);
1399  if (t && res != (unsigned long)-1) {
1400    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
1401    *t = local_t;
1402  }
1403  return res;
1404}
1405#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
1406#else
1407#define INIT_TIME
1408#endif  // SANITIZER_INTERCEPT_TIME
1409
1410#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
1411static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
1412  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
1413#if !SANITIZER_SOLARIS
1414  if (tm->tm_zone) {
1415    // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
1416    // can point to shared memory and tsan would report a data race.
1417    COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
1418                                        internal_strlen(tm->tm_zone) + 1);
1419  }
1420#endif
1421}
1422INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
1423  void *ctx;
1424  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
1425  __sanitizer_tm *res = REAL(localtime)(timep);
1426  if (res) {
1427    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1428    unpoison_tm(ctx, res);
1429  }
1430  return res;
1431}
1432INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
1433  void *ctx;
1434  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
1435  __sanitizer_tm *res = REAL(localtime_r)(timep, result);
1436  if (res) {
1437    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1438    unpoison_tm(ctx, res);
1439  }
1440  return res;
1441}
1442INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
1443  void *ctx;
1444  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
1445  __sanitizer_tm *res = REAL(gmtime)(timep);
1446  if (res) {
1447    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1448    unpoison_tm(ctx, res);
1449  }
1450  return res;
1451}
1452INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
1453  void *ctx;
1454  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
1455  __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
1456  if (res) {
1457    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1458    unpoison_tm(ctx, res);
1459  }
1460  return res;
1461}
1462INTERCEPTOR(char *, ctime, unsigned long *timep) {
1463  void *ctx;
1464  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
1465  // FIXME: under ASan the call below may write to freed memory and corrupt
1466  // its metadata. See
1467  // https://github.com/google/sanitizers/issues/321.
1468  char *res = REAL(ctime)(timep);
1469  if (res) {
1470    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1471    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
1472  }
1473  return res;
1474}
1475INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
1476  void *ctx;
1477  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
1478  // FIXME: under ASan the call below may write to freed memory and corrupt
1479  // its metadata. See
1480  // https://github.com/google/sanitizers/issues/321.
1481  char *res = REAL(ctime_r)(timep, result);
1482  if (res) {
1483    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1484    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
1485  }
1486  return res;
1487}
1488INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
1489  void *ctx;
1490  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
1491  // FIXME: under ASan the call below may write to freed memory and corrupt
1492  // its metadata. See
1493  // https://github.com/google/sanitizers/issues/321.
1494  char *res = REAL(asctime)(tm);
1495  if (res) {
1496    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
1497    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
1498  }
1499  return res;
1500}
1501INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
1502  void *ctx;
1503  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
1504  // FIXME: under ASan the call below may write to freed memory and corrupt
1505  // its metadata. See
1506  // https://github.com/google/sanitizers/issues/321.
1507  char *res = REAL(asctime_r)(tm, result);
1508  if (res) {
1509    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
1510    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
1511  }
1512  return res;
1513}
1514INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
1515  void *ctx;
1516  COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
1517  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
1518  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
1519  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
1520  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
1521  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
1522  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
1523  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
1524  long res = REAL(mktime)(tm);
1525  if (res != -1) unpoison_tm(ctx, tm);
1526  return res;
1527}
1528#define INIT_LOCALTIME_AND_FRIENDS        \
1529  COMMON_INTERCEPT_FUNCTION(localtime);   \
1530  COMMON_INTERCEPT_FUNCTION(localtime_r); \
1531  COMMON_INTERCEPT_FUNCTION(gmtime);      \
1532  COMMON_INTERCEPT_FUNCTION(gmtime_r);    \
1533  COMMON_INTERCEPT_FUNCTION(ctime);       \
1534  COMMON_INTERCEPT_FUNCTION(ctime_r);     \
1535  COMMON_INTERCEPT_FUNCTION(asctime);     \
1536  COMMON_INTERCEPT_FUNCTION(asctime_r);   \
1537  COMMON_INTERCEPT_FUNCTION(mktime);
1538#else
1539#define INIT_LOCALTIME_AND_FRIENDS
1540#endif  // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
1541
1542#if SANITIZER_INTERCEPT_STRPTIME
1543INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
1544  void *ctx;
1545  COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
1546  if (format)
1547    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
1548  // FIXME: under ASan the call below may write to freed memory and corrupt
1549  // its metadata. See
1550  // https://github.com/google/sanitizers/issues/321.
1551  char *res = REAL(strptime)(s, format, tm);
1552  COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
1553  if (res && tm) {
1554    // Do not call unpoison_tm here, because strptime does not, in fact,
1555    // initialize the entire struct tm. For example, tm_zone pointer is left
1556    // uninitialized.
1557    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
1558  }
1559  return res;
1560}
1561#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
1562#else
1563#define INIT_STRPTIME
1564#endif
1565
1566#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
1567#include "sanitizer_common_interceptors_format.inc"
1568
1569#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...)                              \
1570  {                                                                            \
1571    void *ctx;                                                                 \
1572    va_list ap;                                                                \
1573    va_start(ap, format);                                                      \
1574    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap);                     \
1575    int res = WRAP(vname)(__VA_ARGS__, ap);                                    \
1576    va_end(ap);                                                                \
1577    return res;                                                                \
1578  }
1579
1580#endif
1581
1582#if SANITIZER_INTERCEPT_SCANF
1583
1584#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
1585  {                                                                            \
1586    void *ctx;                                                                 \
1587    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
1588    va_list aq;                                                                \
1589    va_copy(aq, ap);                                                           \
1590    int res = REAL(vname)(__VA_ARGS__);                                        \
1591    if (res > 0)                                                               \
1592      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
1593    va_end(aq);                                                                \
1594    return res;                                                                \
1595  }
1596
1597INTERCEPTOR(int, vscanf, const char *format, va_list ap)
1598VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
1599
1600INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
1601VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
1602
1603INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
1604VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
1605
1606#if SANITIZER_INTERCEPT_ISOC99_SCANF
1607INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
1608VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
1609
1610INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
1611            va_list ap)
1612VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
1613
1614INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
1615VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
1616#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF
1617
1618INTERCEPTOR(int, scanf, const char *format, ...)
1619FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
1620
1621INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
1622FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
1623
1624INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
1625FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
1626
1627#if SANITIZER_INTERCEPT_ISOC99_SCANF
1628INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
1629FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
1630
1631INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
1632FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
1633
1634INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
1635FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
1636#endif
1637
1638#endif
1639
1640#if SANITIZER_INTERCEPT_SCANF
1641#define INIT_SCANF                    \
1642  COMMON_INTERCEPT_FUNCTION_LDBL(scanf);   \
1643  COMMON_INTERCEPT_FUNCTION_LDBL(sscanf);  \
1644  COMMON_INTERCEPT_FUNCTION_LDBL(fscanf);  \
1645  COMMON_INTERCEPT_FUNCTION_LDBL(vscanf);  \
1646  COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
1647  COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
1648#else
1649#define INIT_SCANF
1650#endif
1651
1652#if SANITIZER_INTERCEPT_ISOC99_SCANF
1653#define INIT_ISOC99_SCANF                      \
1654  COMMON_INTERCEPT_FUNCTION(__isoc99_scanf);   \
1655  COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf);  \
1656  COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf);  \
1657  COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf);  \
1658  COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
1659  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
1660#else
1661#define INIT_ISOC99_SCANF
1662#endif
1663
1664#if SANITIZER_INTERCEPT_PRINTF
1665
1666#define VPRINTF_INTERCEPTOR_ENTER(vname, ...)                                  \
1667  void *ctx;                                                                   \
1668  COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                           \
1669  va_list aq;                                                                  \
1670  va_copy(aq, ap);
1671
1672#define VPRINTF_INTERCEPTOR_RETURN()                                           \
1673  va_end(aq);
1674
1675#define VPRINTF_INTERCEPTOR_IMPL(vname, ...)                                   \
1676  {                                                                            \
1677    VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__);                             \
1678    if (common_flags()->check_printf)                                          \
1679      printf_common(ctx, format, aq);                                          \
1680    int res = REAL(vname)(__VA_ARGS__);                                        \
1681    VPRINTF_INTERCEPTOR_RETURN();                                              \
1682    return res;                                                                \
1683  }
1684
1685// FIXME: under ASan the REAL() call below may write to freed memory and
1686// corrupt its metadata. See
1687// https://github.com/google/sanitizers/issues/321.
1688#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...)                             \
1689  {                                                                            \
1690    VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__)                         \
1691    if (common_flags()->check_printf) {                                        \
1692      printf_common(ctx, format, aq);                                          \
1693    }                                                                          \
1694    int res = REAL(vname)(str, __VA_ARGS__);                                   \
1695    if (res >= 0) {                                                            \
1696      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1);                       \
1697    }                                                                          \
1698    VPRINTF_INTERCEPTOR_RETURN();                                              \
1699    return res;                                                                \
1700  }
1701
1702// FIXME: under ASan the REAL() call below may write to freed memory and
1703// corrupt its metadata. See
1704// https://github.com/google/sanitizers/issues/321.
1705#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...)                      \
1706  {                                                                            \
1707    VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__)                   \
1708    if (common_flags()->check_printf) {                                        \
1709      printf_common(ctx, format, aq);                                          \
1710    }                                                                          \
1711    int res = REAL(vname)(str, size, __VA_ARGS__);                             \
1712    if (res >= 0) {                                                            \
1713      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1)));  \
1714    }                                                                          \
1715    VPRINTF_INTERCEPTOR_RETURN();                                              \
1716    return res;                                                                \
1717  }
1718
1719// FIXME: under ASan the REAL() call below may write to freed memory and
1720// corrupt its metadata. See
1721// https://github.com/google/sanitizers/issues/321.
1722#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...)                           \
1723  {                                                                            \
1724    VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__)                        \
1725    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *));                 \
1726    if (common_flags()->check_printf) {                                        \
1727      printf_common(ctx, format, aq);                                          \
1728    }                                                                          \
1729    int res = REAL(vname)(strp, __VA_ARGS__);                                  \
1730    if (res >= 0) {                                                            \
1731      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1);                     \
1732    }                                                                          \
1733    VPRINTF_INTERCEPTOR_RETURN();                                              \
1734    return res;                                                                \
1735  }
1736
1737INTERCEPTOR(int, vprintf, const char *format, va_list ap)
1738VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
1739
1740INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
1741            va_list ap)
1742VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
1743
1744INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
1745            va_list ap)
1746VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
1747
1748#if SANITIZER_INTERCEPT___PRINTF_CHK
1749INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag,
1750            SIZE_T size_to, const char *format, va_list ap)
1751VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
1752#endif
1753
1754#if SANITIZER_INTERCEPT_PRINTF_L
1755INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
1756            const char *format, va_list ap)
1757VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)
1758
1759INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
1760            const char *format, ...)
1761FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
1762#endif  // SANITIZER_INTERCEPT_PRINTF_L
1763
1764INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
1765VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
1766
1767#if SANITIZER_INTERCEPT___PRINTF_CHK
1768INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
1769            const char *format, va_list ap)
1770VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
1771#endif
1772
1773INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
1774VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
1775
1776#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1777INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
1778VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
1779
1780INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
1781            const char *format, va_list ap)
1782VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
1783
1784INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
1785            va_list ap)
1786VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)
1787
1788INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
1789            va_list ap)
1790VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
1791                          ap)
1792
1793#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF
1794
1795INTERCEPTOR(int, printf, const char *format, ...)
1796FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
1797
1798INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
1799FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
1800
1801#if SANITIZER_INTERCEPT___PRINTF_CHK
1802INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
1803            const char *format, ...)
1804FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
1805#endif
1806
1807INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
1808FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
1809
1810#if SANITIZER_INTERCEPT___PRINTF_CHK
1811INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
1812            const char *format, ...)
1813FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
1814#endif
1815
1816INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
1817FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
1818
1819#if SANITIZER_INTERCEPT___PRINTF_CHK
1820INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
1821            SIZE_T size_to, const char *format, ...)
1822FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
1823#endif
1824
1825INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
1826FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
1827
1828#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1829INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
1830FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
1831
1832INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
1833            ...)
1834FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
1835
1836INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
1837FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)
1838
1839INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
1840            const char *format, ...)
1841FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
1842                        format)
1843
1844#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF
1845
1846#endif  // SANITIZER_INTERCEPT_PRINTF
1847
1848#if SANITIZER_INTERCEPT_PRINTF
1849#define INIT_PRINTF                     \
1850  COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
1851  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
1852  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
1853  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf);  \
1854  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
1855  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
1856  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
1857  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
1858  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
1859  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
1860#else
1861#define INIT_PRINTF
1862#endif
1863
1864#if SANITIZER_INTERCEPT___PRINTF_CHK
1865#define INIT___PRINTF_CHK                     \
1866  COMMON_INTERCEPT_FUNCTION(__sprintf_chk);   \
1867  COMMON_INTERCEPT_FUNCTION(__snprintf_chk);  \
1868  COMMON_INTERCEPT_FUNCTION(__vsprintf_chk);  \
1869  COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \
1870  COMMON_INTERCEPT_FUNCTION(__fprintf_chk);
1871#else
1872#define INIT___PRINTF_CHK
1873#endif
1874
1875#if SANITIZER_INTERCEPT_PRINTF_L
1876#define INIT_PRINTF_L                     \
1877  COMMON_INTERCEPT_FUNCTION(snprintf_l);  \
1878  COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
1879#else
1880#define INIT_PRINTF_L
1881#endif
1882
1883#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1884#define INIT_ISOC99_PRINTF                       \
1885  COMMON_INTERCEPT_FUNCTION(__isoc99_printf);    \
1886  COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf);   \
1887  COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf);  \
1888  COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf);   \
1889  COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf);   \
1890  COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf);  \
1891  COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
1892  COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
1893#else
1894#define INIT_ISOC99_PRINTF
1895#endif
1896
1897#if SANITIZER_INTERCEPT_IOCTL
1898#include "sanitizer_common_interceptors_ioctl.inc"
1899#include "sanitizer_interceptors_ioctl_netbsd.inc"
1900INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
1901  // We need a frame pointer, because we call into ioctl_common_[pre|post] which
1902  // can trigger a report and we need to be able to unwind through this
1903  // function.  On Mac in debug mode we might not have a frame pointer, because
1904  // ioctl_common_[pre|post] doesn't get inlined here.
1905  ENABLE_FRAME_POINTER;
1906
1907  void *ctx;
1908  va_list ap;
1909  va_start(ap, request);
1910  void *arg = va_arg(ap, void *);
1911  va_end(ap);
1912  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
1913
1914  CHECK(ioctl_initialized);
1915
1916  // Note: TSan does not use common flags, and they are zero-initialized.
1917  // This effectively disables ioctl handling in TSan.
1918  if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
1919
1920  // Although request is unsigned long, the rest of the interceptor uses it
1921  // as just "unsigned" to save space, because we know that all values fit in
1922  // "unsigned" - they are compile-time constants.
1923
1924  const ioctl_desc *desc = ioctl_lookup(request);
1925  ioctl_desc decoded_desc;
1926  if (!desc) {
1927    VPrintf(2, "Decoding unknown ioctl 0x%lx\n", request);
1928    if (!ioctl_decode(request, &decoded_desc))
1929      Printf("WARNING: failed decoding unknown ioctl 0x%lx\n", request);
1930    else
1931      desc = &decoded_desc;
1932  }
1933
1934  if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
1935  int res = REAL(ioctl)(d, request, arg);
1936  // FIXME: some ioctls have different return values for success and failure.
1937  if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
1938  return res;
1939}
1940#define INIT_IOCTL \
1941  ioctl_init();    \
1942  COMMON_INTERCEPT_FUNCTION(ioctl);
1943#else
1944#define INIT_IOCTL
1945#endif
1946
1947#if SANITIZER_POSIX
1948UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
1949  if (pwd) {
1950    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
1951    if (pwd->pw_name)
1952      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
1953                                     internal_strlen(pwd->pw_name) + 1);
1954    if (pwd->pw_passwd)
1955      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
1956                                     internal_strlen(pwd->pw_passwd) + 1);
1957#if !SANITIZER_ANDROID
1958    if (pwd->pw_gecos)
1959      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
1960                                     internal_strlen(pwd->pw_gecos) + 1);
1961#endif
1962#if SANITIZER_APPLE || SANITIZER_FREEBSD || SANITIZER_NETBSD
1963    if (pwd->pw_class)
1964      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
1965                                     internal_strlen(pwd->pw_class) + 1);
1966#endif
1967    if (pwd->pw_dir)
1968      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
1969                                     internal_strlen(pwd->pw_dir) + 1);
1970    if (pwd->pw_shell)
1971      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
1972                                     internal_strlen(pwd->pw_shell) + 1);
1973  }
1974}
1975
1976UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
1977  if (grp) {
1978    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
1979    if (grp->gr_name)
1980      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
1981                                     internal_strlen(grp->gr_name) + 1);
1982    if (grp->gr_passwd)
1983      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
1984                                     internal_strlen(grp->gr_passwd) + 1);
1985    char **p = grp->gr_mem;
1986    for (; *p; ++p) {
1987      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
1988    }
1989    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
1990                                   (p - grp->gr_mem + 1) * sizeof(*p));
1991  }
1992}
1993#endif  // SANITIZER_POSIX
1994
1995#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
1996INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
1997  void *ctx;
1998  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
1999  if (name)
2000    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
2001  __sanitizer_passwd *res = REAL(getpwnam)(name);
2002  unpoison_passwd(ctx, res);
2003  return res;
2004}
2005INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
2006  void *ctx;
2007  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
2008  __sanitizer_passwd *res = REAL(getpwuid)(uid);
2009  unpoison_passwd(ctx, res);
2010  return res;
2011}
2012INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
2013  void *ctx;
2014  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
2015  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
2016  __sanitizer_group *res = REAL(getgrnam)(name);
2017  unpoison_group(ctx, res);
2018  return res;
2019}
2020INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
2021  void *ctx;
2022  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
2023  __sanitizer_group *res = REAL(getgrgid)(gid);
2024  unpoison_group(ctx, res);
2025  return res;
2026}
2027#define INIT_GETPWNAM_AND_FRIENDS      \
2028  COMMON_INTERCEPT_FUNCTION(getpwnam); \
2029  COMMON_INTERCEPT_FUNCTION(getpwuid); \
2030  COMMON_INTERCEPT_FUNCTION(getgrnam); \
2031  COMMON_INTERCEPT_FUNCTION(getgrgid);
2032#else
2033#define INIT_GETPWNAM_AND_FRIENDS
2034#endif
2035
2036#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
2037INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
2038            char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
2039  void *ctx;
2040  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
2041  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
2042  // FIXME: under ASan the call below may write to freed memory and corrupt
2043  // its metadata. See
2044  // https://github.com/google/sanitizers/issues/321.
2045  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
2046  if (!res && result)
2047    unpoison_passwd(ctx, *result);
2048  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2049  return res;
2050}
2051INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
2052            SIZE_T buflen, __sanitizer_passwd **result) {
2053  void *ctx;
2054  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
2055  // FIXME: under ASan the call below may write to freed memory and corrupt
2056  // its metadata. See
2057  // https://github.com/google/sanitizers/issues/321.
2058  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
2059  if (!res && result)
2060    unpoison_passwd(ctx, *result);
2061  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2062  return res;
2063}
2064INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
2065            char *buf, SIZE_T buflen, __sanitizer_group **result) {
2066  void *ctx;
2067  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
2068  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
2069  // FIXME: under ASan the call below may write to freed memory and corrupt
2070  // its metadata. See
2071  // https://github.com/google/sanitizers/issues/321.
2072  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
2073  if (!res && result)
2074    unpoison_group(ctx, *result);
2075  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2076  return res;
2077}
2078INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
2079            SIZE_T buflen, __sanitizer_group **result) {
2080  void *ctx;
2081  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
2082  // FIXME: under ASan the call below may write to freed memory and corrupt
2083  // its metadata. See
2084  // https://github.com/google/sanitizers/issues/321.
2085  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
2086  if (!res && result)
2087    unpoison_group(ctx, *result);
2088  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2089  return res;
2090}
2091#define INIT_GETPWNAM_R_AND_FRIENDS      \
2092  COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
2093  COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
2094  COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
2095  COMMON_INTERCEPT_FUNCTION(getgrgid_r);
2096#else
2097#define INIT_GETPWNAM_R_AND_FRIENDS
2098#endif
2099
2100#if SANITIZER_INTERCEPT_GETPWENT
2101INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
2102  void *ctx;
2103  COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
2104  __sanitizer_passwd *res = REAL(getpwent)(dummy);
2105  unpoison_passwd(ctx, res);
2106  return res;
2107}
2108INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
2109  void *ctx;
2110  COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
2111  __sanitizer_group *res = REAL(getgrent)(dummy);
2112  unpoison_group(ctx, res);
2113  return res;
2114}
2115#define INIT_GETPWENT                  \
2116  COMMON_INTERCEPT_FUNCTION(getpwent); \
2117  COMMON_INTERCEPT_FUNCTION(getgrent);
2118#else
2119#define INIT_GETPWENT
2120#endif
2121
2122#if SANITIZER_INTERCEPT_FGETPWENT
2123INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
2124  void *ctx;
2125  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
2126  __sanitizer_passwd *res = REAL(fgetpwent)(fp);
2127  unpoison_passwd(ctx, res);
2128  return res;
2129}
2130INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
2131  void *ctx;
2132  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
2133  __sanitizer_group *res = REAL(fgetgrent)(fp);
2134  unpoison_group(ctx, res);
2135  return res;
2136}
2137#define INIT_FGETPWENT                  \
2138  COMMON_INTERCEPT_FUNCTION(fgetpwent); \
2139  COMMON_INTERCEPT_FUNCTION(fgetgrent);
2140#else
2141#define INIT_FGETPWENT
2142#endif
2143
2144#if SANITIZER_INTERCEPT_GETPWENT_R
2145INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
2146            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
2147  void *ctx;
2148  COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
2149  // FIXME: under ASan the call below may write to freed memory and corrupt
2150  // its metadata. See
2151  // https://github.com/google/sanitizers/issues/321.
2152  int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
2153  if (!res && pwbufp)
2154    unpoison_passwd(ctx, *pwbufp);
2155  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2156  return res;
2157}
2158INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
2159            __sanitizer_group **pwbufp) {
2160  void *ctx;
2161  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
2162  // FIXME: under ASan the call below may write to freed memory and corrupt
2163  // its metadata. See
2164  // https://github.com/google/sanitizers/issues/321.
2165  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
2166  if (!res && pwbufp)
2167    unpoison_group(ctx, *pwbufp);
2168  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2169  return res;
2170}
2171#define INIT_GETPWENT_R                   \
2172  COMMON_INTERCEPT_FUNCTION(getpwent_r);  \
2173  COMMON_INTERCEPT_FUNCTION(getgrent_r);
2174#else
2175#define INIT_GETPWENT_R
2176#endif
2177
2178#if SANITIZER_INTERCEPT_FGETPWENT_R
2179INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
2180            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
2181  void *ctx;
2182  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
2183  // FIXME: under ASan the call below may write to freed memory and corrupt
2184  // its metadata. See
2185  // https://github.com/google/sanitizers/issues/321.
2186  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
2187  if (!res && pwbufp)
2188    unpoison_passwd(ctx, *pwbufp);
2189  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2190  return res;
2191}
2192#define INIT_FGETPWENT_R                  \
2193  COMMON_INTERCEPT_FUNCTION(fgetpwent_r);
2194#else
2195#define INIT_FGETPWENT_R
2196#endif
2197
2198#if SANITIZER_INTERCEPT_FGETGRENT_R
2199INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
2200            SIZE_T buflen, __sanitizer_group **pwbufp) {
2201  void *ctx;
2202  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
2203  // FIXME: under ASan the call below may write to freed memory and corrupt
2204  // its metadata. See
2205  // https://github.com/google/sanitizers/issues/321.
2206  int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
2207  if (!res && pwbufp)
2208    unpoison_group(ctx, *pwbufp);
2209  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2210  return res;
2211}
2212#define INIT_FGETGRENT_R                  \
2213  COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
2214#else
2215#define INIT_FGETGRENT_R
2216#endif
2217
2218#if SANITIZER_INTERCEPT_SETPWENT
2219// The only thing these interceptors do is disable any nested interceptors.
2220// These functions may open nss modules and call uninstrumented functions from
2221// them, and we don't want things like strlen() to trigger.
2222INTERCEPTOR(void, setpwent, int dummy) {
2223  void *ctx;
2224  COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
2225  REAL(setpwent)(dummy);
2226}
2227INTERCEPTOR(void, endpwent, int dummy) {
2228  void *ctx;
2229  COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
2230  REAL(endpwent)(dummy);
2231}
2232INTERCEPTOR(void, setgrent, int dummy) {
2233  void *ctx;
2234  COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
2235  REAL(setgrent)(dummy);
2236}
2237INTERCEPTOR(void, endgrent, int dummy) {
2238  void *ctx;
2239  COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
2240  REAL(endgrent)(dummy);
2241}
2242#define INIT_SETPWENT                  \
2243  COMMON_INTERCEPT_FUNCTION(setpwent); \
2244  COMMON_INTERCEPT_FUNCTION(endpwent); \
2245  COMMON_INTERCEPT_FUNCTION(setgrent); \
2246  COMMON_INTERCEPT_FUNCTION(endgrent);
2247#else
2248#define INIT_SETPWENT
2249#endif
2250
2251#if SANITIZER_INTERCEPT_CLOCK_GETTIME
2252INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
2253  void *ctx;
2254  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
2255  // FIXME: under ASan the call below may write to freed memory and corrupt
2256  // its metadata. See
2257  // https://github.com/google/sanitizers/issues/321.
2258  int res = REAL(clock_getres)(clk_id, tp);
2259  if (!res && tp) {
2260    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
2261  }
2262  return res;
2263}
2264INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
2265  void *ctx;
2266  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
2267  // FIXME: under ASan the call below may write to freed memory and corrupt
2268  // its metadata. See
2269  // https://github.com/google/sanitizers/issues/321.
2270  int res = REAL(clock_gettime)(clk_id, tp);
2271  if (!res) {
2272    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
2273  }
2274  return res;
2275}
2276#if SANITIZER_GLIBC
2277namespace __sanitizer {
2278extern "C" {
2279int real_clock_gettime(u32 clk_id, void *tp) {
2280  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
2281    return internal_clock_gettime(clk_id, tp);
2282  return REAL(clock_gettime)(clk_id, tp);
2283}
2284}  // extern "C"
2285}  // namespace __sanitizer
2286#endif
2287INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
2288  void *ctx;
2289  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
2290  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
2291  return REAL(clock_settime)(clk_id, tp);
2292}
2293#define INIT_CLOCK_GETTIME                  \
2294  COMMON_INTERCEPT_FUNCTION(clock_getres);  \
2295  COMMON_INTERCEPT_FUNCTION(clock_gettime); \
2296  COMMON_INTERCEPT_FUNCTION(clock_settime);
2297#else
2298#define INIT_CLOCK_GETTIME
2299#endif
2300
2301#if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
2302INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
2303            __sanitizer_clockid_t *clockid) {
2304  void *ctx;
2305  COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid);
2306  int res = REAL(clock_getcpuclockid)(pid, clockid);
2307  if (!res && clockid) {
2308    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
2309  }
2310  return res;
2311}
2312
2313INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
2314            __sanitizer_clockid_t *clockid) {
2315  void *ctx;
2316  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getcpuclockid, thread, clockid);
2317  int res = REAL(pthread_getcpuclockid)(thread, clockid);
2318  if (!res && clockid) {
2319    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
2320  }
2321  return res;
2322}
2323
2324#define INIT_CLOCK_GETCPUCLOCKID                   \
2325  COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);  \
2326  COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
2327#else
2328#define INIT_CLOCK_GETCPUCLOCKID
2329#endif
2330
2331#if SANITIZER_INTERCEPT_GETITIMER
2332INTERCEPTOR(int, getitimer, int which, void *curr_value) {
2333  void *ctx;
2334  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
2335  // FIXME: under ASan the call below may write to freed memory and corrupt
2336  // its metadata. See
2337  // https://github.com/google/sanitizers/issues/321.
2338  int res = REAL(getitimer)(which, curr_value);
2339  if (!res && curr_value) {
2340    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
2341  }
2342  return res;
2343}
2344INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
2345  void *ctx;
2346  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
2347  if (new_value) {
2348    // itimerval can contain padding that may be legitimately uninitialized
2349    const struct __sanitizer_itimerval *nv =
2350        (const struct __sanitizer_itimerval *)new_value;
2351    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec,
2352                                  sizeof(__sanitizer_time_t));
2353    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec,
2354                                  sizeof(__sanitizer_suseconds_t));
2355    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec,
2356                                  sizeof(__sanitizer_time_t));
2357    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec,
2358                                  sizeof(__sanitizer_suseconds_t));
2359  }
2360  // FIXME: under ASan the call below may write to freed memory and corrupt
2361  // its metadata. See
2362  // https://github.com/google/sanitizers/issues/321.
2363  int res = REAL(setitimer)(which, new_value, old_value);
2364  if (!res && old_value) {
2365    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
2366  }
2367  return res;
2368}
2369#define INIT_GETITIMER                  \
2370  COMMON_INTERCEPT_FUNCTION(getitimer); \
2371  COMMON_INTERCEPT_FUNCTION(setitimer);
2372#else
2373#define INIT_GETITIMER
2374#endif
2375
2376#if SANITIZER_INTERCEPT_GLOB
2377static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
2378  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
2379  // +1 for NULL pointer at the end.
2380  if (pglob->gl_pathv)
2381    COMMON_INTERCEPTOR_WRITE_RANGE(
2382        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
2383  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
2384    char *p = pglob->gl_pathv[i];
2385    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
2386  }
2387}
2388
2389#if SANITIZER_SOLARIS
2390INTERCEPTOR(int, glob, const char *pattern, int flags,
2391            int (*errfunc)(const char *epath, int eerrno),
2392            __sanitizer_glob_t *pglob) {
2393  void *ctx;
2394  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
2395  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
2396  int res = REAL(glob)(pattern, flags, errfunc, pglob);
2397  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
2398  return res;
2399}
2400#else
2401static THREADLOCAL __sanitizer_glob_t *pglob_copy;
2402
2403static void wrapped_gl_closedir(void *dir) {
2404  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2405  pglob_copy->gl_closedir(dir);
2406}
2407
2408static void *wrapped_gl_readdir(void *dir) {
2409  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2410  return pglob_copy->gl_readdir(dir);
2411}
2412
2413static void *wrapped_gl_opendir(const char *s) {
2414  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2415  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
2416  return pglob_copy->gl_opendir(s);
2417}
2418
2419static int wrapped_gl_lstat(const char *s, void *st) {
2420  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2421  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
2422  return pglob_copy->gl_lstat(s, st);
2423}
2424
2425static int wrapped_gl_stat(const char *s, void *st) {
2426  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2427  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
2428  return pglob_copy->gl_stat(s, st);
2429}
2430
2431static const __sanitizer_glob_t kGlobCopy = {
2432      0,                  0,                   0,
2433      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
2434      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
2435
2436INTERCEPTOR(int, glob, const char *pattern, int flags,
2437            int (*errfunc)(const char *epath, int eerrno),
2438            __sanitizer_glob_t *pglob) {
2439  void *ctx;
2440  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
2441  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
2442  __sanitizer_glob_t glob_copy;
2443  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
2444  if (flags & glob_altdirfunc) {
2445    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2446    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2447    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2448    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2449    Swap(pglob->gl_stat, glob_copy.gl_stat);
2450    pglob_copy = &glob_copy;
2451  }
2452  int res = REAL(glob)(pattern, flags, errfunc, pglob);
2453  if (flags & glob_altdirfunc) {
2454    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2455    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2456    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2457    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2458    Swap(pglob->gl_stat, glob_copy.gl_stat);
2459  }
2460  pglob_copy = 0;
2461  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
2462  return res;
2463}
2464#endif  // SANITIZER_SOLARIS
2465#define INIT_GLOB                  \
2466  COMMON_INTERCEPT_FUNCTION(glob);
2467#else  // SANITIZER_INTERCEPT_GLOB
2468#define INIT_GLOB
2469#endif  // SANITIZER_INTERCEPT_GLOB
2470
2471#if SANITIZER_INTERCEPT_GLOB64
2472INTERCEPTOR(int, glob64, const char *pattern, int flags,
2473            int (*errfunc)(const char *epath, int eerrno),
2474            __sanitizer_glob_t *pglob) {
2475  void *ctx;
2476  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
2477  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
2478  __sanitizer_glob_t glob_copy;
2479  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
2480  if (flags & glob_altdirfunc) {
2481    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2482    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2483    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2484    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2485    Swap(pglob->gl_stat, glob_copy.gl_stat);
2486    pglob_copy = &glob_copy;
2487  }
2488  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
2489  if (flags & glob_altdirfunc) {
2490    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2491    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2492    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2493    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2494    Swap(pglob->gl_stat, glob_copy.gl_stat);
2495  }
2496  pglob_copy = 0;
2497  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
2498  return res;
2499}
2500#define INIT_GLOB64                \
2501  COMMON_INTERCEPT_FUNCTION(glob64);
2502#else  // SANITIZER_INTERCEPT_GLOB64
2503#define INIT_GLOB64
2504#endif  // SANITIZER_INTERCEPT_GLOB64
2505
2506#if SANITIZER_INTERCEPT___B64_TO
2507INTERCEPTOR(int, __b64_ntop, unsigned char const *src, SIZE_T srclength,
2508            char *target, SIZE_T targsize) {
2509  void *ctx;
2510  COMMON_INTERCEPTOR_ENTER(ctx, __b64_ntop, src, srclength, target, targsize);
2511  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclength);
2512  int res = REAL(__b64_ntop)(src, srclength, target, targsize);
2513  if (res >= 0)
2514    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res + 1);
2515  return res;
2516}
2517INTERCEPTOR(int, __b64_pton, char const *src, char *target, SIZE_T targsize) {
2518  void *ctx;
2519  COMMON_INTERCEPTOR_ENTER(ctx, __b64_pton, src, target, targsize);
2520  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
2521  int res = REAL(__b64_pton)(src, target, targsize);
2522  if (res >= 0)
2523    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res);
2524  return res;
2525}
2526#define INIT___B64_TO                      \
2527    COMMON_INTERCEPT_FUNCTION(__b64_ntop); \
2528    COMMON_INTERCEPT_FUNCTION(__b64_pton);
2529#else  // SANITIZER_INTERCEPT___B64_TO
2530#define INIT___B64_TO
2531#endif  // SANITIZER_INTERCEPT___B64_TO
2532
2533#if SANITIZER_INTERCEPT___DN_EXPAND
2534#  if __GLIBC_PREREQ(2, 34)
2535// Changed with https://sourceware.org/git/?p=glibc.git;h=640bbdf
2536#    define DN_EXPAND_INTERCEPTOR_NAME dn_expand
2537#  else
2538#    define DN_EXPAND_INTERCEPTOR_NAME __dn_expand
2539#  endif
2540INTERCEPTOR(int, DN_EXPAND_INTERCEPTOR_NAME, unsigned char const *base,
2541            unsigned char const *end, unsigned char const *src, char *dest,
2542            int space) {
2543  void *ctx;
2544  COMMON_INTERCEPTOR_ENTER(ctx, DN_EXPAND_INTERCEPTOR_NAME, base, end, src,
2545                           dest, space);
2546  // TODO: add read check if __dn_comp intercept added
2547  int res = REAL(DN_EXPAND_INTERCEPTOR_NAME)(base, end, src, dest, space);
2548  if (res >= 0)
2549    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, internal_strlen(dest) + 1);
2550  return res;
2551}
2552#  define INIT___DN_EXPAND \
2553    COMMON_INTERCEPT_FUNCTION(DN_EXPAND_INTERCEPTOR_NAME);
2554#else  // SANITIZER_INTERCEPT___DN_EXPAND
2555#  define INIT___DN_EXPAND
2556#endif  // SANITIZER_INTERCEPT___DN_EXPAND
2557
2558#if SANITIZER_INTERCEPT_POSIX_SPAWN
2559
2560template <class RealSpawnPtr>
2561static int PosixSpawnImpl(void *ctx, RealSpawnPtr *real_posix_spawn, pid_t *pid,
2562                          const char *file_or_path, const void *file_actions,
2563                          const void *attrp, char *const argv[],
2564                          char *const envp[]) {
2565  COMMON_INTERCEPTOR_READ_RANGE(ctx, file_or_path,
2566                                internal_strlen(file_or_path) + 1);
2567  if (argv) {
2568    for (char *const *s = argv; ; ++s) {
2569      COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
2570      if (!*s) break;
2571      COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
2572    }
2573  }
2574  if (envp) {
2575    for (char *const *s = envp; ; ++s) {
2576      COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
2577      if (!*s) break;
2578      COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
2579    }
2580  }
2581  int res =
2582      real_posix_spawn(pid, file_or_path, file_actions, attrp, argv, envp);
2583  if (res == 0)
2584    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pid, sizeof(*pid));
2585  return res;
2586}
2587INTERCEPTOR(int, posix_spawn, pid_t *pid, const char *path,
2588            const void *file_actions, const void *attrp, char *const argv[],
2589            char *const envp[]) {
2590  void *ctx;
2591  COMMON_INTERCEPTOR_ENTER(ctx, posix_spawn, pid, path, file_actions, attrp,
2592                           argv, envp);
2593  return PosixSpawnImpl(ctx, REAL(posix_spawn), pid, path, file_actions, attrp,
2594                        argv, envp);
2595}
2596INTERCEPTOR(int, posix_spawnp, pid_t *pid, const char *file,
2597            const void *file_actions, const void *attrp, char *const argv[],
2598            char *const envp[]) {
2599  void *ctx;
2600  COMMON_INTERCEPTOR_ENTER(ctx, posix_spawnp, pid, file, file_actions, attrp,
2601                           argv, envp);
2602  return PosixSpawnImpl(ctx, REAL(posix_spawnp), pid, file, file_actions, attrp,
2603                        argv, envp);
2604}
2605#  define INIT_POSIX_SPAWN                  \
2606    COMMON_INTERCEPT_FUNCTION(posix_spawn); \
2607    COMMON_INTERCEPT_FUNCTION(posix_spawnp);
2608#else  // SANITIZER_INTERCEPT_POSIX_SPAWN
2609#  define INIT_POSIX_SPAWN
2610#endif  // SANITIZER_INTERCEPT_POSIX_SPAWN
2611
2612#if SANITIZER_INTERCEPT_WAIT
2613// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
2614// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
2615// details.
2616INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
2617  void *ctx;
2618  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
2619  // FIXME: under ASan the call below may write to freed memory and corrupt
2620  // its metadata. See
2621  // https://github.com/google/sanitizers/issues/321.
2622  int res = REAL(wait)(status);
2623  if (res != -1 && status)
2624    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2625  return res;
2626}
2627// On FreeBSD id_t is always 64-bit wide.
2628#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
2629INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
2630                        int options) {
2631#else
2632INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
2633                        int options) {
2634#endif
2635  void *ctx;
2636  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
2637  // FIXME: under ASan the call below may write to freed memory and corrupt
2638  // its metadata. See
2639  // https://github.com/google/sanitizers/issues/321.
2640  int res = REAL(waitid)(idtype, id, infop, options);
2641  if (res != -1 && infop)
2642    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
2643  return res;
2644}
2645INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
2646  void *ctx;
2647  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
2648  // FIXME: under ASan the call below may write to freed memory and corrupt
2649  // its metadata. See
2650  // https://github.com/google/sanitizers/issues/321.
2651  int res = REAL(waitpid)(pid, status, options);
2652  if (res != -1 && status)
2653    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2654  return res;
2655}
2656INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
2657  void *ctx;
2658  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
2659  // FIXME: under ASan the call below may write to freed memory and corrupt
2660  // its metadata. See
2661  // https://github.com/google/sanitizers/issues/321.
2662  int res = REAL(wait3)(status, options, rusage);
2663  if (res != -1) {
2664    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2665    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
2666  }
2667  return res;
2668}
2669#if SANITIZER_ANDROID
2670INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
2671  void *ctx;
2672  COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
2673  // FIXME: under ASan the call below may write to freed memory and corrupt
2674  // its metadata. See
2675  // https://github.com/google/sanitizers/issues/321.
2676  int res = REAL(__wait4)(pid, status, options, rusage);
2677  if (res != -1) {
2678    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2679    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
2680  }
2681  return res;
2682}
2683#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
2684#else
2685INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
2686  void *ctx;
2687  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
2688  // FIXME: under ASan the call below may write to freed memory and corrupt
2689  // its metadata. See
2690  // https://github.com/google/sanitizers/issues/321.
2691  int res = REAL(wait4)(pid, status, options, rusage);
2692  if (res != -1) {
2693    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2694    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
2695  }
2696  return res;
2697}
2698#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
2699#endif  // SANITIZER_ANDROID
2700#define INIT_WAIT                     \
2701  COMMON_INTERCEPT_FUNCTION(wait);    \
2702  COMMON_INTERCEPT_FUNCTION(waitid);  \
2703  COMMON_INTERCEPT_FUNCTION(waitpid); \
2704  COMMON_INTERCEPT_FUNCTION(wait3);
2705#else
2706#define INIT_WAIT
2707#define INIT_WAIT4
2708#endif
2709
2710#if SANITIZER_INTERCEPT_INET
2711INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
2712  void *ctx;
2713  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
2714  uptr sz = __sanitizer_in_addr_sz(af);
2715  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
2716  // FIXME: figure out read size based on the address family.
2717  // FIXME: under ASan the call below may write to freed memory and corrupt
2718  // its metadata. See
2719  // https://github.com/google/sanitizers/issues/321.
2720  char *res = REAL(inet_ntop)(af, src, dst, size);
2721  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
2722  return res;
2723}
2724INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
2725  void *ctx;
2726  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
2727  COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
2728  // FIXME: figure out read size based on the address family.
2729  // FIXME: under ASan the call below may write to freed memory and corrupt
2730  // its metadata. See
2731  // https://github.com/google/sanitizers/issues/321.
2732  int res = REAL(inet_pton)(af, src, dst);
2733  if (res == 1) {
2734    uptr sz = __sanitizer_in_addr_sz(af);
2735    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
2736  }
2737  return res;
2738}
2739#define INIT_INET                       \
2740  COMMON_INTERCEPT_FUNCTION(inet_ntop); \
2741  COMMON_INTERCEPT_FUNCTION(inet_pton);
2742#else
2743#define INIT_INET
2744#endif
2745
2746#if SANITIZER_INTERCEPT_INET
2747INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
2748  void *ctx;
2749  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
2750  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, internal_strlen(cp) + 1);
2751  // FIXME: under ASan the call below may write to freed memory and corrupt
2752  // its metadata. See
2753  // https://github.com/google/sanitizers/issues/321.
2754  int res = REAL(inet_aton)(cp, dst);
2755  if (res != 0) {
2756    uptr sz = __sanitizer_in_addr_sz(af_inet);
2757    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
2758  }
2759  return res;
2760}
2761#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
2762#else
2763#define INIT_INET_ATON
2764#endif
2765
2766#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
2767INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
2768  void *ctx;
2769  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
2770  // FIXME: under ASan the call below may write to freed memory and corrupt
2771  // its metadata. See
2772  // https://github.com/google/sanitizers/issues/321.
2773  int res = REAL(pthread_getschedparam)(thread, policy, param);
2774  if (res == 0) {
2775    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
2776    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
2777  }
2778  return res;
2779}
2780#define INIT_PTHREAD_GETSCHEDPARAM \
2781  COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
2782#else
2783#define INIT_PTHREAD_GETSCHEDPARAM
2784#endif
2785
2786#if SANITIZER_INTERCEPT_GETADDRINFO
2787INTERCEPTOR(int, getaddrinfo, char *node, char *service,
2788            struct __sanitizer_addrinfo *hints,
2789            struct __sanitizer_addrinfo **out) {
2790  void *ctx;
2791  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
2792  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, internal_strlen(node) + 1);
2793  if (service)
2794    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, internal_strlen(service) + 1);
2795  if (hints)
2796    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
2797  // FIXME: under ASan the call below may write to freed memory and corrupt
2798  // its metadata. See
2799  // https://github.com/google/sanitizers/issues/321.
2800  int res = REAL(getaddrinfo)(node, service, hints, out);
2801  if (res == 0 && out) {
2802    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
2803    struct __sanitizer_addrinfo *p = *out;
2804    while (p) {
2805      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
2806      if (p->ai_addr)
2807        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
2808      if (p->ai_canonname)
2809        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
2810                                       internal_strlen(p->ai_canonname) + 1);
2811      p = p->ai_next;
2812    }
2813  }
2814  return res;
2815}
2816#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
2817#else
2818#define INIT_GETADDRINFO
2819#endif
2820
2821#if SANITIZER_INTERCEPT_GETNAMEINFO
2822INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
2823            unsigned hostlen, char *serv, unsigned servlen, int flags) {
2824  void *ctx;
2825  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
2826                           serv, servlen, flags);
2827  // FIXME: consider adding READ_RANGE(sockaddr, salen)
2828  // There is padding in in_addr that may make this too noisy
2829  // FIXME: under ASan the call below may write to freed memory and corrupt
2830  // its metadata. See
2831  // https://github.com/google/sanitizers/issues/321.
2832  int res =
2833      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
2834  if (res == 0) {
2835    if (host && hostlen)
2836      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, internal_strlen(host) + 1);
2837    if (serv && servlen)
2838      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, internal_strlen(serv) + 1);
2839  }
2840  return res;
2841}
2842#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
2843#else
2844#define INIT_GETNAMEINFO
2845#endif
2846
2847#if SANITIZER_INTERCEPT_GETSOCKNAME
2848INTERCEPTOR(int, getsockname, int sock_fd, void *addr, unsigned *addrlen) {
2849  void *ctx;
2850  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
2851  unsigned addr_sz;
2852  if (addrlen) {
2853    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2854    addr_sz = *addrlen;
2855  }
2856  // FIXME: under ASan the call below may write to freed memory and corrupt
2857  // its metadata. See
2858  // https://github.com/google/sanitizers/issues/321.
2859  int res = REAL(getsockname)(sock_fd, addr, addrlen);
2860  if (!res && addr && addrlen) {
2861    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
2862  }
2863  return res;
2864}
2865#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
2866#else
2867#define INIT_GETSOCKNAME
2868#endif
2869
2870#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
2871static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
2872  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
2873  if (h->h_name)
2874    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, internal_strlen(h->h_name) + 1);
2875  char **p = h->h_aliases;
2876  while (*p) {
2877    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
2878    ++p;
2879  }
2880  COMMON_INTERCEPTOR_WRITE_RANGE(
2881      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
2882  p = h->h_addr_list;
2883  while (*p) {
2884    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
2885    ++p;
2886  }
2887  COMMON_INTERCEPTOR_WRITE_RANGE(
2888      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
2889}
2890#endif
2891
2892#if SANITIZER_INTERCEPT_GETHOSTBYNAME
2893INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
2894  void *ctx;
2895  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
2896  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
2897  if (res) write_hostent(ctx, res);
2898  return res;
2899}
2900
2901INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
2902            int type) {
2903  void *ctx;
2904  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
2905  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
2906  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
2907  if (res) write_hostent(ctx, res);
2908  return res;
2909}
2910
2911INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
2912  void *ctx;
2913  COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
2914  struct __sanitizer_hostent *res = REAL(gethostent)(fake);
2915  if (res) write_hostent(ctx, res);
2916  return res;
2917}
2918#define INIT_GETHOSTBYNAME                  \
2919  COMMON_INTERCEPT_FUNCTION(gethostent);    \
2920  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
2921  COMMON_INTERCEPT_FUNCTION(gethostbyname);
2922#else
2923#define INIT_GETHOSTBYNAME
2924#endif  // SANITIZER_INTERCEPT_GETHOSTBYNAME
2925
2926#if SANITIZER_INTERCEPT_GETHOSTBYNAME2
2927INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
2928  void *ctx;
2929  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
2930  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
2931  if (res) write_hostent(ctx, res);
2932  return res;
2933}
2934#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2);
2935#else
2936#define INIT_GETHOSTBYNAME2
2937#endif  // SANITIZER_INTERCEPT_GETHOSTBYNAME2
2938
2939#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
2940INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
2941            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
2942            int *h_errnop) {
2943  void *ctx;
2944  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
2945                           h_errnop);
2946  // FIXME: under ASan the call below may write to freed memory and corrupt
2947  // its metadata. See
2948  // https://github.com/google/sanitizers/issues/321.
2949  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
2950  if (result) {
2951    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2952    if (res == 0 && *result) write_hostent(ctx, *result);
2953  }
2954  if (h_errnop)
2955    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2956  return res;
2957}
2958#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
2959#else
2960#define INIT_GETHOSTBYNAME_R
2961#endif
2962
2963#if SANITIZER_INTERCEPT_GETHOSTENT_R
2964INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
2965            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
2966  void *ctx;
2967  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
2968                           h_errnop);
2969  // FIXME: under ASan the call below may write to freed memory and corrupt
2970  // its metadata. See
2971  // https://github.com/google/sanitizers/issues/321.
2972  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
2973  if (result) {
2974    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2975    if (res == 0 && *result) write_hostent(ctx, *result);
2976  }
2977  if (h_errnop)
2978    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2979  return res;
2980}
2981#define INIT_GETHOSTENT_R                  \
2982  COMMON_INTERCEPT_FUNCTION(gethostent_r);
2983#else
2984#define INIT_GETHOSTENT_R
2985#endif
2986
2987#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
2988INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
2989            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
2990            __sanitizer_hostent **result, int *h_errnop) {
2991  void *ctx;
2992  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
2993                           buflen, result, h_errnop);
2994  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
2995  // FIXME: under ASan the call below may write to freed memory and corrupt
2996  // its metadata. See
2997  // https://github.com/google/sanitizers/issues/321.
2998  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
2999                                  h_errnop);
3000  if (result) {
3001    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3002    if (res == 0 && *result) write_hostent(ctx, *result);
3003  }
3004  if (h_errnop)
3005    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
3006  return res;
3007}
3008#define INIT_GETHOSTBYADDR_R                  \
3009  COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
3010#else
3011#define INIT_GETHOSTBYADDR_R
3012#endif
3013
3014#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
3015INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
3016            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
3017            __sanitizer_hostent **result, int *h_errnop) {
3018  void *ctx;
3019  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
3020                           result, h_errnop);
3021  // FIXME: under ASan the call below may write to freed memory and corrupt
3022  // its metadata. See
3023  // https://github.com/google/sanitizers/issues/321.
3024  int res =
3025      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
3026  if (result) {
3027    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3028    if (res == 0 && *result) write_hostent(ctx, *result);
3029  }
3030  if (h_errnop)
3031    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
3032  return res;
3033}
3034#define INIT_GETHOSTBYNAME2_R                  \
3035  COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
3036#else
3037#define INIT_GETHOSTBYNAME2_R
3038#endif
3039
3040#if SANITIZER_INTERCEPT_GETSOCKOPT
3041INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
3042            int *optlen) {
3043  void *ctx;
3044  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
3045                           optlen);
3046  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
3047  // FIXME: under ASan the call below may write to freed memory and corrupt
3048  // its metadata. See
3049  // https://github.com/google/sanitizers/issues/321.
3050  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
3051  if (res == 0)
3052    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
3053  return res;
3054}
3055#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
3056#else
3057#define INIT_GETSOCKOPT
3058#endif
3059
3060#if SANITIZER_INTERCEPT_ACCEPT
3061INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
3062  void *ctx;
3063  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
3064  unsigned addrlen0 = 0;
3065  if (addrlen) {
3066    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
3067    addrlen0 = *addrlen;
3068  }
3069  int fd2 = REAL(accept)(fd, addr, addrlen);
3070  if (fd2 >= 0) {
3071    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
3072    if (addr && addrlen)
3073      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
3074  }
3075  return fd2;
3076}
3077#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
3078#else
3079#define INIT_ACCEPT
3080#endif
3081
3082#if SANITIZER_INTERCEPT_ACCEPT4
3083INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
3084  void *ctx;
3085  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
3086  unsigned addrlen0 = 0;
3087  if (addrlen) {
3088    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
3089    addrlen0 = *addrlen;
3090  }
3091  // FIXME: under ASan the call below may write to freed memory and corrupt
3092  // its metadata. See
3093  // https://github.com/google/sanitizers/issues/321.
3094  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
3095  if (fd2 >= 0) {
3096    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
3097    if (addr && addrlen)
3098      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
3099  }
3100  return fd2;
3101}
3102#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
3103#else
3104#define INIT_ACCEPT4
3105#endif
3106
3107#if SANITIZER_INTERCEPT_PACCEPT
3108INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen,
3109            __sanitizer_sigset_t *set, int f) {
3110  void *ctx;
3111  COMMON_INTERCEPTOR_ENTER(ctx, paccept, fd, addr, addrlen, set, f);
3112  unsigned addrlen0 = 0;
3113  if (addrlen) {
3114    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
3115    addrlen0 = *addrlen;
3116  }
3117  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
3118  int fd2 = REAL(paccept)(fd, addr, addrlen, set, f);
3119  if (fd2 >= 0) {
3120    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
3121    if (addr && addrlen)
3122      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
3123  }
3124  return fd2;
3125}
3126#define INIT_PACCEPT COMMON_INTERCEPT_FUNCTION(paccept);
3127#else
3128#define INIT_PACCEPT
3129#endif
3130
3131#if SANITIZER_INTERCEPT_MODF
3132INTERCEPTOR(double, modf, double x, double *iptr) {
3133  void *ctx;
3134  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
3135  // FIXME: under ASan the call below may write to freed memory and corrupt
3136  // its metadata. See
3137  // https://github.com/google/sanitizers/issues/321.
3138  double res = REAL(modf)(x, iptr);
3139  if (iptr) {
3140    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
3141  }
3142  return res;
3143}
3144INTERCEPTOR(float, modff, float x, float *iptr) {
3145  void *ctx;
3146  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
3147  // FIXME: under ASan the call below may write to freed memory and corrupt
3148  // its metadata. See
3149  // https://github.com/google/sanitizers/issues/321.
3150  float res = REAL(modff)(x, iptr);
3151  if (iptr) {
3152    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
3153  }
3154  return res;
3155}
3156INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
3157  void *ctx;
3158  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
3159  // FIXME: under ASan the call below may write to freed memory and corrupt
3160  // its metadata. See
3161  // https://github.com/google/sanitizers/issues/321.
3162  long double res = REAL(modfl)(x, iptr);
3163  if (iptr) {
3164    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
3165  }
3166  return res;
3167}
3168#define INIT_MODF                   \
3169  COMMON_INTERCEPT_FUNCTION(modf);  \
3170  COMMON_INTERCEPT_FUNCTION(modff); \
3171  COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
3172#else
3173#define INIT_MODF
3174#endif
3175
3176#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
3177static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
3178                         SSIZE_T maxlen) {
3179  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
3180  if (msg->msg_name && msg->msg_namelen)
3181    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
3182  if (msg->msg_iov && msg->msg_iovlen)
3183    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
3184                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
3185  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
3186  if (msg->msg_control && msg->msg_controllen)
3187    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
3188}
3189#endif
3190
3191#if SANITIZER_INTERCEPT_RECVMSG
3192INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
3193            int flags) {
3194  void *ctx;
3195  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
3196  // FIXME: under ASan the call below may write to freed memory and corrupt
3197  // its metadata. See
3198  // https://github.com/google/sanitizers/issues/321.
3199  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
3200  if (res >= 0) {
3201    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
3202    if (msg) {
3203      write_msghdr(ctx, msg, res);
3204      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
3205    }
3206  }
3207  return res;
3208}
3209#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
3210#else
3211#define INIT_RECVMSG
3212#endif
3213
3214#if SANITIZER_INTERCEPT_RECVMMSG
3215INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
3216            unsigned int vlen, int flags, void *timeout) {
3217  void *ctx;
3218  COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
3219  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
3220  int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
3221  if (res >= 0) {
3222    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
3223    for (int i = 0; i < res; ++i) {
3224      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
3225                                     sizeof(msgvec[i].msg_len));
3226      write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
3227      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
3228    }
3229  }
3230  return res;
3231}
3232#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
3233#else
3234#define INIT_RECVMMSG
3235#endif
3236
3237#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
3238static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
3239  const unsigned kCmsgDataOffset =
3240      RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));
3241
3242  char *p = (char *)control;
3243  char *const control_end = p + controllen;
3244  while (true) {
3245    if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
3246    __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
3247    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));
3248
3249    if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;
3250
3251    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
3252                                  sizeof(cmsg->cmsg_level));
3253    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
3254                                  sizeof(cmsg->cmsg_type));
3255
3256    if (cmsg->cmsg_len > kCmsgDataOffset) {
3257      char *data = p + kCmsgDataOffset;
3258      unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
3259      if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
3260    }
3261
3262    p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
3263  }
3264}
3265
3266static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
3267                        SSIZE_T maxlen) {
3268#define R(f) \
3269  COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
3270  R(name);
3271  R(namelen);
3272  R(iov);
3273  R(iovlen);
3274  R(control);
3275  R(controllen);
3276  R(flags);
3277#undef R
3278  if (msg->msg_name && msg->msg_namelen)
3279    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
3280  if (msg->msg_iov && msg->msg_iovlen)
3281    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
3282                                  sizeof(*msg->msg_iov) * msg->msg_iovlen);
3283  read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
3284  if (msg->msg_control && msg->msg_controllen)
3285    read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
3286}
3287#endif
3288
3289#if SANITIZER_INTERCEPT_SENDMSG
3290INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
3291            int flags) {
3292  void *ctx;
3293  COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
3294  if (fd >= 0) {
3295    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
3296    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
3297  }
3298  SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
3299  if (common_flags()->intercept_send && res >= 0 && msg)
3300    read_msghdr(ctx, msg, res);
3301  return res;
3302}
3303#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
3304#else
3305#define INIT_SENDMSG
3306#endif
3307
3308#if SANITIZER_INTERCEPT_SENDMMSG
3309INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
3310            unsigned vlen, int flags) {
3311  void *ctx;
3312  COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
3313  if (fd >= 0) {
3314    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
3315    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
3316  }
3317  int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
3318  if (res >= 0 && msgvec) {
3319    for (int i = 0; i < res; ++i) {
3320      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
3321                                     sizeof(msgvec[i].msg_len));
3322      if (common_flags()->intercept_send)
3323        read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
3324    }
3325  }
3326  return res;
3327}
3328#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
3329#else
3330#define INIT_SENDMMSG
3331#endif
3332
3333#if SANITIZER_INTERCEPT_SYSMSG
3334INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz,
3335            int msgflg) {
3336  void *ctx;
3337  COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg);
3338  if (msgp)
3339    COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz);
3340  int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
3341  return res;
3342}
3343
3344INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz,
3345            long msgtyp, int msgflg) {
3346  void *ctx;
3347  COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
3348  SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
3349  if (len != -1)
3350    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len);
3351  return len;
3352}
3353
3354#define INIT_SYSMSG                  \
3355  COMMON_INTERCEPT_FUNCTION(msgsnd); \
3356  COMMON_INTERCEPT_FUNCTION(msgrcv);
3357#else
3358#define INIT_SYSMSG
3359#endif
3360
3361#if SANITIZER_INTERCEPT_GETPEERNAME
3362INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
3363  void *ctx;
3364  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
3365  unsigned addr_sz;
3366  if (addrlen) {
3367    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
3368    addr_sz = *addrlen;
3369  }
3370  // FIXME: under ASan the call below may write to freed memory and corrupt
3371  // its metadata. See
3372  // https://github.com/google/sanitizers/issues/321.
3373  int res = REAL(getpeername)(sockfd, addr, addrlen);
3374  if (!res && addr && addrlen) {
3375    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
3376  }
3377  return res;
3378}
3379#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
3380#else
3381#define INIT_GETPEERNAME
3382#endif
3383
3384#if SANITIZER_INTERCEPT_SYSINFO
3385INTERCEPTOR(int, sysinfo, void *info) {
3386  void *ctx;
3387  // FIXME: under ASan the call below may write to freed memory and corrupt
3388  // its metadata. See
3389  // https://github.com/google/sanitizers/issues/321.
3390  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
3391  int res = REAL(sysinfo)(info);
3392  if (!res && info)
3393    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
3394  return res;
3395}
3396#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
3397#else
3398#define INIT_SYSINFO
3399#endif
3400
3401#if SANITIZER_INTERCEPT_READDIR
3402INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
3403  void *ctx;
3404  COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
3405  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
3406  __sanitizer_dirent *res = REAL(opendir)(path);
3407  if (res)
3408    COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
3409  return res;
3410}
3411
3412INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
3413  void *ctx;
3414  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
3415  // FIXME: under ASan the call below may write to freed memory and corrupt
3416  // its metadata. See
3417  // https://github.com/google/sanitizers/issues/321.
3418  __sanitizer_dirent *res = REAL(readdir)(dirp);
3419  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
3420  return res;
3421}
3422
3423INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
3424            __sanitizer_dirent **result) {
3425  void *ctx;
3426  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
3427  // FIXME: under ASan the call below may write to freed memory and corrupt
3428  // its metadata. See
3429  // https://github.com/google/sanitizers/issues/321.
3430  int res = REAL(readdir_r)(dirp, entry, result);
3431  if (!res) {
3432    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3433    if (*result)
3434      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
3435  }
3436  return res;
3437}
3438
3439#define INIT_READDIR                  \
3440  COMMON_INTERCEPT_FUNCTION(opendir); \
3441  COMMON_INTERCEPT_FUNCTION(readdir); \
3442  COMMON_INTERCEPT_FUNCTION(readdir_r);
3443#else
3444#define INIT_READDIR
3445#endif
3446
3447#if SANITIZER_INTERCEPT_READDIR64
3448INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
3449  void *ctx;
3450  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
3451  // FIXME: under ASan the call below may write to freed memory and corrupt
3452  // its metadata. See
3453  // https://github.com/google/sanitizers/issues/321.
3454  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
3455  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
3456  return res;
3457}
3458
3459INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
3460            __sanitizer_dirent64 **result) {
3461  void *ctx;
3462  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
3463  // FIXME: under ASan the call below may write to freed memory and corrupt
3464  // its metadata. See
3465  // https://github.com/google/sanitizers/issues/321.
3466  int res = REAL(readdir64_r)(dirp, entry, result);
3467  if (!res) {
3468    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3469    if (*result)
3470      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
3471  }
3472  return res;
3473}
3474#define INIT_READDIR64                  \
3475  COMMON_INTERCEPT_FUNCTION(readdir64); \
3476  COMMON_INTERCEPT_FUNCTION(readdir64_r);
3477#else
3478#define INIT_READDIR64
3479#endif
3480
3481#if SANITIZER_INTERCEPT_PTRACE
3482INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
3483  void *ctx;
3484  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
3485  __sanitizer_iovec local_iovec;
3486
3487  if (data) {
3488    if (request == ptrace_setregs) {
3489      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
3490    } else if (request == ptrace_setfpregs) {
3491      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
3492    } else if (request == ptrace_setfpxregs) {
3493      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
3494    } else if (request == ptrace_setvfpregs) {
3495      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
3496    } else if (request == ptrace_setsiginfo) {
3497      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
3498
3499    // Some kernel might zero the iovec::iov_base in case of invalid
3500    // write access.  In this case copy the invalid address for further
3501    // inspection.
3502    } else if (request == ptrace_setregset || request == ptrace_getregset) {
3503      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
3504      COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
3505      local_iovec = *iovec;
3506      if (request == ptrace_setregset)
3507        COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
3508    }
3509  }
3510
3511  // FIXME: under ASan the call below may write to freed memory and corrupt
3512  // its metadata. See
3513  // https://github.com/google/sanitizers/issues/321.
3514  uptr res = REAL(ptrace)(request, pid, addr, data);
3515
3516  if (!res && data) {
3517    // Note that PEEK* requests assign different meaning to the return value.
3518    // This function does not handle them (nor does it need to).
3519    if (request == ptrace_getregs) {
3520      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
3521    } else if (request == ptrace_getfpregs) {
3522      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
3523    } else if (request == ptrace_getfpxregs) {
3524      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
3525    } else if (request == ptrace_getvfpregs) {
3526      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
3527    } else if (request == ptrace_getsiginfo) {
3528      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
3529    } else if (request == ptrace_geteventmsg) {
3530      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
3531    } else if (request == ptrace_getregset) {
3532      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
3533      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
3534      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
3535                                     local_iovec.iov_len);
3536    }
3537  }
3538  return res;
3539}
3540
3541#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
3542#else
3543#define INIT_PTRACE
3544#endif
3545
3546#if SANITIZER_INTERCEPT_SETLOCALE
3547static void unpoison_ctype_arrays(void *ctx) {
3548#if SANITIZER_NETBSD
3549  // These arrays contain 256 regular elements in unsigned char range + 1 EOF
3550  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short));
3551  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short));
3552  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short));
3553#endif
3554}
3555
3556INTERCEPTOR(char *, setlocale, int category, char *locale) {
3557  void *ctx;
3558  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
3559  if (locale)
3560    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, internal_strlen(locale) + 1);
3561  char *res = REAL(setlocale)(category, locale);
3562  if (res) {
3563    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
3564    unpoison_ctype_arrays(ctx);
3565  }
3566  return res;
3567}
3568
3569#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
3570#else
3571#define INIT_SETLOCALE
3572#endif
3573
3574#if SANITIZER_INTERCEPT_GETCWD
3575INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
3576  void *ctx;
3577  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
3578  // FIXME: under ASan the call below may write to freed memory and corrupt
3579  // its metadata. See
3580  // https://github.com/google/sanitizers/issues/321.
3581  char *res = REAL(getcwd)(buf, size);
3582  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
3583  return res;
3584}
3585#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
3586#else
3587#define INIT_GETCWD
3588#endif
3589
3590#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
3591INTERCEPTOR(char *, get_current_dir_name, int fake) {
3592  void *ctx;
3593  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
3594  // FIXME: under ASan the call below may write to freed memory and corrupt
3595  // its metadata. See
3596  // https://github.com/google/sanitizers/issues/321.
3597  char *res = REAL(get_current_dir_name)(fake);
3598  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
3599  return res;
3600}
3601
3602#define INIT_GET_CURRENT_DIR_NAME \
3603  COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
3604#else
3605#define INIT_GET_CURRENT_DIR_NAME
3606#endif
3607
3608UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
3609  CHECK(endptr);
3610  if (nptr == *endptr) {
3611    // No digits were found at strtol call, we need to find out the last
3612    // symbol accessed by strtoll on our own.
3613    // We get this symbol by skipping leading blanks and optional +/- sign.
3614    while (IsSpace(*nptr)) nptr++;
3615    if (*nptr == '+' || *nptr == '-') nptr++;
3616    *endptr = const_cast<char *>(nptr);
3617  }
3618  CHECK(*endptr >= nptr);
3619}
3620
3621UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
3622                             char **endptr, char *real_endptr, int base) {
3623  if (endptr) {
3624    *endptr = real_endptr;
3625    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
3626  }
3627  // If base has unsupported value, strtol can exit with EINVAL
3628  // without reading any characters. So do additional checks only
3629  // if base is valid.
3630  bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
3631  if (is_valid_base) {
3632    FixRealStrtolEndptr(nptr, &real_endptr);
3633  }
3634  COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
3635                                 (real_endptr - nptr) + 1 : 0);
3636}
3637
3638
3639#if SANITIZER_INTERCEPT_STRTOIMAX
3640INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
3641  void *ctx;
3642  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
3643  // FIXME: under ASan the call below may write to freed memory and corrupt
3644  // its metadata. See
3645  // https://github.com/google/sanitizers/issues/321.
3646  char *real_endptr;
3647  INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
3648  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
3649  return res;
3650}
3651
3652INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
3653  void *ctx;
3654  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
3655  // FIXME: under ASan the call below may write to freed memory and corrupt
3656  // its metadata. See
3657  // https://github.com/google/sanitizers/issues/321.
3658  char *real_endptr;
3659  UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
3660  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
3661  return res;
3662}
3663
3664#define INIT_STRTOIMAX                  \
3665  COMMON_INTERCEPT_FUNCTION(strtoimax); \
3666  COMMON_INTERCEPT_FUNCTION(strtoumax);
3667#else
3668#define INIT_STRTOIMAX
3669#endif
3670
3671#if SANITIZER_INTERCEPT_MBSTOWCS
3672INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
3673  void *ctx;
3674  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
3675  // FIXME: under ASan the call below may write to freed memory and corrupt
3676  // its metadata. See
3677  // https://github.com/google/sanitizers/issues/321.
3678  SIZE_T res = REAL(mbstowcs)(dest, src, len);
3679  if (res != (SIZE_T) - 1 && dest) {
3680    SIZE_T write_cnt = res + (res < len);
3681    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
3682  }
3683  return res;
3684}
3685
3686INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
3687            void *ps) {
3688  void *ctx;
3689  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
3690  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3691  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3692  // FIXME: under ASan the call below may write to freed memory and corrupt
3693  // its metadata. See
3694  // https://github.com/google/sanitizers/issues/321.
3695  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
3696  if (res != (SIZE_T)(-1) && dest && src) {
3697    // This function, and several others, may or may not write the terminating
3698    // \0 character. They write it iff they clear *src.
3699    SIZE_T write_cnt = res + !*src;
3700    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
3701  }
3702  return res;
3703}
3704
3705#define INIT_MBSTOWCS                  \
3706  COMMON_INTERCEPT_FUNCTION(mbstowcs); \
3707  COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
3708#else
3709#define INIT_MBSTOWCS
3710#endif
3711
3712#if SANITIZER_INTERCEPT_MBSNRTOWCS
3713INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
3714            SIZE_T len, void *ps) {
3715  void *ctx;
3716  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
3717  if (src) {
3718    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3719    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
3720  }
3721  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3722  // FIXME: under ASan the call below may write to freed memory and corrupt
3723  // its metadata. See
3724  // https://github.com/google/sanitizers/issues/321.
3725  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
3726  if (res != (SIZE_T)(-1) && dest && src) {
3727    SIZE_T write_cnt = res + !*src;
3728    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
3729  }
3730  return res;
3731}
3732
3733#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
3734#else
3735#define INIT_MBSNRTOWCS
3736#endif
3737
3738#if SANITIZER_INTERCEPT_WCSTOMBS
3739INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
3740  void *ctx;
3741  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
3742  // FIXME: under ASan the call below may write to freed memory and corrupt
3743  // its metadata. See
3744  // https://github.com/google/sanitizers/issues/321.
3745  SIZE_T res = REAL(wcstombs)(dest, src, len);
3746  if (res != (SIZE_T) - 1 && dest) {
3747    SIZE_T write_cnt = res + (res < len);
3748    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
3749  }
3750  return res;
3751}
3752
3753INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
3754            void *ps) {
3755  void *ctx;
3756  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
3757  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3758  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3759  // FIXME: under ASan the call below may write to freed memory and corrupt
3760  // its metadata. See
3761  // https://github.com/google/sanitizers/issues/321.
3762  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
3763  if (res != (SIZE_T) - 1 && dest && src) {
3764    SIZE_T write_cnt = res + !*src;
3765    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
3766  }
3767  return res;
3768}
3769
3770#define INIT_WCSTOMBS                  \
3771  COMMON_INTERCEPT_FUNCTION(wcstombs); \
3772  COMMON_INTERCEPT_FUNCTION(wcsrtombs);
3773#else
3774#define INIT_WCSTOMBS
3775#endif
3776
3777#if SANITIZER_INTERCEPT_WCSNRTOMBS
3778INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
3779            SIZE_T len, void *ps) {
3780  void *ctx;
3781  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
3782  if (src) {
3783    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3784    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
3785  }
3786  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3787  // FIXME: under ASan the call below may write to freed memory and corrupt
3788  // its metadata. See
3789  // https://github.com/google/sanitizers/issues/321.
3790  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
3791  if (res != ((SIZE_T)-1) && dest && src) {
3792    SIZE_T write_cnt = res + !*src;
3793    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
3794  }
3795  return res;
3796}
3797
3798#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
3799#else
3800#define INIT_WCSNRTOMBS
3801#endif
3802
3803
3804#if SANITIZER_INTERCEPT_WCRTOMB
3805INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
3806  void *ctx;
3807  COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
3808  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3809
3810  if (!dest)
3811    return REAL(wcrtomb)(dest, src, ps);
3812
3813  char local_dest[32];
3814  SIZE_T res = REAL(wcrtomb)(local_dest, src, ps);
3815  if (res != ((SIZE_T)-1)) {
3816    CHECK_LE(res, sizeof(local_dest));
3817    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
3818    REAL(memcpy)(dest, local_dest, res);
3819  }
3820  return res;
3821}
3822
3823#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
3824#else
3825#define INIT_WCRTOMB
3826#endif
3827
3828#if SANITIZER_INTERCEPT_WCTOMB
3829INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
3830  void *ctx;
3831  COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src);
3832  if (!dest)
3833    return REAL(wctomb)(dest, src);
3834
3835  char local_dest[32];
3836  int res = REAL(wctomb)(local_dest, src);
3837  if (res != -1) {
3838    CHECK_LE(res, sizeof(local_dest));
3839    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
3840    REAL(memcpy)(dest, local_dest, res);
3841  }
3842  return res;
3843}
3844
3845#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb);
3846#else
3847#define INIT_WCTOMB
3848#endif
3849
3850#if SANITIZER_INTERCEPT_TCGETATTR
3851INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
3852  void *ctx;
3853  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
3854  // FIXME: under ASan the call below may write to freed memory and corrupt
3855  // its metadata. See
3856  // https://github.com/google/sanitizers/issues/321.
3857  int res = REAL(tcgetattr)(fd, termios_p);
3858  if (!res && termios_p)
3859    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
3860  return res;
3861}
3862
3863#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
3864#else
3865#define INIT_TCGETATTR
3866#endif
3867
3868#if SANITIZER_INTERCEPT_REALPATH
3869INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
3870  void *ctx;
3871  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
3872  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
3873
3874  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
3875  // version of a versioned symbol. For realpath(), this gives us something
3876  // (called __old_realpath) that does not handle NULL in the second argument.
3877  // Handle it as part of the interceptor.
3878  char *allocated_path = nullptr;
3879  if (!resolved_path)
3880    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
3881
3882  char *res = REAL(realpath)(path, resolved_path);
3883  if (allocated_path && !res)
3884    WRAP(free)(allocated_path);
3885  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
3886  return res;
3887}
3888#  define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
3889#else
3890#define INIT_REALPATH
3891#endif
3892
3893#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
3894INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
3895  void *ctx;
3896  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
3897  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
3898  char *res = REAL(canonicalize_file_name)(path);
3899  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
3900  return res;
3901}
3902#define INIT_CANONICALIZE_FILE_NAME \
3903  COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
3904#else
3905#define INIT_CANONICALIZE_FILE_NAME
3906#endif
3907
3908#if SANITIZER_INTERCEPT_CONFSTR
3909INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
3910  void *ctx;
3911  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
3912  // FIXME: under ASan the call below may write to freed memory and corrupt
3913  // its metadata. See
3914  // https://github.com/google/sanitizers/issues/321.
3915  SIZE_T res = REAL(confstr)(name, buf, len);
3916  if (buf && res)
3917    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
3918  return res;
3919}
3920#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
3921#else
3922#define INIT_CONFSTR
3923#endif
3924
3925#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
3926INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
3927  void *ctx;
3928  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
3929  // FIXME: under ASan the call below may write to freed memory and corrupt
3930  // its metadata. See
3931  // https://github.com/google/sanitizers/issues/321.
3932  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
3933  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
3934  return res;
3935}
3936#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
3937#else
3938#define INIT_SCHED_GETAFFINITY
3939#endif
3940
3941#if SANITIZER_INTERCEPT_SCHED_GETPARAM
3942INTERCEPTOR(int, sched_getparam, int pid, void *param) {
3943  void *ctx;
3944  COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
3945  int res = REAL(sched_getparam)(pid, param);
3946  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
3947  return res;
3948}
3949#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
3950#else
3951#define INIT_SCHED_GETPARAM
3952#endif
3953
3954#if SANITIZER_INTERCEPT_STRERROR
3955INTERCEPTOR(char *, strerror, int errnum) {
3956  void *ctx;
3957  COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
3958  COMMON_INTERCEPTOR_STRERROR();
3959  char *res = REAL(strerror)(errnum);
3960  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
3961  return res;
3962}
3963#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
3964#else
3965#define INIT_STRERROR
3966#endif
3967
3968#if SANITIZER_INTERCEPT_STRERROR_R
3969// There are 2 versions of strerror_r:
3970//  * POSIX version returns 0 on success, negative error code on failure,
3971//    writes message to buf.
3972//  * GNU version returns message pointer, which points to either buf or some
3973//    static storage.
3974#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
3975    SANITIZER_APPLE || SANITIZER_ANDROID || SANITIZER_NETBSD ||                 \
3976    SANITIZER_FREEBSD
3977// POSIX version. Spec is not clear on whether buf is NULL-terminated.
3978// At least on OSX, buf contents are valid even when the call fails.
3979INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
3980  void *ctx;
3981  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
3982  // FIXME: under ASan the call below may write to freed memory and corrupt
3983  // its metadata. See
3984  // https://github.com/google/sanitizers/issues/321.
3985  int res = REAL(strerror_r)(errnum, buf, buflen);
3986
3987  SIZE_T sz = internal_strnlen(buf, buflen);
3988  if (sz < buflen) ++sz;
3989  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
3990  return res;
3991}
3992#else
3993// GNU version.
3994INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
3995  void *ctx;
3996  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
3997  // FIXME: under ASan the call below may write to freed memory and corrupt
3998  // its metadata. See
3999  // https://github.com/google/sanitizers/issues/321.
4000  char *res = REAL(strerror_r)(errnum, buf, buflen);
4001  if (res == buf)
4002    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
4003  else
4004    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
4005  return res;
4006}
4007#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
4008       //SANITIZER_APPLE
4009#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
4010#else
4011#define INIT_STRERROR_R
4012#endif
4013
4014#if SANITIZER_INTERCEPT_XPG_STRERROR_R
4015INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
4016  void *ctx;
4017  COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
4018  // FIXME: under ASan the call below may write to freed memory and corrupt
4019  // its metadata. See
4020  // https://github.com/google/sanitizers/issues/321.
4021  int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
4022  // This version always returns a null-terminated string.
4023  if (buf && buflen)
4024    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
4025  return res;
4026}
4027#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
4028#else
4029#define INIT_XPG_STRERROR_R
4030#endif
4031
4032#if SANITIZER_INTERCEPT_SCANDIR
4033typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
4034typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
4035                                const struct __sanitizer_dirent **);
4036
4037static THREADLOCAL scandir_filter_f scandir_filter;
4038static THREADLOCAL scandir_compar_f scandir_compar;
4039
4040static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
4041  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
4042  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
4043  return scandir_filter(dir);
4044}
4045
4046static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
4047                                  const struct __sanitizer_dirent **b) {
4048  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
4049  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
4050  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
4051  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
4052  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
4053  return scandir_compar(a, b);
4054}
4055
4056INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
4057            scandir_filter_f filter, scandir_compar_f compar) {
4058  void *ctx;
4059  COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
4060  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
4061  scandir_filter = filter;
4062  scandir_compar = compar;
4063  // FIXME: under ASan the call below may write to freed memory and corrupt
4064  // its metadata. See
4065  // https://github.com/google/sanitizers/issues/321.
4066  int res = REAL(scandir)(dirp, namelist,
4067                          filter ? wrapped_scandir_filter : nullptr,
4068                          compar ? wrapped_scandir_compar : nullptr);
4069  scandir_filter = nullptr;
4070  scandir_compar = nullptr;
4071  if (namelist && res > 0) {
4072    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
4073    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
4074    for (int i = 0; i < res; ++i)
4075      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
4076                                     (*namelist)[i]->d_reclen);
4077  }
4078  return res;
4079}
4080#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
4081#else
4082#define INIT_SCANDIR
4083#endif
4084
4085#if SANITIZER_INTERCEPT_SCANDIR64
4086typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
4087typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
4088                                  const struct __sanitizer_dirent64 **);
4089
4090static THREADLOCAL scandir64_filter_f scandir64_filter;
4091static THREADLOCAL scandir64_compar_f scandir64_compar;
4092
4093static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
4094  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
4095  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
4096  return scandir64_filter(dir);
4097}
4098
4099static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
4100                                    const struct __sanitizer_dirent64 **b) {
4101  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
4102  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
4103  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
4104  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
4105  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
4106  return scandir64_compar(a, b);
4107}
4108
4109INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
4110            scandir64_filter_f filter, scandir64_compar_f compar) {
4111  void *ctx;
4112  COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
4113  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
4114  scandir64_filter = filter;
4115  scandir64_compar = compar;
4116  // FIXME: under ASan the call below may write to freed memory and corrupt
4117  // its metadata. See
4118  // https://github.com/google/sanitizers/issues/321.
4119  int res =
4120      REAL(scandir64)(dirp, namelist,
4121                      filter ? wrapped_scandir64_filter : nullptr,
4122                      compar ? wrapped_scandir64_compar : nullptr);
4123  scandir64_filter = nullptr;
4124  scandir64_compar = nullptr;
4125  if (namelist && res > 0) {
4126    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
4127    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
4128    for (int i = 0; i < res; ++i)
4129      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
4130                                     (*namelist)[i]->d_reclen);
4131  }
4132  return res;
4133}
4134#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
4135#else
4136#define INIT_SCANDIR64
4137#endif
4138
4139#if SANITIZER_INTERCEPT_GETGROUPS
4140INTERCEPTOR(int, getgroups, int size, u32 *lst) {
4141  void *ctx;
4142  COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
4143  // FIXME: under ASan the call below may write to freed memory and corrupt
4144  // its metadata. See
4145  // https://github.com/google/sanitizers/issues/321.
4146  int res = REAL(getgroups)(size, lst);
4147  if (res >= 0 && lst && size > 0)
4148    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
4149  return res;
4150}
4151#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
4152#else
4153#define INIT_GETGROUPS
4154#endif
4155
4156#if SANITIZER_INTERCEPT_POLL
4157static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
4158                        __sanitizer_nfds_t nfds) {
4159  for (unsigned i = 0; i < nfds; ++i) {
4160    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
4161    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
4162  }
4163}
4164
4165static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
4166                         __sanitizer_nfds_t nfds) {
4167  for (unsigned i = 0; i < nfds; ++i)
4168    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
4169                                   sizeof(fds[i].revents));
4170}
4171
4172INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
4173            int timeout) {
4174  void *ctx;
4175  COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
4176  if (fds && nfds) read_pollfd(ctx, fds, nfds);
4177  int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
4178  if (fds && nfds) write_pollfd(ctx, fds, nfds);
4179  return res;
4180}
4181#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
4182#else
4183#define INIT_POLL
4184#endif
4185
4186#if SANITIZER_INTERCEPT_PPOLL
4187INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
4188            void *timeout_ts, __sanitizer_sigset_t *sigmask) {
4189  void *ctx;
4190  COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
4191  if (fds && nfds) read_pollfd(ctx, fds, nfds);
4192  if (timeout_ts)
4193    COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
4194  if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
4195  int res =
4196      COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
4197  if (fds && nfds) write_pollfd(ctx, fds, nfds);
4198  return res;
4199}
4200#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
4201#else
4202#define INIT_PPOLL
4203#endif
4204
4205#if SANITIZER_INTERCEPT_WORDEXP
4206INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
4207  void *ctx;
4208  COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
4209  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
4210  // FIXME: under ASan the call below may write to freed memory and corrupt
4211  // its metadata. See
4212  // https://github.com/google/sanitizers/issues/321.
4213  int res = REAL(wordexp)(s, p, flags);
4214  if (!res && p) {
4215    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
4216    uptr we_wordc =
4217        ((flags & wordexp_wrde_dooffs) ? p->we_offs : 0) + p->we_wordc;
4218    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
4219                                   sizeof(*p->we_wordv) * (we_wordc + 1));
4220    for (uptr i = 0; i < we_wordc; ++i) {
4221      char *w = p->we_wordv[i];
4222      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1);
4223    }
4224  }
4225  return res;
4226}
4227#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
4228#else
4229#define INIT_WORDEXP
4230#endif
4231
4232#if SANITIZER_INTERCEPT_SIGWAIT
4233INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
4234  void *ctx;
4235  COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
4236  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4237  // FIXME: under ASan the call below may write to freed memory and corrupt
4238  // its metadata. See
4239  // https://github.com/google/sanitizers/issues/321.
4240  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwait)(set, sig);
4241  if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
4242  return res;
4243}
4244#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
4245#else
4246#define INIT_SIGWAIT
4247#endif
4248
4249#if SANITIZER_INTERCEPT_SIGWAITINFO
4250INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
4251  void *ctx;
4252  COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
4253  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4254  // FIXME: under ASan the call below may write to freed memory and corrupt
4255  // its metadata. See
4256  // https://github.com/google/sanitizers/issues/321.
4257  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwaitinfo)(set, info);
4258  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
4259  return res;
4260}
4261#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
4262#else
4263#define INIT_SIGWAITINFO
4264#endif
4265
4266#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
4267INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
4268            void *timeout) {
4269  void *ctx;
4270  COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
4271  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
4272  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4273  // FIXME: under ASan the call below may write to freed memory and corrupt
4274  // its metadata. See
4275  // https://github.com/google/sanitizers/issues/321.
4276  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigtimedwait)(set, info, timeout);
4277  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
4278  return res;
4279}
4280#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
4281#else
4282#define INIT_SIGTIMEDWAIT
4283#endif
4284
4285#if SANITIZER_INTERCEPT_SIGSETOPS
4286INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
4287  void *ctx;
4288  COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
4289  // FIXME: under ASan the call below may write to freed memory and corrupt
4290  // its metadata. See
4291  // https://github.com/google/sanitizers/issues/321.
4292  int res = REAL(sigemptyset)(set);
4293  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
4294  return res;
4295}
4296
4297INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
4298  void *ctx;
4299  COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
4300  // FIXME: under ASan the call below may write to freed memory and corrupt
4301  // its metadata. See
4302  // https://github.com/google/sanitizers/issues/321.
4303  int res = REAL(sigfillset)(set);
4304  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
4305  return res;
4306}
4307#define INIT_SIGSETOPS                    \
4308  COMMON_INTERCEPT_FUNCTION(sigemptyset); \
4309  COMMON_INTERCEPT_FUNCTION(sigfillset);
4310#else
4311#define INIT_SIGSETOPS
4312#endif
4313
4314#if SANITIZER_INTERCEPT_SIGSET_LOGICOPS
4315INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst,
4316            __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
4317  void *ctx;
4318  COMMON_INTERCEPTOR_ENTER(ctx, sigandset, dst, src1, src2);
4319  if (src1)
4320    COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
4321  if (src2)
4322    COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
4323  int res = REAL(sigandset)(dst, src1, src2);
4324  if (!res && dst)
4325    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
4326  return res;
4327}
4328
4329INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst,
4330            __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
4331  void *ctx;
4332  COMMON_INTERCEPTOR_ENTER(ctx, sigorset, dst, src1, src2);
4333  if (src1)
4334    COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
4335  if (src2)
4336    COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
4337  int res = REAL(sigorset)(dst, src1, src2);
4338  if (!res && dst)
4339    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
4340  return res;
4341}
4342#define INIT_SIGSET_LOGICOPS                    \
4343  COMMON_INTERCEPT_FUNCTION(sigandset);   \
4344  COMMON_INTERCEPT_FUNCTION(sigorset);
4345#else
4346#define INIT_SIGSET_LOGICOPS
4347#endif
4348
4349#if SANITIZER_INTERCEPT_SIGPENDING
4350INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
4351  void *ctx;
4352  COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
4353  // FIXME: under ASan the call below may write to freed memory and corrupt
4354  // its metadata. See
4355  // https://github.com/google/sanitizers/issues/321.
4356  int res = REAL(sigpending)(set);
4357  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
4358  return res;
4359}
4360#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
4361#else
4362#define INIT_SIGPENDING
4363#endif
4364
4365#if SANITIZER_INTERCEPT_SIGPROCMASK
4366INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
4367            __sanitizer_sigset_t *oldset) {
4368  void *ctx;
4369  COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
4370  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4371  // FIXME: under ASan the call below may write to freed memory and corrupt
4372  // its metadata. See
4373  // https://github.com/google/sanitizers/issues/321.
4374  int res = REAL(sigprocmask)(how, set, oldset);
4375  if (!res && oldset)
4376    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
4377  return res;
4378}
4379#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
4380#else
4381#define INIT_SIGPROCMASK
4382#endif
4383
4384#if SANITIZER_INTERCEPT_PTHREAD_SIGMASK
4385INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
4386            __sanitizer_sigset_t *oldset) {
4387  void *ctx;
4388  COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
4389  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4390  // FIXME: under ASan the call below may write to freed memory and corrupt
4391  // its metadata. See
4392  // https://github.com/google/sanitizers/issues/321.
4393  int res = REAL(pthread_sigmask)(how, set, oldset);
4394  if (!res && oldset)
4395    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
4396  return res;
4397}
4398#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask);
4399#else
4400#define INIT_PTHREAD_SIGMASK
4401#endif
4402
4403#if SANITIZER_INTERCEPT_BACKTRACE
4404INTERCEPTOR(int, backtrace, void **buffer, int size) {
4405  void *ctx;
4406  COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
4407  // FIXME: under ASan the call below may write to freed memory and corrupt
4408  // its metadata. See
4409  // https://github.com/google/sanitizers/issues/321.
4410  int res = REAL(backtrace)(buffer, size);
4411  if (res && buffer)
4412    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
4413  return res;
4414}
4415
4416INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
4417  void *ctx;
4418  COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
4419  if (buffer && size)
4420    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
4421  // FIXME: under ASan the call below may write to freed memory and corrupt
4422  // its metadata. See
4423  // https://github.com/google/sanitizers/issues/321.
4424  char **res = REAL(backtrace_symbols)(buffer, size);
4425  if (res && size) {
4426    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
4427    for (int i = 0; i < size; ++i)
4428      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], internal_strlen(res[i]) + 1);
4429  }
4430  return res;
4431}
4432#define INIT_BACKTRACE                  \
4433  COMMON_INTERCEPT_FUNCTION(backtrace); \
4434  COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
4435#else
4436#define INIT_BACKTRACE
4437#endif
4438
4439#if SANITIZER_INTERCEPT__EXIT
4440INTERCEPTOR(void, _exit, int status) {
4441  void *ctx;
4442  COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
4443  COMMON_INTERCEPTOR_USER_CALLBACK_START();
4444  int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
4445  COMMON_INTERCEPTOR_USER_CALLBACK_END();
4446  if (status == 0) status = status1;
4447  REAL(_exit)(status);
4448}
4449#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
4450#else
4451#define INIT__EXIT
4452#endif
4453
4454#if SANITIZER_INTERCEPT_PTHREAD_MUTEX
4455INTERCEPTOR(int, pthread_mutex_lock, void *m) {
4456  void *ctx;
4457  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
4458  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
4459  int res = REAL(pthread_mutex_lock)(m);
4460  if (res == errno_EOWNERDEAD)
4461    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
4462  if (res == 0 || res == errno_EOWNERDEAD)
4463    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
4464  if (res == errno_EINVAL)
4465    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4466  return res;
4467}
4468
4469INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
4470  void *ctx;
4471  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
4472  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
4473  int res = REAL(pthread_mutex_unlock)(m);
4474  if (res == errno_EINVAL)
4475    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4476  return res;
4477}
4478
4479#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
4480#define INIT_PTHREAD_MUTEX_UNLOCK \
4481  COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
4482#else
4483#define INIT_PTHREAD_MUTEX_LOCK
4484#define INIT_PTHREAD_MUTEX_UNLOCK
4485#endif
4486
4487#if SANITIZER_INTERCEPT___PTHREAD_MUTEX
4488INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
4489  void *ctx;
4490  COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m);
4491  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
4492  int res = REAL(__pthread_mutex_lock)(m);
4493  if (res == errno_EOWNERDEAD)
4494    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
4495  if (res == 0 || res == errno_EOWNERDEAD)
4496    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
4497  if (res == errno_EINVAL)
4498    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4499  return res;
4500}
4501
4502INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
4503  void *ctx;
4504  COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m);
4505  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
4506  int res = REAL(__pthread_mutex_unlock)(m);
4507  if (res == errno_EINVAL)
4508    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4509  return res;
4510}
4511
4512#define INIT___PTHREAD_MUTEX_LOCK \
4513  COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock)
4514#define INIT___PTHREAD_MUTEX_UNLOCK \
4515  COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock)
4516#else
4517#define INIT___PTHREAD_MUTEX_LOCK
4518#define INIT___PTHREAD_MUTEX_UNLOCK
4519#endif
4520
4521#if SANITIZER_INTERCEPT___LIBC_MUTEX
4522INTERCEPTOR(int, __libc_mutex_lock, void *m)
4523ALIAS(WRAPPER_NAME(pthread_mutex_lock));
4524
4525INTERCEPTOR(int, __libc_mutex_unlock, void *m)
4526ALIAS(WRAPPER_NAME(pthread_mutex_unlock));
4527
4528INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate)
4529ALIAS(WRAPPER_NAME(pthread_setcancelstate));
4530
4531#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock)
4532#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock)
4533#define INIT___LIBC_THR_SETCANCELSTATE \
4534  COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate)
4535#else
4536#define INIT___LIBC_MUTEX_LOCK
4537#define INIT___LIBC_MUTEX_UNLOCK
4538#define INIT___LIBC_THR_SETCANCELSTATE
4539#endif
4540
4541#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
4542static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
4543  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
4544  if (mnt->mnt_fsname)
4545    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
4546                                   internal_strlen(mnt->mnt_fsname) + 1);
4547  if (mnt->mnt_dir)
4548    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
4549                                   internal_strlen(mnt->mnt_dir) + 1);
4550  if (mnt->mnt_type)
4551    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
4552                                   internal_strlen(mnt->mnt_type) + 1);
4553  if (mnt->mnt_opts)
4554    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
4555                                   internal_strlen(mnt->mnt_opts) + 1);
4556}
4557#endif
4558
4559#if SANITIZER_INTERCEPT_GETMNTENT
4560INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
4561  void *ctx;
4562  COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
4563  __sanitizer_mntent *res = REAL(getmntent)(fp);
4564  if (res) write_mntent(ctx, res);
4565  return res;
4566}
4567#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
4568#else
4569#define INIT_GETMNTENT
4570#endif
4571
4572#if SANITIZER_INTERCEPT_GETMNTENT_R
4573INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
4574            __sanitizer_mntent *mntbuf, char *buf, int buflen) {
4575  void *ctx;
4576  COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
4577  __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
4578  if (res) write_mntent(ctx, res);
4579  return res;
4580}
4581#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
4582#else
4583#define INIT_GETMNTENT_R
4584#endif
4585
4586#if SANITIZER_INTERCEPT_STATFS
4587INTERCEPTOR(int, statfs, char *path, void *buf) {
4588  void *ctx;
4589  COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
4590  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
4591  // FIXME: under ASan the call below may write to freed memory and corrupt
4592  // its metadata. See
4593  // https://github.com/google/sanitizers/issues/321.
4594  int res = REAL(statfs)(path, buf);
4595  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
4596  return res;
4597}
4598INTERCEPTOR(int, fstatfs, int fd, void *buf) {
4599  void *ctx;
4600  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
4601  // FIXME: under ASan the call below may write to freed memory and corrupt
4602  // its metadata. See
4603  // https://github.com/google/sanitizers/issues/321.
4604  int res = REAL(fstatfs)(fd, buf);
4605  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
4606  return res;
4607}
4608#define INIT_STATFS                  \
4609  COMMON_INTERCEPT_FUNCTION(statfs); \
4610  COMMON_INTERCEPT_FUNCTION(fstatfs);
4611#else
4612#define INIT_STATFS
4613#endif
4614
4615#if SANITIZER_INTERCEPT_STATFS64
4616INTERCEPTOR(int, statfs64, char *path, void *buf) {
4617  void *ctx;
4618  COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
4619  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
4620  // FIXME: under ASan the call below may write to freed memory and corrupt
4621  // its metadata. See
4622  // https://github.com/google/sanitizers/issues/321.
4623  int res = REAL(statfs64)(path, buf);
4624  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
4625  return res;
4626}
4627INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
4628  void *ctx;
4629  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
4630  // FIXME: under ASan the call below may write to freed memory and corrupt
4631  // its metadata. See
4632  // https://github.com/google/sanitizers/issues/321.
4633  int res = REAL(fstatfs64)(fd, buf);
4634  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
4635  return res;
4636}
4637#define INIT_STATFS64                  \
4638  COMMON_INTERCEPT_FUNCTION(statfs64); \
4639  COMMON_INTERCEPT_FUNCTION(fstatfs64);
4640#else
4641#define INIT_STATFS64
4642#endif
4643
4644#if SANITIZER_INTERCEPT_STATVFS
4645INTERCEPTOR(int, statvfs, char *path, void *buf) {
4646  void *ctx;
4647  COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
4648  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
4649  // FIXME: under ASan the call below may write to freed memory and corrupt
4650  // its metadata. See
4651  // https://github.com/google/sanitizers/issues/321.
4652  int res = REAL(statvfs)(path, buf);
4653  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
4654  return res;
4655}
4656INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
4657  void *ctx;
4658  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
4659  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
4660  // FIXME: under ASan the call below may write to freed memory and corrupt
4661  // its metadata. See
4662  // https://github.com/google/sanitizers/issues/321.
4663  int res = REAL(fstatvfs)(fd, buf);
4664  if (!res) {
4665    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
4666    if (fd >= 0)
4667      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
4668  }
4669  return res;
4670}
4671#define INIT_STATVFS                  \
4672  COMMON_INTERCEPT_FUNCTION(statvfs); \
4673  COMMON_INTERCEPT_FUNCTION(fstatvfs);
4674#else
4675#define INIT_STATVFS
4676#endif
4677
4678#if SANITIZER_INTERCEPT_STATVFS64
4679INTERCEPTOR(int, statvfs64, char *path, void *buf) {
4680  void *ctx;
4681  COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
4682  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
4683  // FIXME: under ASan the call below may write to freed memory and corrupt
4684  // its metadata. See
4685  // https://github.com/google/sanitizers/issues/321.
4686  int res = REAL(statvfs64)(path, buf);
4687  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
4688  return res;
4689}
4690INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
4691  void *ctx;
4692  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
4693  // FIXME: under ASan the call below may write to freed memory and corrupt
4694  // its metadata. See
4695  // https://github.com/google/sanitizers/issues/321.
4696  int res = REAL(fstatvfs64)(fd, buf);
4697  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
4698  return res;
4699}
4700#define INIT_STATVFS64                  \
4701  COMMON_INTERCEPT_FUNCTION(statvfs64); \
4702  COMMON_INTERCEPT_FUNCTION(fstatvfs64);
4703#else
4704#define INIT_STATVFS64
4705#endif
4706
4707#if SANITIZER_INTERCEPT_INITGROUPS
4708INTERCEPTOR(int, initgroups, char *user, u32 group) {
4709  void *ctx;
4710  COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
4711  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, internal_strlen(user) + 1);
4712  int res = REAL(initgroups)(user, group);
4713  return res;
4714}
4715#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
4716#else
4717#define INIT_INITGROUPS
4718#endif
4719
4720#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
4721INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
4722  void *ctx;
4723  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
4724  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
4725  char *res = REAL(ether_ntoa)(addr);
4726  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
4727  return res;
4728}
4729INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
4730  void *ctx;
4731  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
4732  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
4733  __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
4734  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
4735  return res;
4736}
4737#define INIT_ETHER_NTOA_ATON             \
4738  COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
4739  COMMON_INTERCEPT_FUNCTION(ether_aton);
4740#else
4741#define INIT_ETHER_NTOA_ATON
4742#endif
4743
4744#if SANITIZER_INTERCEPT_ETHER_HOST
4745INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
4746  void *ctx;
4747  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
4748  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
4749  // FIXME: under ASan the call below may write to freed memory and corrupt
4750  // its metadata. See
4751  // https://github.com/google/sanitizers/issues/321.
4752  int res = REAL(ether_ntohost)(hostname, addr);
4753  if (!res && hostname)
4754    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
4755  return res;
4756}
4757INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
4758  void *ctx;
4759  COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
4760  if (hostname)
4761    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
4762  // FIXME: under ASan the call below may write to freed memory and corrupt
4763  // its metadata. See
4764  // https://github.com/google/sanitizers/issues/321.
4765  int res = REAL(ether_hostton)(hostname, addr);
4766  if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
4767  return res;
4768}
4769INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
4770            char *hostname) {
4771  void *ctx;
4772  COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
4773  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, internal_strlen(line) + 1);
4774  // FIXME: under ASan the call below may write to freed memory and corrupt
4775  // its metadata. See
4776  // https://github.com/google/sanitizers/issues/321.
4777  int res = REAL(ether_line)(line, addr, hostname);
4778  if (!res) {
4779    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
4780    if (hostname)
4781      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
4782  }
4783  return res;
4784}
4785#define INIT_ETHER_HOST                     \
4786  COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
4787  COMMON_INTERCEPT_FUNCTION(ether_hostton); \
4788  COMMON_INTERCEPT_FUNCTION(ether_line);
4789#else
4790#define INIT_ETHER_HOST
4791#endif
4792
4793#if SANITIZER_INTERCEPT_ETHER_R
4794INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
4795  void *ctx;
4796  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
4797  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
4798  // FIXME: under ASan the call below may write to freed memory and corrupt
4799  // its metadata. See
4800  // https://github.com/google/sanitizers/issues/321.
4801  char *res = REAL(ether_ntoa_r)(addr, buf);
4802  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
4803  return res;
4804}
4805INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
4806            __sanitizer_ether_addr *addr) {
4807  void *ctx;
4808  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
4809  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
4810  // FIXME: under ASan the call below may write to freed memory and corrupt
4811  // its metadata. See
4812  // https://github.com/google/sanitizers/issues/321.
4813  __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
4814  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
4815  return res;
4816}
4817#define INIT_ETHER_R                       \
4818  COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
4819  COMMON_INTERCEPT_FUNCTION(ether_aton_r);
4820#else
4821#define INIT_ETHER_R
4822#endif
4823
4824#if SANITIZER_INTERCEPT_SHMCTL
4825INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
4826  void *ctx;
4827  COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
4828  // FIXME: under ASan the call below may write to freed memory and corrupt
4829  // its metadata. See
4830  // https://github.com/google/sanitizers/issues/321.
4831  int res = REAL(shmctl)(shmid, cmd, buf);
4832  if (res >= 0) {
4833    unsigned sz = 0;
4834    if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
4835      sz = sizeof(__sanitizer_shmid_ds);
4836    else if (cmd == shmctl_ipc_info)
4837      sz = struct_shminfo_sz;
4838    else if (cmd == shmctl_shm_info)
4839      sz = struct_shm_info_sz;
4840    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
4841  }
4842  return res;
4843}
4844#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
4845#else
4846#define INIT_SHMCTL
4847#endif
4848
4849#if SANITIZER_INTERCEPT_RANDOM_R
4850INTERCEPTOR(int, random_r, void *buf, u32 *result) {
4851  void *ctx;
4852  COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
4853  // FIXME: under ASan the call below may write to freed memory and corrupt
4854  // its metadata. See
4855  // https://github.com/google/sanitizers/issues/321.
4856  int res = REAL(random_r)(buf, result);
4857  if (!res && result)
4858    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
4859  return res;
4860}
4861#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
4862#else
4863#define INIT_RANDOM_R
4864#endif
4865
4866// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
4867// its metadata. See
4868// https://github.com/google/sanitizers/issues/321.
4869#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET ||              \
4870    SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED ||        \
4871    SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
4872    SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET ||         \
4873    SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET ||        \
4874    SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET ||          \
4875    SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
4876#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz)            \
4877  INTERCEPTOR(int, fn, void *attr, void *r) {                  \
4878    void *ctx;                                                 \
4879    COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r);                \
4880    int res = REAL(fn)(attr, r);                               \
4881    if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
4882    return res;                                                \
4883  }
4884#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
4885  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
4886#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
4887  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
4888#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
4889  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
4890#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
4891  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
4892#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
4893  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
4894#endif
4895
4896#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
4897INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
4898INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
4899INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
4900INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
4901INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
4902  void *ctx;
4903  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
4904  // FIXME: under ASan the call below may write to freed memory and corrupt
4905  // its metadata. See
4906  // https://github.com/google/sanitizers/issues/321.
4907  int res = REAL(pthread_attr_getstack)(attr, addr, size);
4908  if (!res) {
4909    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
4910    if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
4911  }
4912  return res;
4913}
4914
4915// We may need to call the real pthread_attr_getstack from the run-time
4916// in sanitizer_common, but we don't want to include the interception headers
4917// there. So, just define this function here.
4918namespace __sanitizer {
4919extern "C" {
4920int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
4921  return REAL(pthread_attr_getstack)(attr, addr, size);
4922}
4923}  // extern "C"
4924}  // namespace __sanitizer
4925
4926#define INIT_PTHREAD_ATTR_GET                             \
4927  COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
4928  COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize);   \
4929  COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope);       \
4930  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize);   \
4931  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
4932#else
4933#define INIT_PTHREAD_ATTR_GET
4934#endif
4935
4936#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED
4937INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
4938INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
4939
4940#define INIT_PTHREAD_ATTR_GET_SCHED                      \
4941  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \
4942  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy);
4943#else
4944#define INIT_PTHREAD_ATTR_GET_SCHED
4945#endif
4946
4947#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
4948INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
4949
4950#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
4951  COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
4952#else
4953#define INIT_PTHREAD_ATTR_GETINHERITSCHED
4954#endif
4955
4956#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
4957INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
4958            void *cpuset) {
4959  void *ctx;
4960  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
4961                           cpuset);
4962  // FIXME: under ASan the call below may write to freed memory and corrupt
4963  // its metadata. See
4964  // https://github.com/google/sanitizers/issues/321.
4965  int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
4966  if (!res && cpusetsize && cpuset)
4967    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
4968  return res;
4969}
4970
4971#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
4972  COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
4973#else
4974#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
4975#endif
4976
4977#if SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP
4978INTERCEPTOR(int, pthread_getaffinity_np, void *attr, SIZE_T cpusetsize,
4979            void *cpuset) {
4980  void *ctx;
4981  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getaffinity_np, attr, cpusetsize,
4982                           cpuset);
4983  // FIXME: under ASan the call below may write to freed memory and corrupt
4984  // its metadata. See
4985  // https://github.com/google/sanitizers/issues/321.
4986  int res = REAL(pthread_getaffinity_np)(attr, cpusetsize, cpuset);
4987  if (!res && cpusetsize && cpuset)
4988    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
4989  return res;
4990}
4991
4992#define INIT_PTHREAD_GETAFFINITY_NP \
4993  COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np);
4994#else
4995#define INIT_PTHREAD_GETAFFINITY_NP
4996#endif
4997
4998#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
4999INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
5000#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
5001  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
5002#else
5003#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
5004#endif
5005
5006#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
5007INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
5008#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
5009  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
5010#else
5011#define INIT_PTHREAD_MUTEXATTR_GETTYPE
5012#endif
5013
5014#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
5015INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
5016#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
5017  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
5018#else
5019#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
5020#endif
5021
5022#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
5023INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
5024#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
5025  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
5026#else
5027#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
5028#endif
5029
5030#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
5031INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
5032#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
5033  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
5034#else
5035#define INIT_PTHREAD_MUTEXATTR_GETROBUST
5036#endif
5037
5038#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
5039INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
5040#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
5041  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
5042#else
5043#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
5044#endif
5045
5046#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
5047INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
5048#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
5049  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
5050#else
5051#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
5052#endif
5053
5054#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
5055INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
5056#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
5057  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
5058#else
5059#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
5060#endif
5061
5062#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
5063INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
5064#define INIT_PTHREAD_CONDATTR_GETPSHARED \
5065  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
5066#else
5067#define INIT_PTHREAD_CONDATTR_GETPSHARED
5068#endif
5069
5070#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
5071INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
5072#define INIT_PTHREAD_CONDATTR_GETCLOCK \
5073  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
5074#else
5075#define INIT_PTHREAD_CONDATTR_GETCLOCK
5076#endif
5077
5078#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
5079INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
5080#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
5081  COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
5082#else
5083#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
5084#endif
5085
5086#if SANITIZER_INTERCEPT_TMPNAM
5087INTERCEPTOR(char *, tmpnam, char *s) {
5088  void *ctx;
5089  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
5090  char *res = REAL(tmpnam)(s);
5091  if (res) {
5092    if (s)
5093      // FIXME: under ASan the call below may write to freed memory and corrupt
5094      // its metadata. See
5095      // https://github.com/google/sanitizers/issues/321.
5096      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
5097    else
5098      COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
5099  }
5100  return res;
5101}
5102#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
5103#else
5104#define INIT_TMPNAM
5105#endif
5106
5107#if SANITIZER_INTERCEPT_TMPNAM_R
5108INTERCEPTOR(char *, tmpnam_r, char *s) {
5109  void *ctx;
5110  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
5111  // FIXME: under ASan the call below may write to freed memory and corrupt
5112  // its metadata. See
5113  // https://github.com/google/sanitizers/issues/321.
5114  char *res = REAL(tmpnam_r)(s);
5115  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
5116  return res;
5117}
5118#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
5119#else
5120#define INIT_TMPNAM_R
5121#endif
5122
5123#if SANITIZER_INTERCEPT_PTSNAME
5124INTERCEPTOR(char *, ptsname, int fd) {
5125  void *ctx;
5126  COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd);
5127  char *res = REAL(ptsname)(fd);
5128  if (res != nullptr)
5129    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
5130  return res;
5131}
5132#define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname);
5133#else
5134#define INIT_PTSNAME
5135#endif
5136
5137#if SANITIZER_INTERCEPT_PTSNAME_R
5138INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) {
5139  void *ctx;
5140  COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize);
5141  int res = REAL(ptsname_r)(fd, name, namesize);
5142  if (res == 0)
5143    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
5144  return res;
5145}
5146#define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r);
5147#else
5148#define INIT_PTSNAME_R
5149#endif
5150
5151#if SANITIZER_INTERCEPT_TTYNAME
5152INTERCEPTOR(char *, ttyname, int fd) {
5153  void *ctx;
5154  COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
5155  char *res = REAL(ttyname)(fd);
5156  if (res != nullptr)
5157    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
5158  return res;
5159}
5160#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
5161#else
5162#define INIT_TTYNAME
5163#endif
5164
5165#if SANITIZER_INTERCEPT_TTYNAME_R
5166INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
5167  void *ctx;
5168  COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
5169  int res = REAL(ttyname_r)(fd, name, namesize);
5170  if (res == 0)
5171    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
5172  return res;
5173}
5174#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
5175#else
5176#define INIT_TTYNAME_R
5177#endif
5178
5179#if SANITIZER_INTERCEPT_TEMPNAM
5180INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
5181  void *ctx;
5182  COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
5183  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, internal_strlen(dir) + 1);
5184  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, internal_strlen(pfx) + 1);
5185  char *res = REAL(tempnam)(dir, pfx);
5186  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
5187  return res;
5188}
5189#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
5190#else
5191#define INIT_TEMPNAM
5192#endif
5193
5194#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD
5195INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
5196  void *ctx;
5197  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
5198  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
5199  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
5200  return REAL(pthread_setname_np)(thread, name);
5201}
5202#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
5203#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD
5204INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) {
5205  void *ctx;
5206  char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
5207  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
5208  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
5209  internal_snprintf(newname, sizeof(newname), name, arg);
5210  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
5211  return REAL(pthread_setname_np)(thread, name, arg);
5212}
5213#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
5214#else
5215#define INIT_PTHREAD_SETNAME_NP
5216#endif
5217
5218#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP
5219INTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) {
5220  void *ctx;
5221  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len);
5222  int res = REAL(pthread_getname_np)(thread, name, len);
5223  if (!res)
5224    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1);
5225  return res;
5226}
5227#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
5228#else
5229#define INIT_PTHREAD_GETNAME_NP
5230#endif
5231
5232#if SANITIZER_INTERCEPT_SINCOS
5233INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
5234  void *ctx;
5235  COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
5236  // FIXME: under ASan the call below may write to freed memory and corrupt
5237  // its metadata. See
5238  // https://github.com/google/sanitizers/issues/321.
5239  REAL(sincos)(x, sin, cos);
5240  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
5241  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
5242}
5243INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
5244  void *ctx;
5245  COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
5246  // FIXME: under ASan the call below may write to freed memory and corrupt
5247  // its metadata. See
5248  // https://github.com/google/sanitizers/issues/321.
5249  REAL(sincosf)(x, sin, cos);
5250  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
5251  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
5252}
5253INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
5254  void *ctx;
5255  COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
5256  // FIXME: under ASan the call below may write to freed memory and corrupt
5257  // its metadata. See
5258  // https://github.com/google/sanitizers/issues/321.
5259  REAL(sincosl)(x, sin, cos);
5260  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
5261  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
5262}
5263#define INIT_SINCOS                   \
5264  COMMON_INTERCEPT_FUNCTION(sincos);  \
5265  COMMON_INTERCEPT_FUNCTION(sincosf); \
5266  COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
5267#else
5268#define INIT_SINCOS
5269#endif
5270
5271#if SANITIZER_INTERCEPT_REMQUO
5272INTERCEPTOR(double, remquo, double x, double y, int *quo) {
5273  void *ctx;
5274  COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
5275  // FIXME: under ASan the call below may write to freed memory and corrupt
5276  // its metadata. See
5277  // https://github.com/google/sanitizers/issues/321.
5278  double res = REAL(remquo)(x, y, quo);
5279  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
5280  return res;
5281}
5282INTERCEPTOR(float, remquof, float x, float y, int *quo) {
5283  void *ctx;
5284  COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
5285  // FIXME: under ASan the call below may write to freed memory and corrupt
5286  // its metadata. See
5287  // https://github.com/google/sanitizers/issues/321.
5288  float res = REAL(remquof)(x, y, quo);
5289  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
5290  return res;
5291}
5292#define INIT_REMQUO                   \
5293  COMMON_INTERCEPT_FUNCTION(remquo);  \
5294  COMMON_INTERCEPT_FUNCTION(remquof);
5295#else
5296#define INIT_REMQUO
5297#endif
5298
5299#if SANITIZER_INTERCEPT_REMQUOL
5300INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
5301  void *ctx;
5302  COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
5303  // FIXME: under ASan the call below may write to freed memory and corrupt
5304  // its metadata. See
5305  // https://github.com/google/sanitizers/issues/321.
5306  long double res = REAL(remquol)(x, y, quo);
5307  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
5308  return res;
5309}
5310#define INIT_REMQUOL                  \
5311  COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
5312#else
5313#define INIT_REMQUOL
5314#endif
5315
5316#if SANITIZER_INTERCEPT_LGAMMA
5317extern int signgam;
5318INTERCEPTOR(double, lgamma, double x) {
5319  void *ctx;
5320  COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
5321  double res = REAL(lgamma)(x);
5322  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
5323  return res;
5324}
5325INTERCEPTOR(float, lgammaf, float x) {
5326  void *ctx;
5327  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
5328  float res = REAL(lgammaf)(x);
5329  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
5330  return res;
5331}
5332#define INIT_LGAMMA                   \
5333  COMMON_INTERCEPT_FUNCTION(lgamma);  \
5334  COMMON_INTERCEPT_FUNCTION(lgammaf);
5335#else
5336#define INIT_LGAMMA
5337#endif
5338
5339#if SANITIZER_INTERCEPT_LGAMMAL
5340INTERCEPTOR(long double, lgammal, long double x) {
5341  void *ctx;
5342  COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
5343  long double res = REAL(lgammal)(x);
5344  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
5345  return res;
5346}
5347#define INIT_LGAMMAL                  \
5348  COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
5349#else
5350#define INIT_LGAMMAL
5351#endif
5352
5353#if SANITIZER_INTERCEPT_LGAMMA_R
5354INTERCEPTOR(double, lgamma_r, double x, int *signp) {
5355  void *ctx;
5356  COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
5357  // FIXME: under ASan the call below may write to freed memory and corrupt
5358  // its metadata. See
5359  // https://github.com/google/sanitizers/issues/321.
5360  double res = REAL(lgamma_r)(x, signp);
5361  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
5362  return res;
5363}
5364INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
5365  void *ctx;
5366  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
5367  // FIXME: under ASan the call below may write to freed memory and corrupt
5368  // its metadata. See
5369  // https://github.com/google/sanitizers/issues/321.
5370  float res = REAL(lgammaf_r)(x, signp);
5371  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
5372  return res;
5373}
5374#define INIT_LGAMMA_R                   \
5375  COMMON_INTERCEPT_FUNCTION(lgamma_r);  \
5376  COMMON_INTERCEPT_FUNCTION(lgammaf_r);
5377#else
5378#define INIT_LGAMMA_R
5379#endif
5380
5381#if SANITIZER_INTERCEPT_LGAMMAL_R
5382INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
5383  void *ctx;
5384  COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
5385  // FIXME: under ASan the call below may write to freed memory and corrupt
5386  // its metadata. See
5387  // https://github.com/google/sanitizers/issues/321.
5388  long double res = REAL(lgammal_r)(x, signp);
5389  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
5390  return res;
5391}
5392#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
5393#else
5394#define INIT_LGAMMAL_R
5395#endif
5396
5397#if SANITIZER_INTERCEPT_DRAND48_R
5398INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
5399  void *ctx;
5400  COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
5401  // FIXME: under ASan the call below may write to freed memory and corrupt
5402  // its metadata. See
5403  // https://github.com/google/sanitizers/issues/321.
5404  int res = REAL(drand48_r)(buffer, result);
5405  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
5406  return res;
5407}
5408INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
5409  void *ctx;
5410  COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
5411  // FIXME: under ASan the call below may write to freed memory and corrupt
5412  // its metadata. See
5413  // https://github.com/google/sanitizers/issues/321.
5414  int res = REAL(lrand48_r)(buffer, result);
5415  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
5416  return res;
5417}
5418#define INIT_DRAND48_R                  \
5419  COMMON_INTERCEPT_FUNCTION(drand48_r); \
5420  COMMON_INTERCEPT_FUNCTION(lrand48_r);
5421#else
5422#define INIT_DRAND48_R
5423#endif
5424
5425#if SANITIZER_INTERCEPT_RAND_R
5426INTERCEPTOR(int, rand_r, unsigned *seedp) {
5427  void *ctx;
5428  COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
5429  COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
5430  return REAL(rand_r)(seedp);
5431}
5432#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
5433#else
5434#define INIT_RAND_R
5435#endif
5436
5437#if SANITIZER_INTERCEPT_GETLINE
5438INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
5439  void *ctx;
5440  COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
5441  // FIXME: under ASan the call below may write to freed memory and corrupt
5442  // its metadata. See
5443  // https://github.com/google/sanitizers/issues/321.
5444  SSIZE_T res = REAL(getline)(lineptr, n, stream);
5445  if (res > 0) {
5446    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
5447    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
5448    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
5449  }
5450  return res;
5451}
5452
5453// FIXME: under ASan the call below may write to freed memory and corrupt its
5454// metadata. See
5455// https://github.com/google/sanitizers/issues/321.
5456#define GETDELIM_INTERCEPTOR_IMPL(vname)                                       \
5457  {                                                                            \
5458    void *ctx;                                                                 \
5459    COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream);           \
5460    SSIZE_T res = REAL(vname)(lineptr, n, delim, stream);                      \
5461    if (res > 0) {                                                             \
5462      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));          \
5463      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));                      \
5464      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);                  \
5465    }                                                                          \
5466    return res;                                                                \
5467  }
5468
5469INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
5470            void *stream)
5471GETDELIM_INTERCEPTOR_IMPL(__getdelim)
5472
5473// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
5474// with its own body.
5475INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
5476            void *stream)
5477GETDELIM_INTERCEPTOR_IMPL(getdelim)
5478
5479#define INIT_GETLINE                     \
5480  COMMON_INTERCEPT_FUNCTION(getline);    \
5481  COMMON_INTERCEPT_FUNCTION(__getdelim); \
5482  COMMON_INTERCEPT_FUNCTION(getdelim);
5483#else
5484#define INIT_GETLINE
5485#endif
5486
5487#if SANITIZER_INTERCEPT_ICONV
5488INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
5489            char **outbuf, SIZE_T *outbytesleft) {
5490  void *ctx;
5491  COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
5492                           outbytesleft);
5493  if (inbytesleft)
5494    COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
5495  if (inbuf && inbytesleft)
5496    COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
5497  if (outbytesleft)
5498    COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
5499  void *outbuf_orig = outbuf ? *outbuf : nullptr;
5500  // FIXME: under ASan the call below may write to freed memory and corrupt
5501  // its metadata. See
5502  // https://github.com/google/sanitizers/issues/321.
5503  SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
5504  if (outbuf && *outbuf > outbuf_orig) {
5505    SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
5506    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
5507  }
5508  return res;
5509}
5510#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
5511#else
5512#define INIT_ICONV
5513#endif
5514
5515#if SANITIZER_INTERCEPT_TIMES
5516INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
5517  void *ctx;
5518  COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
5519  // FIXME: under ASan the call below may write to freed memory and corrupt
5520  // its metadata. See
5521  // https://github.com/google/sanitizers/issues/321.
5522  __sanitizer_clock_t res = REAL(times)(tms);
5523  if (res != (__sanitizer_clock_t)-1 && tms)
5524    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
5525  return res;
5526}
5527#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
5528#else
5529#define INIT_TIMES
5530#endif
5531
5532#if SANITIZER_S390 && \
5533    (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
5534extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
5535DEFINE_REAL(uptr, __tls_get_offset, void *arg)
5536#endif
5537
5538#if SANITIZER_INTERCEPT_TLS_GET_ADDR
5539#if !SANITIZER_S390
5540#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
5541// If you see any crashes around this functions, there are 2 known issues with
5542// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
5543// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
5544// 2. It can be called recursively if sanitizer code uses __tls_get_addr
5545// to access thread local variables (it should not happen normally,
5546// because sanitizers use initial-exec tls model).
5547INTERCEPTOR(void *, __tls_get_addr, void *arg) {
5548  void *ctx;
5549  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
5550  void *res = REAL(__tls_get_addr)(arg);
5551  uptr tls_begin, tls_end;
5552  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
5553  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
5554  if (dtv) {
5555    // New DTLS block has been allocated.
5556    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
5557  }
5558  return res;
5559}
5560#if SANITIZER_PPC
5561// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
5562// mostly the same semantics as __tls_get_addr, but its presence enables
5563// some optimizations in linker (which are safe to ignore here).
5564extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
5565                          visibility("default")))
5566void *__tls_get_addr_opt(void *arg);
5567#endif
5568#else // SANITIZER_S390
5569// On s390, we have to intercept two functions here:
5570// - __tls_get_addr_internal, which is a glibc-internal function that is like
5571//   the usual __tls_get_addr, but returns a TP-relative offset instead of
5572//   a proper pointer.  It is used by dlsym for TLS symbols.
5573// - __tls_get_offset, which is like the above, but also takes a GOT-relative
5574//   descriptor offset as an argument instead of a pointer.  GOT address
5575//   is passed in r12, so it's necessary to write it in assembly.  This is
5576//   the function used by the compiler.
5577#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
5578INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
5579  void *ctx;
5580  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
5581  uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
5582  uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
5583  void *ptr = reinterpret_cast<void *>(res + tp);
5584  uptr tls_begin, tls_end;
5585  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
5586  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
5587  if (dtv) {
5588    // New DTLS block has been allocated.
5589    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
5590  }
5591  return res;
5592}
5593#endif // SANITIZER_S390
5594#else
5595#define INIT_TLS_GET_ADDR
5596#endif
5597
5598#if SANITIZER_S390 && \
5599    (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
5600extern "C" uptr __tls_get_offset(void *arg);
5601extern "C" uptr __interceptor___tls_get_offset(void *arg);
5602// We need a hidden symbol aliasing the above, so that we can jump
5603// directly to it from the assembly below.
5604extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
5605                          visibility("hidden")))
5606uptr __tls_get_addr_hidden(void *arg);
5607// Now carefully intercept __tls_get_offset.
5608asm(
5609  ".text\n"
5610// The __intercept_ version has to exist, so that gen_dynamic_list.py
5611// exports our symbol.
5612  ".weak __tls_get_offset\n"
5613  ".type __tls_get_offset, @function\n"
5614  "__tls_get_offset:\n"
5615  ".global __interceptor___tls_get_offset\n"
5616  ".type __interceptor___tls_get_offset, @function\n"
5617  "__interceptor___tls_get_offset:\n"
5618#ifdef __s390x__
5619  "la %r2, 0(%r2,%r12)\n"
5620  "jg __tls_get_addr_hidden\n"
5621#else
5622  "basr %r3,0\n"
5623  "0: la %r2,0(%r2,%r12)\n"
5624  "l %r4,1f-0b(%r3)\n"
5625  "b 0(%r4,%r3)\n"
5626  "1: .long __tls_get_addr_hidden - 0b\n"
5627#endif
5628  ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
5629// Assembly wrapper to call REAL(__tls_get_offset)(arg)
5630  ".type __tls_get_offset_wrapper, @function\n"
5631  "__tls_get_offset_wrapper:\n"
5632#ifdef __s390x__
5633  "sgr %r2,%r12\n"
5634#else
5635  "sr %r2,%r12\n"
5636#endif
5637  "br %r3\n"
5638  ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
5639);
5640#endif
5641
5642#if SANITIZER_INTERCEPT_LISTXATTR
5643INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
5644  void *ctx;
5645  COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
5646  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
5647  // FIXME: under ASan the call below may write to freed memory and corrupt
5648  // its metadata. See
5649  // https://github.com/google/sanitizers/issues/321.
5650  SSIZE_T res = REAL(listxattr)(path, list, size);
5651  // Here and below, size == 0 is a special case where nothing is written to the
5652  // buffer, and res contains the desired buffer size.
5653  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
5654  return res;
5655}
5656INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
5657  void *ctx;
5658  COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
5659  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
5660  // FIXME: under ASan the call below may write to freed memory and corrupt
5661  // its metadata. See
5662  // https://github.com/google/sanitizers/issues/321.
5663  SSIZE_T res = REAL(llistxattr)(path, list, size);
5664  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
5665  return res;
5666}
5667INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
5668  void *ctx;
5669  COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
5670  // FIXME: under ASan the call below may write to freed memory and corrupt
5671  // its metadata. See
5672  // https://github.com/google/sanitizers/issues/321.
5673  SSIZE_T res = REAL(flistxattr)(fd, list, size);
5674  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
5675  return res;
5676}
5677#define INIT_LISTXATTR                   \
5678  COMMON_INTERCEPT_FUNCTION(listxattr);  \
5679  COMMON_INTERCEPT_FUNCTION(llistxattr); \
5680  COMMON_INTERCEPT_FUNCTION(flistxattr);
5681#else
5682#define INIT_LISTXATTR
5683#endif
5684
5685#if SANITIZER_INTERCEPT_GETXATTR
5686INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
5687            SIZE_T size) {
5688  void *ctx;
5689  COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
5690  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
5691  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
5692  // FIXME: under ASan the call below may write to freed memory and corrupt
5693  // its metadata. See
5694  // https://github.com/google/sanitizers/issues/321.
5695  SSIZE_T res = REAL(getxattr)(path, name, value, size);
5696  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
5697  return res;
5698}
5699INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
5700            SIZE_T size) {
5701  void *ctx;
5702  COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
5703  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
5704  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
5705  // FIXME: under ASan the call below may write to freed memory and corrupt
5706  // its metadata. See
5707  // https://github.com/google/sanitizers/issues/321.
5708  SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
5709  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
5710  return res;
5711}
5712INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
5713            SIZE_T size) {
5714  void *ctx;
5715  COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
5716  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
5717  // FIXME: under ASan the call below may write to freed memory and corrupt
5718  // its metadata. See
5719  // https://github.com/google/sanitizers/issues/321.
5720  SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
5721  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
5722  return res;
5723}
5724#define INIT_GETXATTR                   \
5725  COMMON_INTERCEPT_FUNCTION(getxattr);  \
5726  COMMON_INTERCEPT_FUNCTION(lgetxattr); \
5727  COMMON_INTERCEPT_FUNCTION(fgetxattr);
5728#else
5729#define INIT_GETXATTR
5730#endif
5731
5732#if SANITIZER_INTERCEPT_GETRESID
5733INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
5734  void *ctx;
5735  COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
5736  // FIXME: under ASan the call below may write to freed memory and corrupt
5737  // its metadata. See
5738  // https://github.com/google/sanitizers/issues/321.
5739  int res = REAL(getresuid)(ruid, euid, suid);
5740  if (res >= 0) {
5741    if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
5742    if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
5743    if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
5744  }
5745  return res;
5746}
5747INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
5748  void *ctx;
5749  COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
5750  // FIXME: under ASan the call below may write to freed memory and corrupt
5751  // its metadata. See
5752  // https://github.com/google/sanitizers/issues/321.
5753  int res = REAL(getresgid)(rgid, egid, sgid);
5754  if (res >= 0) {
5755    if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
5756    if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
5757    if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
5758  }
5759  return res;
5760}
5761#define INIT_GETRESID                   \
5762  COMMON_INTERCEPT_FUNCTION(getresuid); \
5763  COMMON_INTERCEPT_FUNCTION(getresgid);
5764#else
5765#define INIT_GETRESID
5766#endif
5767
5768#if SANITIZER_INTERCEPT_GETIFADDRS
5769// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
5770// intercept freeifaddrs(). If that ceases to be the case, we might need to
5771// intercept it to poison the memory again.
5772INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
5773  void *ctx;
5774  COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
5775  // FIXME: under ASan the call below may write to freed memory and corrupt
5776  // its metadata. See
5777  // https://github.com/google/sanitizers/issues/321.
5778  int res = REAL(getifaddrs)(ifap);
5779  if (res == 0 && ifap) {
5780    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
5781    __sanitizer_ifaddrs *p = *ifap;
5782    while (p) {
5783      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
5784      if (p->ifa_name)
5785        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
5786                                       internal_strlen(p->ifa_name) + 1);
5787      if (p->ifa_addr)
5788        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
5789      if (p->ifa_netmask)
5790        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
5791      // On Linux this is a union, but the other member also points to a
5792      // struct sockaddr, so the following is sufficient.
5793      if (p->ifa_dstaddr)
5794        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
5795      // FIXME(smatveev): Unpoison p->ifa_data as well.
5796      p = p->ifa_next;
5797    }
5798  }
5799  return res;
5800}
5801#define INIT_GETIFADDRS                  \
5802  COMMON_INTERCEPT_FUNCTION(getifaddrs);
5803#else
5804#define INIT_GETIFADDRS
5805#endif
5806
5807#if SANITIZER_INTERCEPT_IF_INDEXTONAME
5808INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
5809  void *ctx;
5810  COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
5811  // FIXME: under ASan the call below may write to freed memory and corrupt
5812  // its metadata. See
5813  // https://github.com/google/sanitizers/issues/321.
5814  char *res = REAL(if_indextoname)(ifindex, ifname);
5815  if (res && ifname)
5816    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
5817  return res;
5818}
5819INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
5820  void *ctx;
5821  COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
5822  if (ifname)
5823    COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
5824  return REAL(if_nametoindex)(ifname);
5825}
5826#define INIT_IF_INDEXTONAME                  \
5827  COMMON_INTERCEPT_FUNCTION(if_indextoname); \
5828  COMMON_INTERCEPT_FUNCTION(if_nametoindex);
5829#else
5830#define INIT_IF_INDEXTONAME
5831#endif
5832
5833#if SANITIZER_INTERCEPT_CAPGET
5834INTERCEPTOR(int, capget, void *hdrp, void *datap) {
5835  void *ctx;
5836  COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
5837  if (hdrp)
5838    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
5839  // FIXME: under ASan the call below may write to freed memory and corrupt
5840  // its metadata. See
5841  // https://github.com/google/sanitizers/issues/321.
5842  int res = REAL(capget)(hdrp, datap);
5843  if (res == 0 && datap)
5844    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
5845  // We can also return -1 and write to hdrp->version if the version passed in
5846  // hdrp->version is unsupported. But that's not a trivial condition to check,
5847  // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
5848  return res;
5849}
5850INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
5851  void *ctx;
5852  COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
5853  if (hdrp)
5854    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
5855  if (datap)
5856    COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
5857  return REAL(capset)(hdrp, datap);
5858}
5859#define INIT_CAPGET                  \
5860  COMMON_INTERCEPT_FUNCTION(capget); \
5861  COMMON_INTERCEPT_FUNCTION(capset);
5862#else
5863#define INIT_CAPGET
5864#endif
5865
5866#if SANITIZER_INTERCEPT_AEABI_MEM
5867INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
5868  void *ctx;
5869  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5870}
5871
5872INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
5873  void *ctx;
5874  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5875}
5876
5877INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
5878  void *ctx;
5879  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5880}
5881
5882INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
5883  void *ctx;
5884  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5885}
5886
5887INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
5888  void *ctx;
5889  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5890}
5891
5892INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
5893  void *ctx;
5894  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5895}
5896
5897// Note the argument order.
5898INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
5899  void *ctx;
5900  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5901}
5902
5903INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
5904  void *ctx;
5905  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5906}
5907
5908INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
5909  void *ctx;
5910  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5911}
5912
5913INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
5914  void *ctx;
5915  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5916}
5917
5918INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
5919  void *ctx;
5920  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5921}
5922
5923INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
5924  void *ctx;
5925  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5926}
5927
5928#define INIT_AEABI_MEM                         \
5929  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove);  \
5930  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
5931  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
5932  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy);   \
5933  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4);  \
5934  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8);  \
5935  COMMON_INTERCEPT_FUNCTION(__aeabi_memset);   \
5936  COMMON_INTERCEPT_FUNCTION(__aeabi_memset4);  \
5937  COMMON_INTERCEPT_FUNCTION(__aeabi_memset8);  \
5938  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr);   \
5939  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4);  \
5940  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
5941#else
5942#define INIT_AEABI_MEM
5943#endif  // SANITIZER_INTERCEPT_AEABI_MEM
5944
5945#if SANITIZER_INTERCEPT___BZERO
5946INTERCEPTOR(void *, __bzero, void *block, uptr size) {
5947  void *ctx;
5948  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5949}
5950#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
5951#else
5952#define INIT___BZERO
5953#endif  // SANITIZER_INTERCEPT___BZERO
5954
5955#if SANITIZER_INTERCEPT_BZERO
5956INTERCEPTOR(void *, bzero, void *block, uptr size) {
5957  void *ctx;
5958  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5959}
5960#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
5961#else
5962#define INIT_BZERO
5963#endif  // SANITIZER_INTERCEPT_BZERO
5964
5965#if SANITIZER_INTERCEPT_FTIME
5966INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
5967  void *ctx;
5968  COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
5969  // FIXME: under ASan the call below may write to freed memory and corrupt
5970  // its metadata. See
5971  // https://github.com/google/sanitizers/issues/321.
5972  int res = REAL(ftime)(tp);
5973  if (tp)
5974    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
5975  return res;
5976}
5977#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
5978#else
5979#define INIT_FTIME
5980#endif  // SANITIZER_INTERCEPT_FTIME
5981
5982#if SANITIZER_INTERCEPT_XDR
5983INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
5984            unsigned size, int op) {
5985  void *ctx;
5986  COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
5987  // FIXME: under ASan the call below may write to freed memory and corrupt
5988  // its metadata. See
5989  // https://github.com/google/sanitizers/issues/321.
5990  REAL(xdrmem_create)(xdrs, addr, size, op);
5991  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
5992  if (op == __sanitizer_XDR_ENCODE) {
5993    // It's not obvious how much data individual xdr_ routines write.
5994    // Simply unpoison the entire target buffer in advance.
5995    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
5996  }
5997}
5998
5999INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
6000  void *ctx;
6001  COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
6002  // FIXME: under ASan the call below may write to freed memory and corrupt
6003  // its metadata. See
6004  // https://github.com/google/sanitizers/issues/321.
6005  REAL(xdrstdio_create)(xdrs, file, op);
6006  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
6007}
6008
6009// FIXME: under ASan the call below may write to freed memory and corrupt
6010// its metadata. See
6011// https://github.com/google/sanitizers/issues/321.
6012#define XDR_INTERCEPTOR(F, T)                             \
6013  INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) {      \
6014    void *ctx;                                            \
6015    COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p);            \
6016    if (p && xdrs->x_op == __sanitizer_XDR_ENCODE)        \
6017      COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));  \
6018    int res = REAL(F)(xdrs, p);                           \
6019    if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
6020      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
6021    return res;                                           \
6022  }
6023
6024XDR_INTERCEPTOR(xdr_short, short)
6025XDR_INTERCEPTOR(xdr_u_short, unsigned short)
6026XDR_INTERCEPTOR(xdr_int, int)
6027XDR_INTERCEPTOR(xdr_u_int, unsigned)
6028XDR_INTERCEPTOR(xdr_long, long)
6029XDR_INTERCEPTOR(xdr_u_long, unsigned long)
6030XDR_INTERCEPTOR(xdr_hyper, long long)
6031XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
6032XDR_INTERCEPTOR(xdr_longlong_t, long long)
6033XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
6034XDR_INTERCEPTOR(xdr_int8_t, u8)
6035XDR_INTERCEPTOR(xdr_uint8_t, u8)
6036XDR_INTERCEPTOR(xdr_int16_t, u16)
6037XDR_INTERCEPTOR(xdr_uint16_t, u16)
6038XDR_INTERCEPTOR(xdr_int32_t, u32)
6039XDR_INTERCEPTOR(xdr_uint32_t, u32)
6040XDR_INTERCEPTOR(xdr_int64_t, u64)
6041XDR_INTERCEPTOR(xdr_uint64_t, u64)
6042XDR_INTERCEPTOR(xdr_quad_t, long long)
6043XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
6044XDR_INTERCEPTOR(xdr_bool, bool)
6045XDR_INTERCEPTOR(xdr_enum, int)
6046XDR_INTERCEPTOR(xdr_char, char)
6047XDR_INTERCEPTOR(xdr_u_char, unsigned char)
6048XDR_INTERCEPTOR(xdr_float, float)
6049XDR_INTERCEPTOR(xdr_double, double)
6050
6051// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
6052// wrapstring, sizeof
6053
6054INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
6055            unsigned maxsize) {
6056  void *ctx;
6057  COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
6058  if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
6059    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
6060    COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
6061    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
6062  }
6063  // FIXME: under ASan the call below may write to freed memory and corrupt
6064  // its metadata. See
6065  // https://github.com/google/sanitizers/issues/321.
6066  int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
6067  if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
6068    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
6069    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
6070    if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
6071  }
6072  return res;
6073}
6074
6075INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
6076            unsigned maxsize) {
6077  void *ctx;
6078  COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
6079  if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
6080    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
6081    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, internal_strlen(*p) + 1);
6082  }
6083  // FIXME: under ASan the call below may write to freed memory and corrupt
6084  // its metadata. See
6085  // https://github.com/google/sanitizers/issues/321.
6086  int res = REAL(xdr_string)(xdrs, p, maxsize);
6087  if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
6088    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
6089    if (res && *p)
6090      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
6091  }
6092  return res;
6093}
6094
6095#define INIT_XDR                               \
6096  COMMON_INTERCEPT_FUNCTION(xdrmem_create);    \
6097  COMMON_INTERCEPT_FUNCTION(xdrstdio_create);  \
6098  COMMON_INTERCEPT_FUNCTION(xdr_short);        \
6099  COMMON_INTERCEPT_FUNCTION(xdr_u_short);      \
6100  COMMON_INTERCEPT_FUNCTION(xdr_int);          \
6101  COMMON_INTERCEPT_FUNCTION(xdr_u_int);        \
6102  COMMON_INTERCEPT_FUNCTION(xdr_long);         \
6103  COMMON_INTERCEPT_FUNCTION(xdr_u_long);       \
6104  COMMON_INTERCEPT_FUNCTION(xdr_hyper);        \
6105  COMMON_INTERCEPT_FUNCTION(xdr_u_hyper);      \
6106  COMMON_INTERCEPT_FUNCTION(xdr_longlong_t);   \
6107  COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
6108  COMMON_INTERCEPT_FUNCTION(xdr_int8_t);       \
6109  COMMON_INTERCEPT_FUNCTION(xdr_uint8_t);      \
6110  COMMON_INTERCEPT_FUNCTION(xdr_int16_t);      \
6111  COMMON_INTERCEPT_FUNCTION(xdr_uint16_t);     \
6112  COMMON_INTERCEPT_FUNCTION(xdr_int32_t);      \
6113  COMMON_INTERCEPT_FUNCTION(xdr_uint32_t);     \
6114  COMMON_INTERCEPT_FUNCTION(xdr_int64_t);      \
6115  COMMON_INTERCEPT_FUNCTION(xdr_uint64_t);     \
6116  COMMON_INTERCEPT_FUNCTION(xdr_quad_t);       \
6117  COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t);     \
6118  COMMON_INTERCEPT_FUNCTION(xdr_bool);         \
6119  COMMON_INTERCEPT_FUNCTION(xdr_enum);         \
6120  COMMON_INTERCEPT_FUNCTION(xdr_char);         \
6121  COMMON_INTERCEPT_FUNCTION(xdr_u_char);       \
6122  COMMON_INTERCEPT_FUNCTION(xdr_float);        \
6123  COMMON_INTERCEPT_FUNCTION(xdr_double);       \
6124  COMMON_INTERCEPT_FUNCTION(xdr_bytes);        \
6125  COMMON_INTERCEPT_FUNCTION(xdr_string);
6126#else
6127#define INIT_XDR
6128#endif  // SANITIZER_INTERCEPT_XDR
6129
6130#if SANITIZER_INTERCEPT_XDRREC
6131typedef int (*xdrrec_cb)(char*, char*, int);
6132struct XdrRecWrapper {
6133  char *handle;
6134  xdrrec_cb rd, wr;
6135};
6136typedef AddrHashMap<XdrRecWrapper *, 11> XdrRecWrapMap;
6137static XdrRecWrapMap *xdrrec_wrap_map;
6138
6139static int xdrrec_wr_wrap(char *handle, char *buf, int count) {
6140  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6141  COMMON_INTERCEPTOR_INITIALIZE_RANGE(buf, count);
6142  XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
6143  return wrap->wr(wrap->handle, buf, count);
6144}
6145
6146static int xdrrec_rd_wrap(char *handle, char *buf, int count) {
6147  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6148  XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
6149  return wrap->rd(wrap->handle, buf, count);
6150}
6151
6152// This doesn't apply to the solaris version as it has a different function
6153// signature.
6154INTERCEPTOR(void, xdrrec_create, __sanitizer_XDR *xdr, unsigned sndsize,
6155            unsigned rcvsize, char *handle, int (*rd)(char*, char*, int),
6156            int (*wr)(char*, char*, int)) {
6157  void *ctx;
6158  COMMON_INTERCEPTOR_ENTER(ctx, xdrrec_create, xdr, sndsize, rcvsize,
6159                           handle, rd, wr);
6160  COMMON_INTERCEPTOR_READ_RANGE(ctx, &xdr->x_op, sizeof xdr->x_op);
6161
6162  // We can't allocate a wrapper on the stack, as the handle is used outside
6163  // this stack frame. So we put it on the heap, and keep track of it with
6164  // the HashMap (keyed by x_private). When we later need to xdr_destroy,
6165  // we can index the map, free the wrapper, and then clean the map entry.
6166  XdrRecWrapper *wrap_data =
6167      (XdrRecWrapper *)InternalAlloc(sizeof(XdrRecWrapper));
6168  wrap_data->handle = handle;
6169  wrap_data->rd = rd;
6170  wrap_data->wr = wr;
6171  if (wr)
6172    wr = xdrrec_wr_wrap;
6173  if (rd)
6174    rd = xdrrec_rd_wrap;
6175  handle = (char *)wrap_data;
6176
6177  REAL(xdrrec_create)(xdr, sndsize, rcvsize, handle, rd, wr);
6178  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdr, sizeof *xdr);
6179
6180  XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, false, true);
6181  *wrap = wrap_data;
6182}
6183
6184// We have to intercept this to be able to free wrapper memory;
6185// otherwise it's not necessary.
6186INTERCEPTOR(void, xdr_destroy, __sanitizer_XDR *xdr) {
6187  void *ctx;
6188  COMMON_INTERCEPTOR_ENTER(ctx, xdr_destroy, xdr);
6189
6190  XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, true);
6191  InternalFree(*wrap);
6192  REAL(xdr_destroy)(xdr);
6193}
6194#define INIT_XDRREC_LINUX \
6195  static u64 xdrrec_wrap_mem[sizeof(XdrRecWrapMap) / sizeof(u64) + 1]; \
6196  xdrrec_wrap_map = new ((void *)&xdrrec_wrap_mem) XdrRecWrapMap(); \
6197  COMMON_INTERCEPT_FUNCTION(xdrrec_create); \
6198  COMMON_INTERCEPT_FUNCTION(xdr_destroy);
6199#else
6200#define INIT_XDRREC_LINUX
6201#endif
6202
6203#if SANITIZER_INTERCEPT_TSEARCH
6204INTERCEPTOR(void *, tsearch, void *key, void **rootp,
6205            int (*compar)(const void *, const void *)) {
6206  void *ctx;
6207  COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
6208  // FIXME: under ASan the call below may write to freed memory and corrupt
6209  // its metadata. See
6210  // https://github.com/google/sanitizers/issues/321.
6211  void *res = REAL(tsearch)(key, rootp, compar);
6212  if (res && *(void **)res == key)
6213    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
6214  return res;
6215}
6216#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
6217#else
6218#define INIT_TSEARCH
6219#endif
6220
6221#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
6222    SANITIZER_INTERCEPT_OPEN_MEMSTREAM
6223void unpoison_file(__sanitizer_FILE *fp) {
6224#if SANITIZER_HAS_STRUCT_FILE
6225  COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
6226#if SANITIZER_NETBSD
6227  if (fp->_bf._base && fp->_bf._size > 0)
6228    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base,
6229                                        fp->_bf._size);
6230#else
6231  if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
6232    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
6233                                        fp->_IO_read_end - fp->_IO_read_base);
6234  if (fp->_IO_write_base && fp->_IO_write_base < fp->_IO_write_end)
6235    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_write_base,
6236                                        fp->_IO_write_end - fp->_IO_write_base);
6237#endif
6238#endif  // SANITIZER_HAS_STRUCT_FILE
6239}
6240#endif
6241
6242#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
6243// These guys are called when a .c source is built with -O2.
6244INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
6245  void *ctx;
6246  COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
6247  int res = REAL(__uflow)(fp);
6248  unpoison_file(fp);
6249  return res;
6250}
6251INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
6252  void *ctx;
6253  COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
6254  int res = REAL(__underflow)(fp);
6255  unpoison_file(fp);
6256  return res;
6257}
6258INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
6259  void *ctx;
6260  COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
6261  int res = REAL(__overflow)(fp, ch);
6262  unpoison_file(fp);
6263  return res;
6264}
6265INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
6266  void *ctx;
6267  COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
6268  int res = REAL(__wuflow)(fp);
6269  unpoison_file(fp);
6270  return res;
6271}
6272INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
6273  void *ctx;
6274  COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
6275  int res = REAL(__wunderflow)(fp);
6276  unpoison_file(fp);
6277  return res;
6278}
6279INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
6280  void *ctx;
6281  COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
6282  int res = REAL(__woverflow)(fp, ch);
6283  unpoison_file(fp);
6284  return res;
6285}
6286#define INIT_LIBIO_INTERNALS               \
6287  COMMON_INTERCEPT_FUNCTION(__uflow);      \
6288  COMMON_INTERCEPT_FUNCTION(__underflow);  \
6289  COMMON_INTERCEPT_FUNCTION(__overflow);   \
6290  COMMON_INTERCEPT_FUNCTION(__wuflow);     \
6291  COMMON_INTERCEPT_FUNCTION(__wunderflow); \
6292  COMMON_INTERCEPT_FUNCTION(__woverflow);
6293#else
6294#define INIT_LIBIO_INTERNALS
6295#endif
6296
6297#if SANITIZER_INTERCEPT_FOPEN
6298INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
6299  void *ctx;
6300  COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
6301  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6302  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
6303  __sanitizer_FILE *res = REAL(fopen)(path, mode);
6304  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
6305  if (res) unpoison_file(res);
6306  return res;
6307}
6308INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
6309  void *ctx;
6310  COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
6311  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
6312  __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
6313  if (res) unpoison_file(res);
6314  return res;
6315}
6316INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
6317            __sanitizer_FILE *fp) {
6318  void *ctx;
6319  COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
6320  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6321  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
6322  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
6323  __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
6324  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
6325  if (res) unpoison_file(res);
6326  return res;
6327}
6328#define INIT_FOPEN                   \
6329  COMMON_INTERCEPT_FUNCTION(fopen);  \
6330  COMMON_INTERCEPT_FUNCTION(fdopen); \
6331  COMMON_INTERCEPT_FUNCTION(freopen);
6332#else
6333#define INIT_FOPEN
6334#endif
6335
6336#if SANITIZER_INTERCEPT_FLOPEN
6337INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
6338  void *ctx;
6339  va_list ap;
6340  va_start(ap, flags);
6341  u16 mode = static_cast<u16>(va_arg(ap, u32));
6342  va_end(ap);
6343  COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
6344  if (path) {
6345    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6346  }
6347  return REAL(flopen)(path, flags, mode);
6348}
6349
6350INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
6351  void *ctx;
6352  va_list ap;
6353  va_start(ap, flags);
6354  u16 mode = static_cast<u16>(va_arg(ap, u32));
6355  va_end(ap);
6356  COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
6357  if (path) {
6358    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6359  }
6360  return REAL(flopenat)(dirfd, path, flags, mode);
6361}
6362
6363#define INIT_FLOPEN    \
6364  COMMON_INTERCEPT_FUNCTION(flopen); \
6365  COMMON_INTERCEPT_FUNCTION(flopenat);
6366#else
6367#define INIT_FLOPEN
6368#endif
6369
6370#if SANITIZER_INTERCEPT_FOPEN64
6371INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
6372  void *ctx;
6373  COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
6374  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6375  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
6376  __sanitizer_FILE *res = REAL(fopen64)(path, mode);
6377  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
6378  if (res) unpoison_file(res);
6379  return res;
6380}
6381INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
6382            __sanitizer_FILE *fp) {
6383  void *ctx;
6384  COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
6385  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
6386  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
6387  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
6388  __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
6389  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
6390  if (res) unpoison_file(res);
6391  return res;
6392}
6393#define INIT_FOPEN64                  \
6394  COMMON_INTERCEPT_FUNCTION(fopen64); \
6395  COMMON_INTERCEPT_FUNCTION(freopen64);
6396#else
6397#define INIT_FOPEN64
6398#endif
6399
6400#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
6401INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
6402  void *ctx;
6403  COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
6404  // FIXME: under ASan the call below may write to freed memory and corrupt
6405  // its metadata. See
6406  // https://github.com/google/sanitizers/issues/321.
6407  __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
6408  if (res) {
6409    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
6410    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
6411    unpoison_file(res);
6412    FileMetadata file = {ptr, sizeloc};
6413    SetInterceptorMetadata(res, file);
6414  }
6415  return res;
6416}
6417INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
6418            SIZE_T *sizeloc) {
6419  void *ctx;
6420  COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
6421  __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
6422  if (res) {
6423    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
6424    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
6425    unpoison_file(res);
6426    FileMetadata file = {(char **)ptr, sizeloc};
6427    SetInterceptorMetadata(res, file);
6428  }
6429  return res;
6430}
6431INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
6432            const char *mode) {
6433  void *ctx;
6434  COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
6435  // FIXME: under ASan the call below may write to freed memory and corrupt
6436  // its metadata. See
6437  // https://github.com/google/sanitizers/issues/321.
6438  __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
6439  if (res) unpoison_file(res);
6440  return res;
6441}
6442#define INIT_OPEN_MEMSTREAM                   \
6443  COMMON_INTERCEPT_FUNCTION(open_memstream);  \
6444  COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
6445  COMMON_INTERCEPT_FUNCTION(fmemopen);
6446#else
6447#define INIT_OPEN_MEMSTREAM
6448#endif
6449
6450#if SANITIZER_INTERCEPT_OBSTACK
6451static void initialize_obstack(__sanitizer_obstack *obstack) {
6452  COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
6453  if (obstack->chunk)
6454    COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
6455                                        sizeof(*obstack->chunk));
6456}
6457
6458INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
6459            int align, void *(*alloc_fn)(uptr arg, uptr sz),
6460            void (*free_fn)(uptr arg, void *p)) {
6461  void *ctx;
6462  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
6463                           free_fn);
6464  int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
6465  if (res) initialize_obstack(obstack);
6466  return res;
6467}
6468INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
6469            int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
6470  void *ctx;
6471  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
6472                           free_fn);
6473  int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
6474  if (res) initialize_obstack(obstack);
6475  return res;
6476}
6477INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
6478  void *ctx;
6479  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
6480  REAL(_obstack_newchunk)(obstack, length);
6481  if (obstack->chunk)
6482    COMMON_INTERCEPTOR_INITIALIZE_RANGE(
6483        obstack->chunk, obstack->next_free - (char *)obstack->chunk);
6484}
6485#define INIT_OBSTACK                           \
6486  COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
6487  COMMON_INTERCEPT_FUNCTION(_obstack_begin);   \
6488  COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
6489#else
6490#define INIT_OBSTACK
6491#endif
6492
6493#if SANITIZER_INTERCEPT_FFLUSH
6494INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
6495  void *ctx;
6496  COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
6497  if (fp)
6498    unpoison_file(fp);
6499  int res = REAL(fflush)(fp);
6500  // FIXME: handle fp == NULL
6501  if (fp) {
6502    const FileMetadata *m = GetInterceptorMetadata(fp);
6503    if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
6504  }
6505  return res;
6506}
6507#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
6508#else
6509#define INIT_FFLUSH
6510#endif
6511
6512#if SANITIZER_INTERCEPT_FCLOSE
6513INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
6514  void *ctx;
6515  COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
6516  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
6517  const FileMetadata *m = GetInterceptorMetadata(fp);
6518  if (fp)
6519    unpoison_file(fp);
6520  int res = REAL(fclose)(fp);
6521  if (m) {
6522    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
6523    DeleteInterceptorMetadata(fp);
6524  }
6525  return res;
6526}
6527#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
6528#else
6529#define INIT_FCLOSE
6530#endif
6531
6532#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
6533INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
6534  void *ctx;
6535  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
6536  if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
6537  void *res = COMMON_INTERCEPTOR_DLOPEN(filename, flag);
6538  Symbolizer::GetOrInit()->InvalidateModuleList();
6539  COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
6540  return res;
6541}
6542
6543INTERCEPTOR(int, dlclose, void *handle) {
6544  void *ctx;
6545  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
6546  int res = REAL(dlclose)(handle);
6547  Symbolizer::GetOrInit()->InvalidateModuleList();
6548  COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
6549  return res;
6550}
6551#define INIT_DLOPEN_DLCLOSE          \
6552  COMMON_INTERCEPT_FUNCTION(dlopen); \
6553  COMMON_INTERCEPT_FUNCTION(dlclose);
6554#else
6555#define INIT_DLOPEN_DLCLOSE
6556#endif
6557
6558#if SANITIZER_INTERCEPT_GETPASS
6559INTERCEPTOR(char *, getpass, const char *prompt) {
6560  void *ctx;
6561  COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
6562  if (prompt)
6563    COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, internal_strlen(prompt)+1);
6564  char *res = REAL(getpass)(prompt);
6565  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res)+1);
6566  return res;
6567}
6568
6569#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
6570#else
6571#define INIT_GETPASS
6572#endif
6573
6574#if SANITIZER_INTERCEPT_TIMERFD
6575INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
6576            void *old_value) {
6577  void *ctx;
6578  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
6579                           old_value);
6580  COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
6581  int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
6582  if (res != -1 && old_value)
6583    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
6584  return res;
6585}
6586
6587INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
6588  void *ctx;
6589  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
6590  int res = REAL(timerfd_gettime)(fd, curr_value);
6591  if (res != -1 && curr_value)
6592    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
6593  return res;
6594}
6595#define INIT_TIMERFD                          \
6596  COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
6597  COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
6598#else
6599#define INIT_TIMERFD
6600#endif
6601
6602#if SANITIZER_INTERCEPT_MLOCKX
6603// Linux kernel has a bug that leads to kernel deadlock if a process
6604// maps TBs of memory and then calls mlock().
6605static void MlockIsUnsupported() {
6606  static atomic_uint8_t printed;
6607  if (atomic_exchange(&printed, 1, memory_order_relaxed))
6608    return;
6609  VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
6610          SanitizerToolName);
6611}
6612
6613INTERCEPTOR(int, mlock, const void *addr, uptr len) {
6614  MlockIsUnsupported();
6615  return 0;
6616}
6617
6618INTERCEPTOR(int, munlock, const void *addr, uptr len) {
6619  MlockIsUnsupported();
6620  return 0;
6621}
6622
6623INTERCEPTOR(int, mlockall, int flags) {
6624  MlockIsUnsupported();
6625  return 0;
6626}
6627
6628INTERCEPTOR(int, munlockall, void) {
6629  MlockIsUnsupported();
6630  return 0;
6631}
6632
6633#define INIT_MLOCKX                                                            \
6634  COMMON_INTERCEPT_FUNCTION(mlock);                                            \
6635  COMMON_INTERCEPT_FUNCTION(munlock);                                          \
6636  COMMON_INTERCEPT_FUNCTION(mlockall);                                         \
6637  COMMON_INTERCEPT_FUNCTION(munlockall);
6638
6639#else
6640#define INIT_MLOCKX
6641#endif  // SANITIZER_INTERCEPT_MLOCKX
6642
6643#if SANITIZER_INTERCEPT_FOPENCOOKIE
6644struct WrappedCookie {
6645  void *real_cookie;
6646  __sanitizer_cookie_io_functions_t real_io_funcs;
6647};
6648
6649static uptr wrapped_read(void *cookie, char *buf, uptr size) {
6650  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6651  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6652  __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
6653  return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
6654}
6655
6656static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
6657  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6658  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6659  __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
6660  return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
6661}
6662
6663static int wrapped_seek(void *cookie, u64 *offset, int whence) {
6664  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6665  COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
6666  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6667  __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
6668  return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
6669                   : -1;
6670}
6671
6672static int wrapped_close(void *cookie) {
6673  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
6674  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6675  __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
6676  int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
6677  InternalFree(wrapped_cookie);
6678  return res;
6679}
6680
6681INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
6682            __sanitizer_cookie_io_functions_t io_funcs) {
6683  void *ctx;
6684  COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
6685  WrappedCookie *wrapped_cookie =
6686      (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
6687  wrapped_cookie->real_cookie = cookie;
6688  wrapped_cookie->real_io_funcs = io_funcs;
6689  __sanitizer_FILE *res =
6690      REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
6691                                               wrapped_seek, wrapped_close});
6692  return res;
6693}
6694
6695#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
6696#else
6697#define INIT_FOPENCOOKIE
6698#endif  // SANITIZER_INTERCEPT_FOPENCOOKIE
6699
6700#if SANITIZER_INTERCEPT_SEM
6701INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
6702  void *ctx;
6703  COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
6704  // Workaround a bug in glibc's "old" semaphore implementation by
6705  // zero-initializing the sem_t contents. This has to be done here because
6706  // interceptors bind to the lowest version before glibc 2.36, hitting the
6707  // buggy code path while the non-sanitized build of the same code works fine.
6708  REAL(memset)(s, 0, sizeof(*s));
6709  int res = REAL(sem_init)(s, pshared, value);
6710  return res;
6711}
6712
6713INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
6714  void *ctx;
6715  COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
6716  int res = REAL(sem_destroy)(s);
6717  return res;
6718}
6719
6720INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
6721  void *ctx;
6722  COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
6723  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
6724  if (res == 0) {
6725    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6726  }
6727  return res;
6728}
6729
6730INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
6731  void *ctx;
6732  COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
6733  int res = REAL(sem_trywait)(s);
6734  if (res == 0) {
6735    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6736  }
6737  return res;
6738}
6739
6740INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
6741  void *ctx;
6742  COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
6743  COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
6744  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
6745  if (res == 0) {
6746    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6747  }
6748  return res;
6749}
6750
6751INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
6752  void *ctx;
6753  COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
6754  COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
6755  int res = REAL(sem_post)(s);
6756  return res;
6757}
6758
6759INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
6760  void *ctx;
6761  COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
6762  int res = REAL(sem_getvalue)(s, sval);
6763  if (res == 0) {
6764    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6765    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
6766  }
6767  return res;
6768}
6769
6770INTERCEPTOR(__sanitizer_sem_t *, sem_open, const char *name, int oflag, ...) {
6771  void *ctx;
6772  va_list ap;
6773  va_start(ap, oflag);
6774  u32 mode = va_arg(ap, u32);
6775  u32 value = va_arg(ap, u32);
6776  COMMON_INTERCEPTOR_ENTER(ctx, sem_open, name, oflag, mode, value);
6777  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
6778  __sanitizer_sem_t *s = REAL(sem_open)(name, oflag, mode, value);
6779  if (s)
6780    COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, sizeof(*s));
6781  va_end(ap);
6782  return s;
6783}
6784
6785INTERCEPTOR(int, sem_unlink, const char *name) {
6786  void *ctx;
6787  COMMON_INTERCEPTOR_ENTER(ctx, sem_unlink, name);
6788  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
6789  return REAL(sem_unlink)(name);
6790}
6791
6792#  define INIT_SEM                            \
6793    COMMON_INTERCEPT_FUNCTION(sem_init);      \
6794    COMMON_INTERCEPT_FUNCTION(sem_destroy);   \
6795    COMMON_INTERCEPT_FUNCTION(sem_wait);      \
6796    COMMON_INTERCEPT_FUNCTION(sem_trywait);   \
6797    COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
6798    COMMON_INTERCEPT_FUNCTION(sem_post);      \
6799    COMMON_INTERCEPT_FUNCTION(sem_getvalue);  \
6800    COMMON_INTERCEPT_FUNCTION(sem_open);      \
6801    COMMON_INTERCEPT_FUNCTION(sem_unlink);
6802#else
6803#  define INIT_SEM
6804#endif  // SANITIZER_INTERCEPT_SEM
6805
6806#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
6807INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
6808  void *ctx;
6809  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
6810  int res = REAL(pthread_setcancelstate)(state, oldstate);
6811  if (res == 0 && oldstate != nullptr)
6812    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
6813  return res;
6814}
6815
6816INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
6817  void *ctx;
6818  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
6819  int res = REAL(pthread_setcanceltype)(type, oldtype);
6820  if (res == 0 && oldtype != nullptr)
6821    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
6822  return res;
6823}
6824#define INIT_PTHREAD_SETCANCEL                                                 \
6825  COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate);                           \
6826  COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
6827#else
6828#define INIT_PTHREAD_SETCANCEL
6829#endif
6830
6831#if SANITIZER_INTERCEPT_MINCORE
6832INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
6833  void *ctx;
6834  COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
6835  int res = REAL(mincore)(addr, length, vec);
6836  if (res == 0) {
6837    uptr page_size = GetPageSizeCached();
6838    uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
6839    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
6840  }
6841  return res;
6842}
6843#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
6844#else
6845#define INIT_MINCORE
6846#endif
6847
6848#if SANITIZER_INTERCEPT_PROCESS_VM_READV
6849INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
6850            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
6851            uptr flags) {
6852  void *ctx;
6853  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
6854                           remote_iov, riovcnt, flags);
6855  SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
6856                                       riovcnt, flags);
6857  if (res > 0)
6858    write_iovec(ctx, local_iov, liovcnt, res);
6859  return res;
6860}
6861
6862INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
6863            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
6864            uptr flags) {
6865  void *ctx;
6866  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
6867                           remote_iov, riovcnt, flags);
6868  SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
6869                                        riovcnt, flags);
6870  if (res > 0)
6871    read_iovec(ctx, local_iov, liovcnt, res);
6872  return res;
6873}
6874#define INIT_PROCESS_VM_READV                                                  \
6875  COMMON_INTERCEPT_FUNCTION(process_vm_readv);                                 \
6876  COMMON_INTERCEPT_FUNCTION(process_vm_writev);
6877#else
6878#define INIT_PROCESS_VM_READV
6879#endif
6880
6881#if SANITIZER_INTERCEPT_CTERMID
6882INTERCEPTOR(char *, ctermid, char *s) {
6883  void *ctx;
6884  COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
6885  char *res = REAL(ctermid)(s);
6886  if (res) {
6887    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
6888  }
6889  return res;
6890}
6891#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
6892#else
6893#define INIT_CTERMID
6894#endif
6895
6896#if SANITIZER_INTERCEPT_CTERMID_R
6897INTERCEPTOR(char *, ctermid_r, char *s) {
6898  void *ctx;
6899  COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
6900  char *res = REAL(ctermid_r)(s);
6901  if (res) {
6902    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
6903  }
6904  return res;
6905}
6906#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
6907#else
6908#define INIT_CTERMID_R
6909#endif
6910
6911#if SANITIZER_INTERCEPT_RECV_RECVFROM
6912INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
6913  void *ctx;
6914  COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
6915  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6916  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
6917  if (res > 0) {
6918    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
6919  }
6920  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
6921  return res;
6922}
6923
6924INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
6925            void *srcaddr, int *addrlen) {
6926  void *ctx;
6927  COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
6928                           addrlen);
6929  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6930  SIZE_T srcaddr_sz;
6931  if (srcaddr) srcaddr_sz = *addrlen;
6932  (void)srcaddr_sz;  // prevent "set but not used" warning
6933  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
6934  if (res > 0)
6935    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
6936  if (res >= 0 && srcaddr)
6937    COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
6938                                        Min((SIZE_T)*addrlen, srcaddr_sz));
6939  return res;
6940}
6941#define INIT_RECV_RECVFROM          \
6942  COMMON_INTERCEPT_FUNCTION(recv);  \
6943  COMMON_INTERCEPT_FUNCTION(recvfrom);
6944#else
6945#define INIT_RECV_RECVFROM
6946#endif
6947
6948#if SANITIZER_INTERCEPT_SEND_SENDTO
6949INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
6950  void *ctx;
6951  COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
6952  if (fd >= 0) {
6953    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6954    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
6955  }
6956  SSIZE_T res = REAL(send)(fd, buf, len, flags);
6957  if (common_flags()->intercept_send && res > 0)
6958    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
6959  return res;
6960}
6961
6962INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
6963            void *dstaddr, int addrlen) {
6964  void *ctx;
6965  COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
6966  if (fd >= 0) {
6967    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6968    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
6969  }
6970  // Can't check dstaddr as it may have uninitialized padding at the end.
6971  SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
6972  if (common_flags()->intercept_send && res > 0)
6973    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
6974  return res;
6975}
6976#define INIT_SEND_SENDTO           \
6977  COMMON_INTERCEPT_FUNCTION(send); \
6978  COMMON_INTERCEPT_FUNCTION(sendto);
6979#else
6980#define INIT_SEND_SENDTO
6981#endif
6982
6983#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
6984INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
6985  void *ctx;
6986  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
6987  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6988  int res = REAL(eventfd_read)(fd, value);
6989  if (res == 0) {
6990    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
6991    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
6992  }
6993  return res;
6994}
6995INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
6996  void *ctx;
6997  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
6998  if (fd >= 0) {
6999    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
7000    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
7001  }
7002  int res = REAL(eventfd_write)(fd, value);
7003  return res;
7004}
7005#define INIT_EVENTFD_READ_WRITE            \
7006  COMMON_INTERCEPT_FUNCTION(eventfd_read); \
7007  COMMON_INTERCEPT_FUNCTION(eventfd_write)
7008#else
7009#define INIT_EVENTFD_READ_WRITE
7010#endif
7011
7012#if SANITIZER_INTERCEPT_STAT
7013INTERCEPTOR(int, stat, const char *path, void *buf) {
7014  void *ctx;
7015  COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
7016  if (common_flags()->intercept_stat)
7017    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7018  int res = REAL(stat)(path, buf);
7019  if (!res)
7020    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
7021  return res;
7022}
7023#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
7024#else
7025#define INIT_STAT
7026#endif
7027
7028#if SANITIZER_INTERCEPT_STAT64
7029INTERCEPTOR(int, stat64, const char *path, void *buf) {
7030  void *ctx;
7031  COMMON_INTERCEPTOR_ENTER(ctx, stat64, path, buf);
7032  if (common_flags()->intercept_stat)
7033    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7034  int res = REAL(stat64)(path, buf);
7035  if (!res)
7036    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
7037  return res;
7038}
7039#define INIT_STAT64 COMMON_INTERCEPT_FUNCTION(stat64)
7040#else
7041#define INIT_STAT64
7042#endif
7043
7044
7045#if SANITIZER_INTERCEPT_LSTAT
7046INTERCEPTOR(int, lstat, const char *path, void *buf) {
7047  void *ctx;
7048  COMMON_INTERCEPTOR_ENTER(ctx, lstat, path, buf);
7049  if (common_flags()->intercept_stat)
7050    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7051  int res = REAL(lstat)(path, buf);
7052  if (!res)
7053    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
7054  return res;
7055}
7056#define INIT_LSTAT COMMON_INTERCEPT_FUNCTION(lstat)
7057#else
7058#define INIT_LSTAT
7059#endif
7060
7061#if SANITIZER_INTERCEPT_STAT64
7062INTERCEPTOR(int, lstat64, const char *path, void *buf) {
7063  void *ctx;
7064  COMMON_INTERCEPTOR_ENTER(ctx, lstat64, path, buf);
7065  if (common_flags()->intercept_stat)
7066    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7067  int res = REAL(lstat64)(path, buf);
7068  if (!res)
7069    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
7070  return res;
7071}
7072#define INIT_LSTAT64 COMMON_INTERCEPT_FUNCTION(lstat64)
7073#else
7074#define INIT_LSTAT64
7075#endif
7076
7077#if SANITIZER_INTERCEPT___XSTAT
7078INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
7079  void *ctx;
7080  COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
7081  if (common_flags()->intercept_stat)
7082    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7083  int res = REAL(__xstat)(version, path, buf);
7084  if (!res)
7085    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
7086  return res;
7087}
7088#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
7089#else
7090#define INIT___XSTAT
7091#endif
7092
7093#if SANITIZER_INTERCEPT___XSTAT64
7094INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
7095  void *ctx;
7096  COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
7097  if (common_flags()->intercept_stat)
7098    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7099  int res = REAL(__xstat64)(version, path, buf);
7100  if (!res)
7101    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
7102  return res;
7103}
7104#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
7105#else
7106#define INIT___XSTAT64
7107#endif
7108
7109#if SANITIZER_INTERCEPT___LXSTAT
7110INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
7111  void *ctx;
7112  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
7113  if (common_flags()->intercept_stat)
7114    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7115  int res = REAL(__lxstat)(version, path, buf);
7116  if (!res)
7117    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
7118  return res;
7119}
7120#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
7121#else
7122#define INIT___LXSTAT
7123#endif
7124
7125#if SANITIZER_INTERCEPT___LXSTAT64
7126INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
7127  void *ctx;
7128  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
7129  if (common_flags()->intercept_stat)
7130    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
7131  int res = REAL(__lxstat64)(version, path, buf);
7132  if (!res)
7133    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
7134  return res;
7135}
7136#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
7137#else
7138#define INIT___LXSTAT64
7139#endif
7140
7141// FIXME: add other *stat interceptor
7142
7143#if SANITIZER_INTERCEPT_UTMP
7144INTERCEPTOR(void *, getutent, int dummy) {
7145  void *ctx;
7146  COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
7147  void *res = REAL(getutent)(dummy);
7148  if (res)
7149    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
7150  return res;
7151}
7152INTERCEPTOR(void *, getutid, void *ut) {
7153  void *ctx;
7154  COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
7155  void *res = REAL(getutid)(ut);
7156  if (res)
7157    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
7158  return res;
7159}
7160INTERCEPTOR(void *, getutline, void *ut) {
7161  void *ctx;
7162  COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
7163  void *res = REAL(getutline)(ut);
7164  if (res)
7165    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
7166  return res;
7167}
7168#define INIT_UTMP                      \
7169  COMMON_INTERCEPT_FUNCTION(getutent); \
7170  COMMON_INTERCEPT_FUNCTION(getutid);  \
7171  COMMON_INTERCEPT_FUNCTION(getutline);
7172#else
7173#define INIT_UTMP
7174#endif
7175
7176#if SANITIZER_INTERCEPT_UTMPX
7177INTERCEPTOR(void *, getutxent, int dummy) {
7178  void *ctx;
7179  COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
7180  void *res = REAL(getutxent)(dummy);
7181  if (res)
7182    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
7183  return res;
7184}
7185INTERCEPTOR(void *, getutxid, void *ut) {
7186  void *ctx;
7187  COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
7188  void *res = REAL(getutxid)(ut);
7189  if (res)
7190    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
7191  return res;
7192}
7193INTERCEPTOR(void *, getutxline, void *ut) {
7194  void *ctx;
7195  COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
7196  void *res = REAL(getutxline)(ut);
7197  if (res)
7198    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
7199  return res;
7200}
7201INTERCEPTOR(void *, pututxline, const void *ut) {
7202  void *ctx;
7203  COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut);
7204  if (ut)
7205    COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz);
7206  void *res = REAL(pututxline)(ut);
7207  if (res)
7208    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz);
7209  return res;
7210}
7211#define INIT_UTMPX                      \
7212  COMMON_INTERCEPT_FUNCTION(getutxent); \
7213  COMMON_INTERCEPT_FUNCTION(getutxid);  \
7214  COMMON_INTERCEPT_FUNCTION(getutxline); \
7215  COMMON_INTERCEPT_FUNCTION(pututxline);
7216#else
7217#define INIT_UTMPX
7218#endif
7219
7220#if SANITIZER_INTERCEPT_GETLOADAVG
7221INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
7222  void *ctx;
7223  COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
7224  int res = REAL(getloadavg)(loadavg, nelem);
7225  if (res > 0)
7226    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
7227  return res;
7228}
7229#define INIT_GETLOADAVG                      \
7230  COMMON_INTERCEPT_FUNCTION(getloadavg);
7231#else
7232#define INIT_GETLOADAVG
7233#endif
7234
7235#if SANITIZER_INTERCEPT_MCHECK_MPROBE
7236INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
7237  return 0;
7238}
7239
7240INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
7241  return 0;
7242}
7243
7244INTERCEPTOR(int, mprobe, void *ptr) {
7245  return 0;
7246}
7247#endif
7248
7249INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
7250  void *ctx;
7251  COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
7252  SIZE_T res = REAL(wcslen)(s);
7253  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
7254  return res;
7255}
7256
7257INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
7258  void *ctx;
7259  COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
7260  SIZE_T res = REAL(wcsnlen)(s, n);
7261  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
7262  return res;
7263}
7264#define INIT_WCSLEN                  \
7265  COMMON_INTERCEPT_FUNCTION(wcslen); \
7266  COMMON_INTERCEPT_FUNCTION(wcsnlen);
7267
7268#if SANITIZER_INTERCEPT_WCSCAT
7269INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
7270  void *ctx;
7271  COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
7272  SIZE_T src_size = internal_wcslen(src);
7273  SIZE_T dst_size = internal_wcslen(dst);
7274  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
7275  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
7276  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
7277                                 (src_size + 1) * sizeof(wchar_t));
7278  return REAL(wcscat)(dst, src);
7279}
7280
7281INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
7282  void *ctx;
7283  COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
7284  SIZE_T src_size = internal_wcsnlen(src, n);
7285  SIZE_T dst_size = internal_wcslen(dst);
7286  COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
7287                                Min(src_size + 1, n) * sizeof(wchar_t));
7288  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
7289  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
7290                                 (src_size + 1) * sizeof(wchar_t));
7291  return REAL(wcsncat)(dst, src, n);
7292}
7293#define INIT_WCSCAT                  \
7294  COMMON_INTERCEPT_FUNCTION(wcscat); \
7295  COMMON_INTERCEPT_FUNCTION(wcsncat);
7296#else
7297#define INIT_WCSCAT
7298#endif
7299
7300#if SANITIZER_INTERCEPT_WCSDUP
7301INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
7302  void *ctx;
7303  COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
7304  SIZE_T len = internal_wcslen(s);
7305  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
7306  wchar_t *result = REAL(wcsdup)(s);
7307  if (result)
7308    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(wchar_t) * (len + 1));
7309  return result;
7310}
7311
7312#define INIT_WCSDUP COMMON_INTERCEPT_FUNCTION(wcsdup);
7313#else
7314#define INIT_WCSDUP
7315#endif
7316
7317#if SANITIZER_INTERCEPT_STRXFRM
7318static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }
7319
7320static SIZE_T RealStrLen(const wchar_t *str) { return internal_wcslen(str); }
7321
7322#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...)             \
7323  {                                                                        \
7324    void *ctx;                                                             \
7325    COMMON_INTERCEPTOR_ENTER(ctx, strxfrm, dest, src, len, ##__VA_ARGS__); \
7326    COMMON_INTERCEPTOR_READ_RANGE(ctx, src,                                \
7327                                  sizeof(*src) * (RealStrLen(src) + 1));   \
7328    SIZE_T res = REAL(strxfrm)(dest, src, len, ##__VA_ARGS__);             \
7329    if (res < len)                                                         \
7330      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, sizeof(*src) * (res + 1)); \
7331    return res;                                                            \
7332  }
7333
7334INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T len) {
7335  STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len);
7336}
7337
7338INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T len,
7339            void *locale) {
7340  STRXFRM_INTERCEPTOR_IMPL(strxfrm_l, dest, src, len, locale);
7341}
7342
7343#define INIT_STRXFRM                  \
7344  COMMON_INTERCEPT_FUNCTION(strxfrm); \
7345  COMMON_INTERCEPT_FUNCTION(strxfrm_l);
7346#else
7347#define INIT_STRXFRM
7348#endif
7349
7350#if SANITIZER_INTERCEPT___STRXFRM_L
7351INTERCEPTOR(SIZE_T, __strxfrm_l, char *dest, const char *src, SIZE_T len,
7352            void *locale) {
7353  STRXFRM_INTERCEPTOR_IMPL(__strxfrm_l, dest, src, len, locale);
7354}
7355
7356#define INIT___STRXFRM_L COMMON_INTERCEPT_FUNCTION(__strxfrm_l);
7357#else
7358#define INIT___STRXFRM_L
7359#endif
7360
7361#if SANITIZER_INTERCEPT_WCSXFRM
7362INTERCEPTOR(SIZE_T, wcsxfrm, wchar_t *dest, const wchar_t *src, SIZE_T len) {
7363  STRXFRM_INTERCEPTOR_IMPL(wcsxfrm, dest, src, len);
7364}
7365
7366INTERCEPTOR(SIZE_T, wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
7367            void *locale) {
7368  STRXFRM_INTERCEPTOR_IMPL(wcsxfrm_l, dest, src, len, locale);
7369}
7370
7371#define INIT_WCSXFRM                  \
7372  COMMON_INTERCEPT_FUNCTION(wcsxfrm); \
7373  COMMON_INTERCEPT_FUNCTION(wcsxfrm_l);
7374#else
7375#define INIT_WCSXFRM
7376#endif
7377
7378#if SANITIZER_INTERCEPT___WCSXFRM_L
7379INTERCEPTOR(SIZE_T, __wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
7380            void *locale) {
7381  STRXFRM_INTERCEPTOR_IMPL(__wcsxfrm_l, dest, src, len, locale);
7382}
7383
7384#define INIT___WCSXFRM_L COMMON_INTERCEPT_FUNCTION(__wcsxfrm_l);
7385#else
7386#define INIT___WCSXFRM_L
7387#endif
7388
7389#if SANITIZER_INTERCEPT_ACCT
7390INTERCEPTOR(int, acct, const char *file) {
7391  void *ctx;
7392  COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
7393  if (file)
7394    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
7395  return REAL(acct)(file);
7396}
7397#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
7398#else
7399#define INIT_ACCT
7400#endif
7401
7402#if SANITIZER_INTERCEPT_USER_FROM_UID
7403INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
7404  void *ctx;
7405  const char *user;
7406  COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
7407  user = REAL(user_from_uid)(uid, nouser);
7408  if (user)
7409    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, internal_strlen(user) + 1);
7410  return user;
7411}
7412#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
7413#else
7414#define INIT_USER_FROM_UID
7415#endif
7416
7417#if SANITIZER_INTERCEPT_UID_FROM_USER
7418INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
7419  void *ctx;
7420  int res;
7421  COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
7422  if (name)
7423    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7424  res = REAL(uid_from_user)(name, uid);
7425  if (uid)
7426    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
7427  return res;
7428}
7429#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user)
7430#else
7431#define INIT_UID_FROM_USER
7432#endif
7433
7434#if SANITIZER_INTERCEPT_GROUP_FROM_GID
7435INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
7436  void *ctx;
7437  const char *group;
7438  COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
7439  group = REAL(group_from_gid)(gid, nogroup);
7440  if (group)
7441    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, internal_strlen(group) + 1);
7442  return group;
7443}
7444#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
7445#else
7446#define INIT_GROUP_FROM_GID
7447#endif
7448
7449#if SANITIZER_INTERCEPT_GID_FROM_GROUP
7450INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
7451  void *ctx;
7452  int res;
7453  COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
7454  if (group)
7455    COMMON_INTERCEPTOR_READ_RANGE(ctx, group, internal_strlen(group) + 1);
7456  res = REAL(gid_from_group)(group, gid);
7457  if (gid)
7458    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
7459  return res;
7460}
7461#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group)
7462#else
7463#define INIT_GID_FROM_GROUP
7464#endif
7465
7466#if SANITIZER_INTERCEPT_ACCESS
7467INTERCEPTOR(int, access, const char *path, int mode) {
7468  void *ctx;
7469  COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
7470  if (path)
7471    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
7472  return REAL(access)(path, mode);
7473}
7474#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
7475#else
7476#define INIT_ACCESS
7477#endif
7478
7479#if SANITIZER_INTERCEPT_FACCESSAT
7480INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
7481  void *ctx;
7482  COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
7483  if (path)
7484    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
7485  return REAL(faccessat)(fd, path, mode, flags);
7486}
7487#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
7488#else
7489#define INIT_FACCESSAT
7490#endif
7491
7492#if SANITIZER_INTERCEPT_GETGROUPLIST
7493INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
7494            int *ngroups) {
7495  void *ctx;
7496  int res;
7497  COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
7498  if (name)
7499    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7500  if (ngroups)
7501    COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
7502  res = REAL(getgrouplist)(name, basegid, groups, ngroups);
7503  if (!res && groups && ngroups) {
7504    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
7505    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
7506  }
7507  return res;
7508}
7509
7510#define INIT_GETGROUPLIST COMMON_INTERCEPT_FUNCTION(getgrouplist);
7511#else
7512#define INIT_GETGROUPLIST
7513#endif
7514
7515#if SANITIZER_INTERCEPT_GETGROUPMEMBERSHIP
7516INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
7517            int maxgrp, int *ngroups) {
7518  void *ctx;
7519  int res;
7520  COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
7521                           maxgrp, ngroups);
7522  if (name)
7523    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7524  res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
7525  if (!res && groups && ngroups) {
7526    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
7527    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
7528  }
7529  return res;
7530}
7531
7532#define INIT_GETGROUPMEMBERSHIP COMMON_INTERCEPT_FUNCTION(getgroupmembership);
7533#else
7534#define INIT_GETGROUPMEMBERSHIP
7535#endif
7536
7537#if SANITIZER_INTERCEPT_READLINK
7538INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
7539  void* ctx;
7540  COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
7541  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
7542  SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
7543  if (res > 0)
7544    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
7545  return res;
7546}
7547
7548#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink)
7549#else
7550#define INIT_READLINK
7551#endif
7552
7553#if SANITIZER_INTERCEPT_READLINKAT
7554INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
7555            SIZE_T bufsiz) {
7556  void* ctx;
7557  COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
7558  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
7559  SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
7560  if (res > 0)
7561    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
7562  return res;
7563}
7564
7565#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat)
7566#else
7567#define INIT_READLINKAT
7568#endif
7569
7570#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT
7571INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
7572            struct file_handle *handle, int *mount_id, int flags) {
7573  void* ctx;
7574  COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
7575                           mount_id, flags);
7576  COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, internal_strlen(pathname) + 1);
7577
7578  __sanitizer_file_handle *sanitizer_handle =
7579      reinterpret_cast<__sanitizer_file_handle*>(handle);
7580  COMMON_INTERCEPTOR_READ_RANGE(
7581      ctx, &sanitizer_handle->handle_bytes,
7582      sizeof(sanitizer_handle->handle_bytes));
7583
7584  int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags);
7585  if (!res) {
7586    COMMON_INTERCEPTOR_WRITE_RANGE(
7587        ctx, &sanitizer_handle->handle_bytes,
7588        sizeof(sanitizer_handle->handle_bytes));
7589    COMMON_INTERCEPTOR_WRITE_RANGE(
7590        ctx, &sanitizer_handle->handle_type,
7591        sizeof(sanitizer_handle->handle_type));
7592    COMMON_INTERCEPTOR_WRITE_RANGE(
7593        ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
7594    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id));
7595  }
7596  return res;
7597}
7598
7599#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at)
7600#else
7601#define INIT_NAME_TO_HANDLE_AT
7602#endif
7603
7604#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT
7605INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
7606            int flags) {
7607  void* ctx;
7608  COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags);
7609
7610  __sanitizer_file_handle *sanitizer_handle =
7611      reinterpret_cast<__sanitizer_file_handle*>(handle);
7612  COMMON_INTERCEPTOR_READ_RANGE(
7613      ctx, &sanitizer_handle->handle_bytes,
7614      sizeof(sanitizer_handle->handle_bytes));
7615  COMMON_INTERCEPTOR_READ_RANGE(
7616      ctx, &sanitizer_handle->handle_type,
7617      sizeof(sanitizer_handle->handle_type));
7618  COMMON_INTERCEPTOR_READ_RANGE(
7619      ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
7620
7621  return REAL(open_by_handle_at)(mount_fd, handle, flags);
7622}
7623
7624#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
7625#else
7626#define INIT_OPEN_BY_HANDLE_AT
7627#endif
7628
7629#if SANITIZER_INTERCEPT_STRLCPY
7630INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
7631  void *ctx;
7632  SIZE_T res;
7633  COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size);
7634  if (src) {
7635    // Keep strnlen as macro argument, as macro may ignore it.
7636    COMMON_INTERCEPTOR_READ_STRING(
7637        ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
7638  }
7639  res = REAL(strlcpy)(dst, src, size);
7640  COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, internal_strlen(dst) + 1);
7641  return res;
7642}
7643
7644INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) {
7645  void *ctx;
7646  SIZE_T len = 0;
7647  COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size);
7648  // src is checked in the strlcpy() interceptor
7649  if (dst) {
7650    len = internal_strnlen(dst, size);
7651    COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1);
7652  }
7653  // Reuse the rest of the code in the strlcpy() interceptor
7654  return WRAP(strlcpy)(dst + len, src, size - len) + len;
7655}
7656#define INIT_STRLCPY \
7657  COMMON_INTERCEPT_FUNCTION(strlcpy); \
7658  COMMON_INTERCEPT_FUNCTION(strlcat);
7659#else
7660#define INIT_STRLCPY
7661#endif
7662
7663#if SANITIZER_INTERCEPT_MMAP
7664INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
7665            OFF_T off) {
7666  void *ctx;
7667  if (common_flags()->detect_write_exec)
7668    ReportMmapWriteExec(prot, flags);
7669  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7670    return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
7671  COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
7672  COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off);
7673}
7674
7675INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
7676  void *ctx;
7677  if (common_flags()->detect_write_exec)
7678    ReportMmapWriteExec(prot, 0);
7679  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7680    return (int)internal_mprotect(addr, sz, prot);
7681  COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot);
7682  MprotectMallocZones(addr, prot);
7683  return REAL(mprotect)(addr, sz, prot);
7684}
7685#define INIT_MMAP                                                              \
7686  COMMON_INTERCEPT_FUNCTION(mmap);                                             \
7687  COMMON_INTERCEPT_FUNCTION(mprotect);
7688#else
7689#define INIT_MMAP
7690#endif
7691
7692#if SANITIZER_INTERCEPT_MMAP64
7693INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
7694            OFF64_T off) {
7695  void *ctx;
7696  if (common_flags()->detect_write_exec)
7697    ReportMmapWriteExec(prot, flags);
7698  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7699    return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
7700  COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
7701  COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap64, addr, sz, prot, flags, fd, off);
7702}
7703#define INIT_MMAP64 COMMON_INTERCEPT_FUNCTION(mmap64);
7704#else
7705#define INIT_MMAP64
7706#endif
7707
7708#if SANITIZER_INTERCEPT_DEVNAME
7709INTERCEPTOR(char *, devname, u64 dev, u32 type) {
7710  void *ctx;
7711  char *name;
7712  COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
7713  name = REAL(devname)(dev, type);
7714  if (name)
7715    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
7716  return name;
7717}
7718#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
7719#else
7720#define INIT_DEVNAME
7721#endif
7722
7723#if SANITIZER_INTERCEPT_DEVNAME_R
7724#if SANITIZER_NETBSD
7725#define DEVNAME_R_RETTYPE int
7726#define DEVNAME_R_SUCCESS(x) (!(x))
7727#else
7728#define DEVNAME_R_RETTYPE char*
7729#define DEVNAME_R_SUCCESS(x) (x)
7730#endif
7731INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
7732            uptr len) {
7733  void *ctx;
7734  COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
7735  DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
7736  if (DEVNAME_R_SUCCESS(res))
7737    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, internal_strlen(path) + 1);
7738  return res;
7739}
7740#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
7741#else
7742#define INIT_DEVNAME_R
7743#endif
7744
7745#if SANITIZER_INTERCEPT_FGETLN
7746INTERCEPTOR(char *, fgetln, __sanitizer_FILE *stream, SIZE_T *len) {
7747  void *ctx;
7748  COMMON_INTERCEPTOR_ENTER(ctx, fgetln, stream, len);
7749  char *str = REAL(fgetln)(stream, len);
7750  if (str && len) {
7751    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
7752    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, *len);
7753  }
7754  return str;
7755}
7756#define INIT_FGETLN COMMON_INTERCEPT_FUNCTION(fgetln)
7757#else
7758#define INIT_FGETLN
7759#endif
7760
7761#if SANITIZER_INTERCEPT_STRMODE
7762INTERCEPTOR(void, strmode, u32 mode, char *bp) {
7763  void *ctx;
7764  COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
7765  REAL(strmode)(mode, bp);
7766  if (bp)
7767    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, internal_strlen(bp) + 1);
7768}
7769#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
7770#else
7771#define INIT_STRMODE
7772#endif
7773
7774#if SANITIZER_INTERCEPT_TTYENT
7775INTERCEPTOR(struct __sanitizer_ttyent *, getttyent, void) {
7776  void *ctx;
7777  COMMON_INTERCEPTOR_ENTER(ctx, getttyent);
7778  struct __sanitizer_ttyent *ttyent = REAL(getttyent)();
7779  if (ttyent)
7780    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
7781  return ttyent;
7782}
7783INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
7784  void *ctx;
7785  COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
7786  if (name)
7787    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7788  struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
7789  if (ttyent)
7790    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
7791  return ttyent;
7792}
7793#define INIT_TTYENT \
7794  COMMON_INTERCEPT_FUNCTION(getttyent); \
7795  COMMON_INTERCEPT_FUNCTION(getttynam);
7796#else
7797#define INIT_TTYENT
7798#endif
7799
7800#if SANITIZER_INTERCEPT_TTYENTPATH
7801INTERCEPTOR(int, setttyentpath, char *path) {
7802  void *ctx;
7803  COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
7804  if (path)
7805    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
7806  return REAL(setttyentpath)(path);
7807}
7808#define INIT_TTYENTPATH COMMON_INTERCEPT_FUNCTION(setttyentpath);
7809#else
7810#define INIT_TTYENTPATH
7811#endif
7812
7813#if SANITIZER_INTERCEPT_PROTOENT
7814static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
7815  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
7816
7817  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, internal_strlen(p->p_name) + 1);
7818
7819  SIZE_T pp_size = 1; // One handles the trailing \0
7820
7821  for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
7822      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);
7823
7824  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
7825                                  pp_size * sizeof(char **));
7826}
7827
7828INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
7829  void *ctx;
7830  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
7831  struct __sanitizer_protoent *p = REAL(getprotoent)();
7832  if (p)
7833    write_protoent(ctx, p);
7834  return p;
7835}
7836
7837INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
7838  void *ctx;
7839  COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
7840  if (name)
7841    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7842  struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
7843  if (p)
7844    write_protoent(ctx, p);
7845  return p;
7846}
7847
7848INTERCEPTOR(struct __sanitizer_protoent *, getprotobynumber, int proto) {
7849  void *ctx;
7850  COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber, proto);
7851  struct __sanitizer_protoent *p = REAL(getprotobynumber)(proto);
7852  if (p)
7853    write_protoent(ctx, p);
7854  return p;
7855}
7856#define INIT_PROTOENT \
7857  COMMON_INTERCEPT_FUNCTION(getprotoent); \
7858  COMMON_INTERCEPT_FUNCTION(getprotobyname); \
7859  COMMON_INTERCEPT_FUNCTION(getprotobynumber)
7860#else
7861#define INIT_PROTOENT
7862#endif
7863
7864#if SANITIZER_INTERCEPT_PROTOENT_R
7865INTERCEPTOR(int, getprotoent_r, struct __sanitizer_protoent *result_buf,
7866            char *buf, SIZE_T buflen, struct __sanitizer_protoent **result) {
7867  void *ctx;
7868  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent_r, result_buf, buf, buflen,
7869                           result);
7870  int res = REAL(getprotoent_r)(result_buf, buf, buflen, result);
7871
7872  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
7873  if (!res && *result)
7874    write_protoent(ctx, *result);
7875  return res;
7876}
7877
7878INTERCEPTOR(int, getprotobyname_r, const char *name,
7879            struct __sanitizer_protoent *result_buf, char *buf, SIZE_T buflen,
7880            struct __sanitizer_protoent **result) {
7881  void *ctx;
7882  COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
7883                           buflen, result);
7884  if (name)
7885    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7886  int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);
7887
7888  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
7889  if (!res && *result)
7890    write_protoent(ctx, *result);
7891  return res;
7892}
7893
7894INTERCEPTOR(int, getprotobynumber_r, int num,
7895            struct __sanitizer_protoent *result_buf, char *buf,
7896            SIZE_T buflen, struct __sanitizer_protoent **result) {
7897  void *ctx;
7898  COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber_r, num, result_buf, buf,
7899                           buflen, result);
7900  int res = REAL(getprotobynumber_r)(num, result_buf, buf, buflen, result);
7901
7902  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
7903  if (!res && *result)
7904    write_protoent(ctx, *result);
7905  return res;
7906}
7907
7908#define INIT_PROTOENT_R \
7909  COMMON_INTERCEPT_FUNCTION(getprotoent_r); \
7910  COMMON_INTERCEPT_FUNCTION(getprotobyname_r); \
7911  COMMON_INTERCEPT_FUNCTION(getprotobynumber_r);
7912#else
7913#define INIT_PROTOENT_R
7914#endif
7915
7916#if SANITIZER_INTERCEPT_NETENT
7917INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
7918  void *ctx;
7919  COMMON_INTERCEPTOR_ENTER(ctx, getnetent);
7920  struct __sanitizer_netent *n = REAL(getnetent)();
7921  if (n) {
7922    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
7923
7924    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
7925
7926    SIZE_T nn_size = 1; // One handles the trailing \0
7927
7928    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7929      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
7930
7931    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7932                                   nn_size * sizeof(char **));
7933  }
7934  return n;
7935}
7936
7937INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
7938  void *ctx;
7939  COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
7940  if (name)
7941    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
7942  struct __sanitizer_netent *n = REAL(getnetbyname)(name);
7943  if (n) {
7944    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
7945
7946    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
7947
7948    SIZE_T nn_size = 1; // One handles the trailing \0
7949
7950    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7951      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
7952
7953    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7954                                   nn_size * sizeof(char **));
7955  }
7956  return n;
7957}
7958
7959INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
7960  void *ctx;
7961  COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type);
7962  struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type);
7963  if (n) {
7964    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
7965
7966    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
7967
7968    SIZE_T nn_size = 1; // One handles the trailing \0
7969
7970    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7971      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
7972
7973    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7974                                   nn_size * sizeof(char **));
7975  }
7976  return n;
7977}
7978#define INIT_NETENT \
7979  COMMON_INTERCEPT_FUNCTION(getnetent); \
7980  COMMON_INTERCEPT_FUNCTION(getnetbyname); \
7981  COMMON_INTERCEPT_FUNCTION(getnetbyaddr)
7982#else
7983#define INIT_NETENT
7984#endif
7985
7986#if SANITIZER_INTERCEPT_GETMNTINFO
7987INTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) {
7988  void *ctx;
7989  COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags);
7990  int cnt = REAL(getmntinfo)(mntbufp, flags);
7991  if (cnt > 0 && mntbufp) {
7992    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
7993    if (*mntbufp)
7994#if SANITIZER_NETBSD
7995      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz);
7996#else
7997      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz);
7998#endif
7999  }
8000  return cnt;
8001}
8002#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo)
8003#else
8004#define INIT_GETMNTINFO
8005#endif
8006
8007#if SANITIZER_INTERCEPT_MI_VECTOR_HASH
8008INTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed,
8009            u32 hashes[3]) {
8010  void *ctx;
8011  COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes);
8012  if (key)
8013    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len);
8014  REAL(mi_vector_hash)(key, len, seed, hashes);
8015  if (hashes)
8016    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3);
8017}
8018#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash)
8019#else
8020#define INIT_MI_VECTOR_HASH
8021#endif
8022
8023#if SANITIZER_INTERCEPT_SETVBUF
8024INTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode,
8025  SIZE_T size) {
8026  void *ctx;
8027  COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size);
8028  int ret = REAL(setvbuf)(stream, buf, mode, size);
8029  if (buf)
8030    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
8031  if (stream)
8032      unpoison_file(stream);
8033  return ret;
8034}
8035
8036INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
8037  void *ctx;
8038  COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf);
8039  REAL(setbuf)(stream, buf);
8040  if (buf) {
8041    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
8042  }
8043  if (stream)
8044      unpoison_file(stream);
8045}
8046
8047INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, SIZE_T size) {
8048  void *ctx;
8049  COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, size);
8050  REAL(setbuffer)(stream, buf, size);
8051  if (buf) {
8052    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
8053  }
8054  if (stream)
8055    unpoison_file(stream);
8056}
8057
8058INTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) {
8059  void *ctx;
8060  COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream);
8061  REAL(setlinebuf)(stream);
8062  if (stream)
8063    unpoison_file(stream);
8064}
8065#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \
8066    COMMON_INTERCEPT_FUNCTION(setbuf); \
8067    COMMON_INTERCEPT_FUNCTION(setbuffer); \
8068    COMMON_INTERCEPT_FUNCTION(setlinebuf)
8069#else
8070#define INIT_SETVBUF
8071#endif
8072
8073#if SANITIZER_INTERCEPT_GETVFSSTAT
8074INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
8075  void *ctx;
8076  COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
8077  int ret = REAL(getvfsstat)(buf, bufsize, flags);
8078  if (buf && ret > 0)
8079    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz);
8080  return ret;
8081}
8082#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat)
8083#else
8084#define INIT_GETVFSSTAT
8085#endif
8086
8087#if SANITIZER_INTERCEPT_REGEX
8088INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
8089  void *ctx;
8090  COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
8091  if (pattern)
8092    COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, internal_strlen(pattern) + 1);
8093  int res = REAL(regcomp)(preg, pattern, cflags);
8094  if (preg)
8095    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
8096  return res;
8097}
8098INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
8099            struct __sanitizer_regmatch *pmatch[], int eflags) {
8100  void *ctx;
8101  COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags);
8102  if (preg)
8103    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
8104  if (string)
8105    COMMON_INTERCEPTOR_READ_RANGE(ctx, string, internal_strlen(string) + 1);
8106  int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
8107  if (!res && pmatch)
8108    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
8109  return res;
8110}
8111INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
8112            SIZE_T errbuf_size) {
8113  void *ctx;
8114  COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size);
8115  if (preg)
8116    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
8117  SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
8118  if (errbuf)
8119    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, internal_strlen(errbuf) + 1);
8120  return res;
8121}
8122INTERCEPTOR(void, regfree, const void *preg) {
8123  void *ctx;
8124  COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg);
8125  if (preg)
8126    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
8127  REAL(regfree)(preg);
8128}
8129#define INIT_REGEX                                                             \
8130  COMMON_INTERCEPT_FUNCTION(regcomp);                                          \
8131  COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4");             \
8132  COMMON_INTERCEPT_FUNCTION(regerror);                                         \
8133  COMMON_INTERCEPT_FUNCTION(regfree);
8134#else
8135#define INIT_REGEX
8136#endif
8137
8138#if SANITIZER_INTERCEPT_REGEXSUB
8139INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
8140            const struct __sanitizer_regmatch *rm, const char *str) {
8141  void *ctx;
8142  COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
8143  if (sub)
8144    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
8145  // The implementation demands and hardcodes 10 elements
8146  if (rm)
8147    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
8148  if (str)
8149    COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
8150  SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
8151  if (res > 0 && buf)
8152    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
8153  return res;
8154}
8155INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
8156            const struct __sanitizer_regmatch *rm, const char *sstr) {
8157  void *ctx;
8158  COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
8159  if (sub)
8160    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
8161  // Hardcode 10 elements as this is hardcoded size
8162  if (rm)
8163    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
8164  if (sstr)
8165    COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, internal_strlen(sstr) + 1);
8166  SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
8167  if (res > 0 && buf) {
8168    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
8169    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, internal_strlen(*buf) + 1);
8170  }
8171  return res;
8172}
8173
8174#define INIT_REGEXSUB                                                          \
8175  COMMON_INTERCEPT_FUNCTION(regnsub);                                          \
8176  COMMON_INTERCEPT_FUNCTION(regasub);
8177#else
8178#define INIT_REGEXSUB
8179#endif
8180
8181#if SANITIZER_INTERCEPT_FTS
8182INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
8183            int (*compar)(void **, void **)) {
8184  void *ctx;
8185  COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar);
8186  if (path_argv) {
8187    for (char *const *pa = path_argv; ; ++pa) {
8188      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
8189      if (!*pa)
8190        break;
8191      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
8192    }
8193  }
8194  // TODO(kamil): handle compar callback
8195  void *fts = REAL(fts_open)(path_argv, options, compar);
8196  if (fts)
8197    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz);
8198  return fts;
8199}
8200
8201INTERCEPTOR(void *, fts_read, void *ftsp) {
8202  void *ctx;
8203  COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp);
8204  if (ftsp)
8205    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
8206  void *ftsent = REAL(fts_read)(ftsp);
8207  if (ftsent)
8208    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
8209  return ftsent;
8210}
8211
8212INTERCEPTOR(void *, fts_children, void *ftsp, int options) {
8213  void *ctx;
8214  COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options);
8215  if (ftsp)
8216    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
8217  void *ftsent = REAL(fts_children)(ftsp, options);
8218  if (ftsent)
8219    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
8220  return ftsent;
8221}
8222
8223INTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) {
8224  void *ctx;
8225  COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options);
8226  if (ftsp)
8227    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
8228  if (f)
8229    COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz);
8230  return REAL(fts_set)(ftsp, f, options);
8231}
8232
8233INTERCEPTOR(int, fts_close, void *ftsp) {
8234  void *ctx;
8235  COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp);
8236  if (ftsp)
8237    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
8238  return REAL(fts_close)(ftsp);
8239}
8240#define INIT_FTS                                                               \
8241  COMMON_INTERCEPT_FUNCTION(fts_open);                                         \
8242  COMMON_INTERCEPT_FUNCTION(fts_read);                                         \
8243  COMMON_INTERCEPT_FUNCTION(fts_children);                                     \
8244  COMMON_INTERCEPT_FUNCTION(fts_set);                                          \
8245  COMMON_INTERCEPT_FUNCTION(fts_close);
8246#else
8247#define INIT_FTS
8248#endif
8249
8250#if SANITIZER_INTERCEPT_SYSCTL
8251INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
8252            SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
8253  void *ctx;
8254  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
8255    return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
8256  COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
8257                           newlen);
8258  if (name)
8259    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
8260  if (oldlenp)
8261    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
8262  if (newp && newlen)
8263    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
8264  int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
8265  if (!res) {
8266    if (oldlenp) {
8267      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
8268      if (oldp)
8269        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
8270    }
8271  }
8272  return res;
8273}
8274
8275INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
8276            void *newp, SIZE_T newlen) {
8277  void *ctx;
8278  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
8279    return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen);
8280  COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
8281                           newlen);
8282  if (sname)
8283    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
8284  if (oldlenp)
8285    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
8286  if (newp && newlen)
8287    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
8288  int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
8289  if (!res) {
8290    if (oldlenp) {
8291      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
8292      if (oldp)
8293        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
8294    }
8295  }
8296  return res;
8297}
8298
8299INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
8300            SIZE_T *namelenp) {
8301  void *ctx;
8302  COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
8303  if (sname)
8304    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
8305  if (namelenp)
8306    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
8307  int res = REAL(sysctlnametomib)(sname, name, namelenp);
8308  if (!res) {
8309    if (namelenp) {
8310      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
8311      if (name)
8312        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
8313    }
8314  }
8315  return res;
8316}
8317
8318#define INIT_SYSCTL                        \
8319  COMMON_INTERCEPT_FUNCTION(sysctl);       \
8320  COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
8321  COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
8322#else
8323#define INIT_SYSCTL
8324#endif
8325
8326#if SANITIZER_INTERCEPT_ASYSCTL
8327INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
8328  void *ctx;
8329  COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
8330  if (name)
8331    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
8332  void *res = REAL(asysctl)(name, namelen, len);
8333  if (res && len) {
8334    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
8335    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
8336  }
8337  return res;
8338}
8339
8340INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
8341  void *ctx;
8342  COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
8343  if (sname)
8344    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
8345  void *res = REAL(asysctlbyname)(sname, len);
8346  if (res && len) {
8347    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
8348    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
8349  }
8350  return res;
8351}
8352#define INIT_ASYSCTL                           \
8353  COMMON_INTERCEPT_FUNCTION(asysctl);          \
8354  COMMON_INTERCEPT_FUNCTION(asysctlbyname);
8355#else
8356#define INIT_ASYSCTL
8357#endif
8358
8359#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
8360INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
8361            unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
8362            int v) {
8363  void *ctx;
8364  COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
8365                           csz, rnode, v);
8366  if (sname)
8367    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
8368  if (namelenp)
8369    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
8370  if (csz)
8371    COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
8372  // Skip rnode, it's rarely used and not trivial to sanitize
8373  // It's also used mostly internally
8374  int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
8375  if (!res) {
8376    if (namelenp) {
8377      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
8378      if (name)
8379        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
8380    }
8381    if (csz) {
8382      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
8383      if (cname)
8384        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
8385    }
8386  }
8387  return res;
8388}
8389#define INIT_SYSCTLGETMIBINFO                  \
8390  COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
8391#else
8392#define INIT_SYSCTLGETMIBINFO
8393#endif
8394
8395#if SANITIZER_INTERCEPT_NL_LANGINFO
8396INTERCEPTOR(char *, nl_langinfo, long item) {
8397  void *ctx;
8398  COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
8399  char *ret = REAL(nl_langinfo)(item);
8400  if (ret)
8401    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
8402  return ret;
8403}
8404#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
8405#else
8406#define INIT_NL_LANGINFO
8407#endif
8408
8409#if SANITIZER_INTERCEPT_MODCTL
8410INTERCEPTOR(int, modctl, int operation, void *argp) {
8411  void *ctx;
8412  int ret;
8413  COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp);
8414
8415  if (operation == modctl_load) {
8416    if (argp) {
8417      __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp;
8418      COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
8419      if (ml->ml_filename)
8420        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
8421                                      internal_strlen(ml->ml_filename) + 1);
8422      if (ml->ml_props)
8423        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
8424    }
8425    ret = REAL(modctl)(operation, argp);
8426  } else if (operation == modctl_unload) {
8427    if (argp) {
8428      const char *name = (const char *)argp;
8429      COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
8430    }
8431    ret = REAL(modctl)(operation, argp);
8432  } else if (operation == modctl_stat) {
8433    uptr iov_len;
8434    struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp;
8435    if (iov) {
8436      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov));
8437      iov_len = iov->iov_len;
8438    }
8439    ret = REAL(modctl)(operation, argp);
8440    if (iov)
8441      COMMON_INTERCEPTOR_WRITE_RANGE(
8442          ctx, iov->iov_base, Min(iov_len,  iov->iov_len));
8443  } else if (operation == modctl_exists) {
8444    ret = REAL(modctl)(operation, argp);
8445  } else {
8446    ret = REAL(modctl)(operation, argp);
8447  }
8448
8449  return ret;
8450}
8451#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl)
8452#else
8453#define INIT_MODCTL
8454#endif
8455
8456#if SANITIZER_INTERCEPT_STRTONUM
8457INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
8458            long long maxval, const char **errstr) {
8459  void *ctx;
8460  COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);
8461
8462  // TODO(kamil): Implement strtoll as a common inteceptor
8463  char *real_endptr;
8464  long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
8465  StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);
8466
8467  ret = REAL(strtonum)(nptr, minval, maxval, errstr);
8468  if (errstr) {
8469    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
8470     if (*errstr)
8471      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, internal_strlen(*errstr) + 1);
8472  }
8473  return ret;
8474}
8475#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
8476#else
8477#define INIT_STRTONUM
8478#endif
8479
8480#if SANITIZER_INTERCEPT_FPARSELN
8481INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
8482            SIZE_T *lineno, const char delim[3], int flags) {
8483  void *ctx;
8484  COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags);
8485  if (lineno)
8486    COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno));
8487  if (delim)
8488    COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
8489  char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
8490  if (ret) {
8491    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
8492    if (len)
8493      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
8494    if (lineno)
8495      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno));
8496  }
8497  return ret;
8498}
8499#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln)
8500#else
8501#define INIT_FPARSELN
8502#endif
8503
8504#if SANITIZER_INTERCEPT_STATVFS1
8505INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
8506  void *ctx;
8507  COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
8508  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
8509  int res = REAL(statvfs1)(path, buf, flags);
8510  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
8511  return res;
8512}
8513INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
8514  void *ctx;
8515  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
8516  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
8517  int res = REAL(fstatvfs1)(fd, buf, flags);
8518  if (!res) {
8519    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
8520    if (fd >= 0)
8521      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
8522  }
8523  return res;
8524}
8525#define INIT_STATVFS1                  \
8526  COMMON_INTERCEPT_FUNCTION(statvfs1);  \
8527  COMMON_INTERCEPT_FUNCTION(fstatvfs1);
8528#else
8529#define INIT_STATVFS1
8530#endif
8531
8532#if SANITIZER_INTERCEPT_STRTOI
8533INTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base,
8534            INTMAX_T low, INTMAX_T high, int *rstatus) {
8535  void *ctx;
8536  COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus);
8537  char *real_endptr;
8538  INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus);
8539  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
8540  if (rstatus)
8541    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
8542  return ret;
8543}
8544
8545INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base,
8546            UINTMAX_T low, UINTMAX_T high, int *rstatus) {
8547  void *ctx;
8548  COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus);
8549  char *real_endptr;
8550  UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus);
8551  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
8552  if (rstatus)
8553    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
8554  return ret;
8555}
8556#define INIT_STRTOI                                                            \
8557  COMMON_INTERCEPT_FUNCTION(strtoi);                                           \
8558  COMMON_INTERCEPT_FUNCTION(strtou)
8559#else
8560#define INIT_STRTOI
8561#endif
8562
8563#if SANITIZER_INTERCEPT_CAPSICUM
8564#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...)          \
8565  {                                                                        \
8566    void *ctx;                                                             \
8567    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \
8568    if (rights)                                                            \
8569      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));         \
8570    __sanitizer_cap_rights_t *ret =                                        \
8571        REAL(cap_rights_init)(rights, ##__VA_ARGS__);                      \
8572    if (ret)                                                               \
8573      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));              \
8574    return ret;                                                            \
8575  }
8576
8577#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...)           \
8578  {                                                                       \
8579    void *ctx;                                                            \
8580    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \
8581    if (rights)                                                           \
8582      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));        \
8583    __sanitizer_cap_rights_t *ret =                                       \
8584        REAL(cap_rights_set)(rights, ##__VA_ARGS__);                      \
8585    if (ret)                                                              \
8586      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));             \
8587    return ret;                                                           \
8588  }
8589
8590#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...)         \
8591  {                                                                         \
8592    void *ctx;                                                              \
8593    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \
8594    if (rights)                                                             \
8595      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));          \
8596    __sanitizer_cap_rights_t *ret =                                         \
8597        REAL(cap_rights_clear)(rights, ##__VA_ARGS__);                      \
8598    if (ret)                                                                \
8599      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));               \
8600    return ret;                                                             \
8601  }
8602
8603#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...)        \
8604  {                                                                          \
8605    void *ctx;                                                               \
8606    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \
8607    if (rights)                                                              \
8608      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));           \
8609    return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__);                   \
8610  }
8611
8612INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init,
8613            __sanitizer_cap_rights_t *rights) {
8614  CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights);
8615}
8616
8617INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set,
8618            __sanitizer_cap_rights_t *rights) {
8619  CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights);
8620}
8621
8622INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear,
8623            __sanitizer_cap_rights_t *rights) {
8624  CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights);
8625}
8626
8627INTERCEPTOR(bool, cap_rights_is_set,
8628            __sanitizer_cap_rights_t *rights) {
8629  CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights);
8630}
8631
8632INTERCEPTOR(int, cap_rights_limit, int fd,
8633            const __sanitizer_cap_rights_t *rights) {
8634  void *ctx;
8635  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights);
8636  if (rights)
8637    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));
8638
8639  return REAL(cap_rights_limit)(fd, rights);
8640}
8641
8642INTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) {
8643  void *ctx;
8644  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights);
8645  int ret = REAL(cap_rights_get)(fd, rights);
8646  if (!ret && rights)
8647    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights));
8648
8649  return ret;
8650}
8651
8652INTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) {
8653  void *ctx;
8654  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights);
8655  if (rights)
8656    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));
8657
8658  return REAL(cap_rights_is_valid(rights));
8659}
8660
8661INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge,
8662  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
8663  void *ctx;
8664  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src);
8665  if (src)
8666    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
8667
8668  __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src);
8669  if (dst)
8670    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
8671
8672  return ret;
8673}
8674
8675INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove,
8676  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
8677  void *ctx;
8678  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src);
8679  if (src)
8680    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
8681
8682  __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src);
8683  if (dst)
8684    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
8685
8686  return ret;
8687}
8688
8689INTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big,
8690  const __sanitizer_cap_rights *little) {
8691  void *ctx;
8692  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little);
8693  if (little)
8694    COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little));
8695  if (big)
8696    COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big));
8697
8698  return REAL(cap_rights_contains)(big, little);
8699}
8700
8701INTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) {
8702  void *ctx;
8703  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds);
8704  if (cmds)
8705    COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds);
8706
8707  return REAL(cap_ioctls_limit)(fd, cmds, ncmds);
8708}
8709
8710INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) {
8711  void *ctx;
8712  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds);
8713  int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds);
8714  if (!ret && cmds)
8715    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds);
8716
8717  return ret;
8718}
8719#define INIT_CAPSICUM                          \
8720  COMMON_INTERCEPT_FUNCTION(cap_rights_init); \
8721  COMMON_INTERCEPT_FUNCTION(cap_rights_set); \
8722  COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \
8723  COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \
8724  COMMON_INTERCEPT_FUNCTION(cap_rights_get);   \
8725  COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \
8726  COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \
8727  COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \
8728  COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \
8729  COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \
8730  COMMON_INTERCEPT_FUNCTION(cap_ioctls_get);   \
8731  COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit)
8732#else
8733#define INIT_CAPSICUM
8734#endif
8735
8736#if SANITIZER_INTERCEPT_SHA1
8737INTERCEPTOR(void, SHA1Init, void *context) {
8738  void *ctx;
8739  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context);
8740  REAL(SHA1Init)(context);
8741  if (context)
8742    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
8743}
8744INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) {
8745  void *ctx;
8746  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len);
8747  if (data && len > 0)
8748    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8749  if (context)
8750    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
8751  REAL(SHA1Update)(context, data, len);
8752  if (context)
8753    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
8754}
8755INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) {
8756  void *ctx;
8757  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context);
8758  if (context)
8759    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
8760  REAL(SHA1Final)(digest, context);
8761  if (digest)
8762    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
8763}
8764INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) {
8765  void *ctx;
8766  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer);
8767  if (state)
8768    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
8769  if (buffer)
8770    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64);
8771  REAL(SHA1Transform)(state, buffer);
8772  if (state)
8773    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
8774}
8775INTERCEPTOR(char *, SHA1End, void *context, char *buf) {
8776  void *ctx;
8777  COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf);
8778  if (context)
8779    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
8780  char *ret = REAL(SHA1End)(context, buf);
8781  if (ret)
8782    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8783  return ret;
8784}
8785INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
8786  void *ctx;
8787  COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
8788  if (filename)
8789    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
8790  char *ret = REAL(SHA1File)(filename, buf);
8791  if (ret)
8792    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8793  return ret;
8794}
8795INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
8796  OFF_T length) {
8797  void *ctx;
8798  COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
8799  if (filename)
8800    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
8801  char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
8802  if (ret)
8803    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8804  return ret;
8805}
8806INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) {
8807  void *ctx;
8808  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf);
8809  if (data)
8810    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8811  char *ret = REAL(SHA1Data)(data, len, buf);
8812  if (ret)
8813    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8814  return ret;
8815}
8816#define INIT_SHA1                                                              \
8817  COMMON_INTERCEPT_FUNCTION(SHA1Init);                                         \
8818  COMMON_INTERCEPT_FUNCTION(SHA1Update);                                       \
8819  COMMON_INTERCEPT_FUNCTION(SHA1Final);                                        \
8820  COMMON_INTERCEPT_FUNCTION(SHA1Transform);                                    \
8821  COMMON_INTERCEPT_FUNCTION(SHA1End);                                          \
8822  COMMON_INTERCEPT_FUNCTION(SHA1File);                                         \
8823  COMMON_INTERCEPT_FUNCTION(SHA1FileChunk);                                    \
8824  COMMON_INTERCEPT_FUNCTION(SHA1Data)
8825#else
8826#define INIT_SHA1
8827#endif
8828
8829#if SANITIZER_INTERCEPT_MD4
8830INTERCEPTOR(void, MD4Init, void *context) {
8831  void *ctx;
8832  COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context);
8833  REAL(MD4Init)(context);
8834  if (context)
8835    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
8836}
8837
8838INTERCEPTOR(void, MD4Update, void *context, const unsigned char *data,
8839            unsigned int len) {
8840  void *ctx;
8841  COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len);
8842  if (data && len > 0)
8843    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8844  if (context)
8845    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
8846  REAL(MD4Update)(context, data, len);
8847  if (context)
8848    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
8849}
8850
8851INTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) {
8852  void *ctx;
8853  COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context);
8854  if (context)
8855    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
8856  REAL(MD4Final)(digest, context);
8857  if (digest)
8858    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
8859}
8860
8861INTERCEPTOR(char *, MD4End, void *context, char *buf) {
8862  void *ctx;
8863  COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf);
8864  if (context)
8865    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
8866  char *ret = REAL(MD4End)(context, buf);
8867  if (ret)
8868    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
8869  return ret;
8870}
8871
8872INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
8873  void *ctx;
8874  COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
8875  if (filename)
8876    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
8877  char *ret = REAL(MD4File)(filename, buf);
8878  if (ret)
8879    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
8880  return ret;
8881}
8882
8883INTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len,
8884            char *buf) {
8885  void *ctx;
8886  COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf);
8887  if (data && len > 0)
8888    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8889  char *ret = REAL(MD4Data)(data, len, buf);
8890  if (ret)
8891    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
8892  return ret;
8893}
8894
8895#define INIT_MD4                                                               \
8896  COMMON_INTERCEPT_FUNCTION(MD4Init);                                          \
8897  COMMON_INTERCEPT_FUNCTION(MD4Update);                                        \
8898  COMMON_INTERCEPT_FUNCTION(MD4Final);                                         \
8899  COMMON_INTERCEPT_FUNCTION(MD4End);                                           \
8900  COMMON_INTERCEPT_FUNCTION(MD4File);                                          \
8901  COMMON_INTERCEPT_FUNCTION(MD4Data)
8902#else
8903#define INIT_MD4
8904#endif
8905
8906#if SANITIZER_INTERCEPT_RMD160
8907INTERCEPTOR(void, RMD160Init, void *context) {
8908  void *ctx;
8909  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context);
8910  REAL(RMD160Init)(context);
8911  if (context)
8912    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
8913}
8914INTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) {
8915  void *ctx;
8916  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len);
8917  if (data && len > 0)
8918    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8919  if (context)
8920    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
8921  REAL(RMD160Update)(context, data, len);
8922  if (context)
8923    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
8924}
8925INTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) {
8926  void *ctx;
8927  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context);
8928  if (context)
8929    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
8930  REAL(RMD160Final)(digest, context);
8931  if (digest)
8932    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
8933}
8934INTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) {
8935  void *ctx;
8936  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer);
8937  if (state)
8938    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
8939  if (buffer)
8940    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16);
8941  REAL(RMD160Transform)(state, buffer);
8942  if (state)
8943    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
8944}
8945INTERCEPTOR(char *, RMD160End, void *context, char *buf) {
8946  void *ctx;
8947  COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf);
8948  if (context)
8949    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
8950  char *ret = REAL(RMD160End)(context, buf);
8951  if (ret)
8952    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8953  return ret;
8954}
8955INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
8956  void *ctx;
8957  COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
8958  if (filename)
8959    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
8960  char *ret = REAL(RMD160File)(filename, buf);
8961  if (ret)
8962    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8963  return ret;
8964}
8965INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
8966  OFF_T length) {
8967  void *ctx;
8968  COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
8969  if (filename)
8970    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
8971  char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
8972  if (ret)
8973    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8974  return ret;
8975}
8976INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
8977  void *ctx;
8978  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf);
8979  if (data && len > 0)
8980    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8981  char *ret = REAL(RMD160Data)(data, len, buf);
8982  if (ret)
8983    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8984  return ret;
8985}
8986#define INIT_RMD160                                                            \
8987  COMMON_INTERCEPT_FUNCTION(RMD160Init);                                       \
8988  COMMON_INTERCEPT_FUNCTION(RMD160Update);                                     \
8989  COMMON_INTERCEPT_FUNCTION(RMD160Final);                                      \
8990  COMMON_INTERCEPT_FUNCTION(RMD160Transform);                                  \
8991  COMMON_INTERCEPT_FUNCTION(RMD160End);                                        \
8992  COMMON_INTERCEPT_FUNCTION(RMD160File);                                       \
8993  COMMON_INTERCEPT_FUNCTION(RMD160FileChunk);                                  \
8994  COMMON_INTERCEPT_FUNCTION(RMD160Data)
8995#else
8996#define INIT_RMD160
8997#endif
8998
8999#if SANITIZER_INTERCEPT_MD5
9000INTERCEPTOR(void, MD5Init, void *context) {
9001  void *ctx;
9002  COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
9003  REAL(MD5Init)(context);
9004  if (context)
9005    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
9006}
9007
9008INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
9009            unsigned int len) {
9010  void *ctx;
9011  COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
9012  if (data && len > 0)
9013    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
9014  if (context)
9015    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
9016  REAL(MD5Update)(context, data, len);
9017  if (context)
9018    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
9019}
9020
9021INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
9022  void *ctx;
9023  COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
9024  if (context)
9025    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
9026  REAL(MD5Final)(digest, context);
9027  if (digest)
9028    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
9029}
9030
9031INTERCEPTOR(char *, MD5End, void *context, char *buf) {
9032  void *ctx;
9033  COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
9034  if (context)
9035    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
9036  char *ret = REAL(MD5End)(context, buf);
9037  if (ret)
9038    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
9039  return ret;
9040}
9041
9042INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
9043  void *ctx;
9044  COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
9045  if (filename)
9046    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
9047  char *ret = REAL(MD5File)(filename, buf);
9048  if (ret)
9049    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
9050  return ret;
9051}
9052
9053INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
9054            char *buf) {
9055  void *ctx;
9056  COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
9057  if (data && len > 0)
9058    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
9059  char *ret = REAL(MD5Data)(data, len, buf);
9060  if (ret)
9061    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
9062  return ret;
9063}
9064
9065#define INIT_MD5                                                               \
9066  COMMON_INTERCEPT_FUNCTION(MD5Init);                                          \
9067  COMMON_INTERCEPT_FUNCTION(MD5Update);                                        \
9068  COMMON_INTERCEPT_FUNCTION(MD5Final);                                         \
9069  COMMON_INTERCEPT_FUNCTION(MD5End);                                           \
9070  COMMON_INTERCEPT_FUNCTION(MD5File);                                          \
9071  COMMON_INTERCEPT_FUNCTION(MD5Data)
9072#else
9073#define INIT_MD5
9074#endif
9075
9076#if SANITIZER_INTERCEPT_FSEEK
9077INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
9078  void *ctx;
9079  COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence);
9080  return REAL(fseek)(stream, offset, whence);
9081}
9082INTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) {
9083  void *ctx;
9084  COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence);
9085  return REAL(fseeko)(stream, offset, whence);
9086}
9087INTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) {
9088  void *ctx;
9089  COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream);
9090  return REAL(ftell)(stream);
9091}
9092INTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) {
9093  void *ctx;
9094  COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream);
9095  return REAL(ftello)(stream);
9096}
9097INTERCEPTOR(void, rewind, __sanitizer_FILE *stream) {
9098  void *ctx;
9099  COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream);
9100  return REAL(rewind)(stream);
9101}
9102INTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) {
9103  void *ctx;
9104  COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos);
9105  int ret = REAL(fgetpos)(stream, pos);
9106  if (pos && !ret)
9107    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz);
9108  return ret;
9109}
9110INTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) {
9111  void *ctx;
9112  COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos);
9113  if (pos)
9114    COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz);
9115  return REAL(fsetpos)(stream, pos);
9116}
9117#define INIT_FSEEK \
9118  COMMON_INTERCEPT_FUNCTION(fseek); \
9119  COMMON_INTERCEPT_FUNCTION(fseeko); \
9120  COMMON_INTERCEPT_FUNCTION(ftell); \
9121  COMMON_INTERCEPT_FUNCTION(ftello); \
9122  COMMON_INTERCEPT_FUNCTION(rewind); \
9123  COMMON_INTERCEPT_FUNCTION(fgetpos); \
9124  COMMON_INTERCEPT_FUNCTION(fsetpos)
9125#else
9126#define INIT_FSEEK
9127#endif
9128
9129#if SANITIZER_INTERCEPT_MD2
9130INTERCEPTOR(void, MD2Init, void *context) {
9131  void *ctx;
9132  COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context);
9133  REAL(MD2Init)(context);
9134  if (context)
9135    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
9136}
9137
9138INTERCEPTOR(void, MD2Update, void *context, const unsigned char *data,
9139            unsigned int len) {
9140  void *ctx;
9141  COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len);
9142  if (data && len > 0)
9143    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
9144  if (context)
9145    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
9146  REAL(MD2Update)(context, data, len);
9147  if (context)
9148    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
9149}
9150
9151INTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) {
9152  void *ctx;
9153  COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context);
9154  if (context)
9155    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
9156  REAL(MD2Final)(digest, context);
9157  if (digest)
9158    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
9159}
9160
9161INTERCEPTOR(char *, MD2End, void *context, char *buf) {
9162  void *ctx;
9163  COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf);
9164  if (context)
9165    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
9166  char *ret = REAL(MD2End)(context, buf);
9167  if (ret)
9168    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
9169  return ret;
9170}
9171
9172INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
9173  void *ctx;
9174  COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
9175  if (filename)
9176    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
9177  char *ret = REAL(MD2File)(filename, buf);
9178  if (ret)
9179    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
9180  return ret;
9181}
9182
9183INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
9184            char *buf) {
9185  void *ctx;
9186  COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf);
9187  if (data && len > 0)
9188    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
9189  char *ret = REAL(MD2Data)(data, len, buf);
9190  if (ret)
9191    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
9192  return ret;
9193}
9194
9195#define INIT_MD2                                                               \
9196  COMMON_INTERCEPT_FUNCTION(MD2Init);                                          \
9197  COMMON_INTERCEPT_FUNCTION(MD2Update);                                        \
9198  COMMON_INTERCEPT_FUNCTION(MD2Final);                                         \
9199  COMMON_INTERCEPT_FUNCTION(MD2End);                                           \
9200  COMMON_INTERCEPT_FUNCTION(MD2File);                                          \
9201  COMMON_INTERCEPT_FUNCTION(MD2Data)
9202#else
9203#define INIT_MD2
9204#endif
9205
9206#if SANITIZER_INTERCEPT_SHA2
9207#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
9208  INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
9209    void *ctx; \
9210    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
9211    REAL(SHA##LEN##_Init)(context); \
9212    if (context) \
9213      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9214  } \
9215  INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
9216              const u8 *data, SIZE_T len) { \
9217    void *ctx; \
9218    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
9219    if (data && len > 0) \
9220      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
9221    if (context) \
9222      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9223    REAL(SHA##LEN##_Update)(context, data, len); \
9224    if (context) \
9225      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9226  } \
9227  INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
9228  void *context) { \
9229    void *ctx; \
9230    CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
9231    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
9232    if (context) \
9233      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9234    REAL(SHA##LEN##_Final)(digest, context); \
9235    if (digest) \
9236      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
9237                                     sizeof(digest[0]) * \
9238  SHA##LEN##_digest_length); \
9239  } \
9240  INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
9241    void *ctx; \
9242    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
9243    if (context) \
9244      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9245    char *ret = REAL(SHA##LEN##_End)(context, buf); \
9246    if (ret) \
9247      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9248    return ret; \
9249  } \
9250  INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
9251    void *ctx; \
9252    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
9253    if (filename) \
9254      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
9255    char *ret = REAL(SHA##LEN##_File)(filename, buf); \
9256    if (ret) \
9257      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9258    return ret; \
9259  } \
9260  INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
9261              OFF_T offset, OFF_T length) { \
9262    void *ctx; \
9263    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
9264  length); \
9265    if (filename) \
9266      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
9267    char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
9268    if (ret) \
9269      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9270    return ret; \
9271  } \
9272  INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
9273    void *ctx; \
9274    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
9275    if (data && len > 0) \
9276      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
9277    char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
9278    if (ret) \
9279      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9280    return ret; \
9281  }
9282
9283SHA2_INTERCEPTORS(224, u32)
9284SHA2_INTERCEPTORS(256, u32)
9285SHA2_INTERCEPTORS(384, u64)
9286SHA2_INTERCEPTORS(512, u64)
9287
9288#define INIT_SHA2_INTECEPTORS(LEN) \
9289  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
9290  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
9291  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
9292  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
9293  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
9294  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
9295  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)
9296
9297#define INIT_SHA2 \
9298  INIT_SHA2_INTECEPTORS(224); \
9299  INIT_SHA2_INTECEPTORS(256); \
9300  INIT_SHA2_INTECEPTORS(384); \
9301  INIT_SHA2_INTECEPTORS(512)
9302#undef SHA2_INTERCEPTORS
9303#else
9304#define INIT_SHA2
9305#endif
9306
9307#if SANITIZER_INTERCEPT_VIS
9308INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
9309  void *ctx;
9310  COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
9311  char *end = REAL(vis)(dst, c, flag, nextc);
9312  // dst is NULL terminated and end points to the NULL char
9313  if (dst && end)
9314    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
9315  return end;
9316}
9317INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
9318  void *ctx;
9319  COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
9320  char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
9321  // nvis cannot make sure the dst is NULL terminated
9322  if (dst && end)
9323    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
9324  return end;
9325}
9326INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
9327  void *ctx;
9328  COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
9329  if (src)
9330    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9331  int len = REAL(strvis)(dst, src, flag);
9332  if (dst)
9333    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
9334  return len;
9335}
9336INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
9337  void *ctx;
9338  COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
9339  if (src)
9340    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9341  int len = REAL(stravis)(dst, src, flag);
9342  if (dst) {
9343    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
9344    if (*dst)
9345      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
9346  }
9347  return len;
9348}
9349INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
9350  void *ctx;
9351  COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
9352  if (src)
9353    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9354  int len = REAL(strnvis)(dst, dlen, src, flag);
9355  // The interface will be valid even if there is no space for NULL char
9356  if (dst && len > 0)
9357    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
9358  return len;
9359}
9360INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
9361  void *ctx;
9362  COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
9363  if (src)
9364    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
9365  int ret = REAL(strvisx)(dst, src, len, flag);
9366  if (dst)
9367    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9368  return ret;
9369}
9370INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
9371            int flag) {
9372  void *ctx;
9373  COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
9374  if (src)
9375    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
9376  int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
9377  if (dst && ret >= 0)
9378    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9379  return ret;
9380}
9381INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
9382            int flag, int *cerr_ptr) {
9383  void *ctx;
9384  COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
9385  if (src)
9386    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
9387  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
9388  // according to the implementation
9389  if (cerr_ptr)
9390    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
9391  int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
9392  if (dst && ret >= 0)
9393    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9394  if (cerr_ptr)
9395    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
9396  return ret;
9397}
9398INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
9399            const char *extra) {
9400  void *ctx;
9401  COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
9402  if (extra)
9403    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9404  char *end = REAL(svis)(dst, c, flag, nextc, extra);
9405  if (dst && end)
9406    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
9407  return end;
9408}
9409INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
9410            const char *extra) {
9411  void *ctx;
9412  COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
9413  if (extra)
9414    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9415  char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
9416  if (dst && end)
9417    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
9418                                   Min((SIZE_T)(end - dst + 1), dlen));
9419  return end;
9420}
9421INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
9422            const char *extra) {
9423  void *ctx;
9424  COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
9425  if (src)
9426    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9427  if (extra)
9428    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9429  int len = REAL(strsvis)(dst, src, flag, extra);
9430  if (dst)
9431    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
9432  return len;
9433}
9434INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
9435            const char *extra) {
9436  void *ctx;
9437  COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
9438  if (src)
9439    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9440  if (extra)
9441    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9442  int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
9443  // The interface will be valid even if there is no space for NULL char
9444  if (dst && len >= 0)
9445    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
9446  return len;
9447}
9448INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
9449            const char *extra) {
9450  void *ctx;
9451  COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
9452  if (src)
9453    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
9454  if (extra)
9455    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9456  int ret = REAL(strsvisx)(dst, src, len, flag, extra);
9457  if (dst)
9458    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9459  return ret;
9460}
9461INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
9462            int flag, const char *extra) {
9463  void *ctx;
9464  COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
9465  if (src)
9466    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
9467  if (extra)
9468    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9469  int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
9470  if (dst && ret >= 0)
9471    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9472  return ret;
9473}
9474INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
9475            SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
9476  void *ctx;
9477  COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
9478                           cerr_ptr);
9479  if (src)
9480    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
9481  if (extra)
9482    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
9483  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
9484  // according to the implementation
9485  if (cerr_ptr)
9486    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
9487  int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
9488  if (dst && ret >= 0)
9489    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9490  if (cerr_ptr)
9491    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
9492  return ret;
9493}
9494INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
9495  void *ctx;
9496  COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
9497  if (astate)
9498    COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
9499  int ret = REAL(unvis)(cp, c, astate, flag);
9500  if (ret == unvis_valid || ret == unvis_validpush) {
9501    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
9502  }
9503  return ret;
9504}
9505INTERCEPTOR(int, strunvis, char *dst, const char *src) {
9506  void *ctx;
9507  COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
9508  if (src)
9509    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9510  int ret = REAL(strunvis)(dst, src);
9511  if (ret != -1)
9512    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9513  return ret;
9514}
9515INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
9516  void *ctx;
9517  COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
9518  if (src)
9519    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9520  int ret = REAL(strnunvis)(dst, dlen, src);
9521  if (ret != -1)
9522    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9523  return ret;
9524}
9525INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
9526  void *ctx;
9527  COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
9528  if (src)
9529    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9530  int ret = REAL(strunvisx)(dst, src, flag);
9531  if (ret != -1)
9532    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9533  return ret;
9534}
9535INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
9536            int flag) {
9537  void *ctx;
9538  COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
9539  if (src)
9540    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
9541  int ret = REAL(strnunvisx)(dst, dlen, src, flag);
9542  if (ret != -1)
9543    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9544  return ret;
9545}
9546#define INIT_VIS                                                               \
9547  COMMON_INTERCEPT_FUNCTION(vis);                                              \
9548  COMMON_INTERCEPT_FUNCTION(nvis);                                             \
9549  COMMON_INTERCEPT_FUNCTION(strvis);                                           \
9550  COMMON_INTERCEPT_FUNCTION(stravis);                                          \
9551  COMMON_INTERCEPT_FUNCTION(strnvis);                                          \
9552  COMMON_INTERCEPT_FUNCTION(strvisx);                                          \
9553  COMMON_INTERCEPT_FUNCTION(strnvisx);                                         \
9554  COMMON_INTERCEPT_FUNCTION(strenvisx);                                        \
9555  COMMON_INTERCEPT_FUNCTION(svis);                                             \
9556  COMMON_INTERCEPT_FUNCTION(snvis);                                            \
9557  COMMON_INTERCEPT_FUNCTION(strsvis);                                          \
9558  COMMON_INTERCEPT_FUNCTION(strsnvis);                                         \
9559  COMMON_INTERCEPT_FUNCTION(strsvisx);                                         \
9560  COMMON_INTERCEPT_FUNCTION(strsnvisx);                                        \
9561  COMMON_INTERCEPT_FUNCTION(strsenvisx);                                       \
9562  COMMON_INTERCEPT_FUNCTION(unvis);                                            \
9563  COMMON_INTERCEPT_FUNCTION(strunvis);                                         \
9564  COMMON_INTERCEPT_FUNCTION(strnunvis);                                        \
9565  COMMON_INTERCEPT_FUNCTION(strunvisx);                                        \
9566  COMMON_INTERCEPT_FUNCTION(strnunvisx)
9567#else
9568#define INIT_VIS
9569#endif
9570
9571#if SANITIZER_INTERCEPT_CDB
9572INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
9573  void *ctx;
9574  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
9575  if (path)
9576    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
9577  struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
9578  if (cdbr)
9579    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
9580  return cdbr;
9581}
9582
9583INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
9584  int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
9585  void *ctx;
9586  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
9587    cookie);
9588  if (base && size)
9589    COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
9590  struct __sanitizer_cdbr *cdbr =
9591    REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
9592  if (cdbr)
9593    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
9594  return cdbr;
9595}
9596
9597INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
9598  void *ctx;
9599  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
9600  if (cdbr)
9601    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9602  return REAL(cdbr_entries)(cdbr);
9603}
9604
9605INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
9606            const void **data, SIZE_T *datalen) {
9607  void *ctx;
9608  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
9609  if (cdbr)
9610    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9611  int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
9612  if (!ret) {
9613    if (data)
9614      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
9615    if (datalen)
9616      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
9617    if (data && datalen)
9618      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
9619  }
9620  return ret;
9621}
9622
9623INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
9624            SIZE_T keylen, const void **data, SIZE_T *datalen) {
9625  void *ctx;
9626  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
9627  if (cdbr)
9628    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9629  if (key)
9630    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
9631  int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
9632  if (!ret) {
9633    if (data)
9634      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
9635    if (datalen)
9636      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
9637    if (data && datalen)
9638      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
9639  }
9640  return ret;
9641}
9642
9643INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
9644  void *ctx;
9645  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
9646  if (cdbr)
9647    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9648  REAL(cdbr_close)(cdbr);
9649}
9650
9651INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
9652  void *ctx;
9653  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
9654  struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
9655  if (ret)
9656    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
9657  return ret;
9658}
9659
9660INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
9661  SIZE_T keylen, const void *data, SIZE_T datalen) {
9662  void *ctx;
9663  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
9664  if (cdbw)
9665    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9666  if (data && datalen)
9667    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
9668  if (key && keylen)
9669    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
9670  int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
9671  if (!ret && cdbw)
9672    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9673  return ret;
9674}
9675
9676INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
9677  SIZE_T datalen, u32 *index) {
9678  void *ctx;
9679  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
9680  if (cdbw)
9681    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9682  if (data && datalen)
9683    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
9684  int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
9685  if (!ret) {
9686    if (index)
9687      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
9688    if (cdbw)
9689      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9690  }
9691  return ret;
9692}
9693
9694INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
9695  SIZE_T keylen, u32 index) {
9696  void *ctx;
9697  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
9698  if (cdbw)
9699    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9700  if (key && keylen)
9701    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
9702  int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
9703  if (!ret && cdbw)
9704    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9705  return ret;
9706}
9707
9708INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
9709  const char descr[16], u32 (*seedgen)(void)) {
9710  void *ctx;
9711  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
9712  COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
9713  if (cdbw)
9714    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9715  if (descr)
9716    COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
9717  if (seedgen)
9718    COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
9719  int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
9720  if (!ret) {
9721    if (cdbw)
9722      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9723    if (output >= 0)
9724      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
9725  }
9726  return ret;
9727}
9728
9729INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
9730  void *ctx;
9731  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
9732  if (cdbw)
9733    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9734  REAL(cdbw_close)(cdbw);
9735}
9736
9737#define INIT_CDB \
9738  COMMON_INTERCEPT_FUNCTION(cdbr_open); \
9739  COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
9740  COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
9741  COMMON_INTERCEPT_FUNCTION(cdbr_get); \
9742  COMMON_INTERCEPT_FUNCTION(cdbr_find); \
9743  COMMON_INTERCEPT_FUNCTION(cdbr_close); \
9744  COMMON_INTERCEPT_FUNCTION(cdbw_open); \
9745  COMMON_INTERCEPT_FUNCTION(cdbw_put); \
9746  COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
9747  COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
9748  COMMON_INTERCEPT_FUNCTION(cdbw_output); \
9749  COMMON_INTERCEPT_FUNCTION(cdbw_close)
9750#else
9751#define INIT_CDB
9752#endif
9753
9754#if SANITIZER_INTERCEPT_GETFSENT
9755INTERCEPTOR(void *, getfsent) {
9756  void *ctx;
9757  COMMON_INTERCEPTOR_ENTER(ctx, getfsent);
9758  void *ret = REAL(getfsent)();
9759  if (ret)
9760    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
9761  return ret;
9762}
9763
9764INTERCEPTOR(void *, getfsspec, const char *spec) {
9765  void *ctx;
9766  COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
9767  if (spec)
9768    COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, internal_strlen(spec) + 1);
9769  void *ret = REAL(getfsspec)(spec);
9770  if (ret)
9771    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
9772  return ret;
9773}
9774
9775INTERCEPTOR(void *, getfsfile, const char *file) {
9776  void *ctx;
9777  COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
9778  if (file)
9779    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
9780  void *ret = REAL(getfsfile)(file);
9781  if (ret)
9782    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
9783  return ret;
9784}
9785
9786#define INIT_GETFSENT \
9787  COMMON_INTERCEPT_FUNCTION(getfsent); \
9788  COMMON_INTERCEPT_FUNCTION(getfsspec); \
9789  COMMON_INTERCEPT_FUNCTION(getfsfile);
9790#else
9791#define INIT_GETFSENT
9792#endif
9793
9794#if SANITIZER_INTERCEPT_ARC4RANDOM
9795INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) {
9796  void *ctx;
9797  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len);
9798  REAL(arc4random_buf)(buf, len);
9799  if (buf && len)
9800    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len);
9801}
9802
9803INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
9804  void *ctx;
9805  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen);
9806  if (dat && datlen)
9807    COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen);
9808  REAL(arc4random_addrandom)(dat, datlen);
9809}
9810
9811#define INIT_ARC4RANDOM \
9812  COMMON_INTERCEPT_FUNCTION(arc4random_buf); \
9813  COMMON_INTERCEPT_FUNCTION(arc4random_addrandom);
9814#else
9815#define INIT_ARC4RANDOM
9816#endif
9817
9818#if SANITIZER_INTERCEPT_POPEN
9819INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
9820  void *ctx;
9821  COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
9822  if (command)
9823    COMMON_INTERCEPTOR_READ_RANGE(ctx, command, internal_strlen(command) + 1);
9824  if (type)
9825    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
9826  __sanitizer_FILE *res = REAL(popen)(command, type);
9827  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
9828  if (res) unpoison_file(res);
9829  return res;
9830}
9831#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
9832#else
9833#define INIT_POPEN
9834#endif
9835
9836#if SANITIZER_INTERCEPT_POPENVE
9837INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
9838            char *const *argv, char *const *envp, const char *type) {
9839  void *ctx;
9840  COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
9841  if (path)
9842    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
9843  if (argv) {
9844    for (char *const *pa = argv; ; ++pa) {
9845      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
9846      if (!*pa)
9847        break;
9848      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
9849    }
9850  }
9851  if (envp) {
9852    for (char *const *pa = envp; ; ++pa) {
9853      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
9854      if (!*pa)
9855        break;
9856      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
9857    }
9858  }
9859  if (type)
9860    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
9861  __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
9862  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
9863  if (res) unpoison_file(res);
9864  return res;
9865}
9866#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
9867#else
9868#define INIT_POPENVE
9869#endif
9870
9871#if SANITIZER_INTERCEPT_PCLOSE
9872INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
9873  void *ctx;
9874  COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
9875  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
9876  const FileMetadata *m = GetInterceptorMetadata(fp);
9877  int res = REAL(pclose)(fp);
9878  if (m) {
9879    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
9880    DeleteInterceptorMetadata(fp);
9881  }
9882  return res;
9883}
9884#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
9885#else
9886#define INIT_PCLOSE
9887#endif
9888
9889#if SANITIZER_INTERCEPT_FUNOPEN
9890typedef int (*funopen_readfn)(void *cookie, char *buf, int len);
9891typedef int (*funopen_writefn)(void *cookie, const char *buf, int len);
9892typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence);
9893typedef int (*funopen_closefn)(void *cookie);
9894
9895struct WrappedFunopenCookie {
9896  void *real_cookie;
9897  funopen_readfn real_read;
9898  funopen_writefn real_write;
9899  funopen_seekfn real_seek;
9900  funopen_closefn real_close;
9901};
9902
9903static int wrapped_funopen_read(void *cookie, char *buf, int len) {
9904  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9905  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9906  funopen_readfn real_read = wrapped_cookie->real_read;
9907  return real_read(wrapped_cookie->real_cookie, buf, len);
9908}
9909
9910static int wrapped_funopen_write(void *cookie, const char *buf, int len) {
9911  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9912  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9913  funopen_writefn real_write = wrapped_cookie->real_write;
9914  return real_write(wrapped_cookie->real_cookie, buf, len);
9915}
9916
9917static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) {
9918  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9919  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9920  funopen_seekfn real_seek = wrapped_cookie->real_seek;
9921  return real_seek(wrapped_cookie->real_cookie, offset, whence);
9922}
9923
9924static int wrapped_funopen_close(void *cookie) {
9925  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
9926  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9927  funopen_closefn real_close = wrapped_cookie->real_close;
9928  int res = real_close(wrapped_cookie->real_cookie);
9929  InternalFree(wrapped_cookie);
9930  return res;
9931}
9932
9933INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn,
9934            funopen_writefn writefn, funopen_seekfn seekfn,
9935            funopen_closefn closefn) {
9936  void *ctx;
9937  COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn,
9938                           closefn);
9939
9940  WrappedFunopenCookie *wrapped_cookie =
9941      (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie));
9942  wrapped_cookie->real_cookie = cookie;
9943  wrapped_cookie->real_read = readfn;
9944  wrapped_cookie->real_write = writefn;
9945  wrapped_cookie->real_seek = seekfn;
9946  wrapped_cookie->real_close = closefn;
9947
9948  __sanitizer_FILE *res =
9949      REAL(funopen)(wrapped_cookie,
9950                    readfn  ? wrapped_funopen_read  : nullptr,
9951                    writefn ? wrapped_funopen_write : nullptr,
9952                    seekfn  ? wrapped_funopen_seek  : nullptr,
9953                    closefn ? wrapped_funopen_close : nullptr);
9954  if (res)
9955    unpoison_file(res);
9956  return res;
9957}
9958#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen)
9959#else
9960#define INIT_FUNOPEN
9961#endif
9962
9963#if SANITIZER_INTERCEPT_FUNOPEN2
9964typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len);
9965typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len);
9966typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence);
9967typedef int (*funopen2_flushfn)(void *cookie);
9968typedef int (*funopen2_closefn)(void *cookie);
9969
9970struct WrappedFunopen2Cookie {
9971  void *real_cookie;
9972  funopen2_readfn real_read;
9973  funopen2_writefn real_write;
9974  funopen2_seekfn real_seek;
9975  funopen2_flushfn real_flush;
9976  funopen2_closefn real_close;
9977};
9978
9979static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) {
9980  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9981  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9982  funopen2_readfn real_read = wrapped_cookie->real_read;
9983  return real_read(wrapped_cookie->real_cookie, buf, len);
9984}
9985
9986static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf,
9987                                      SIZE_T len) {
9988  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9989  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9990  funopen2_writefn real_write = wrapped_cookie->real_write;
9991  return real_write(wrapped_cookie->real_cookie, buf, len);
9992}
9993
9994static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) {
9995  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9996  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9997  funopen2_seekfn real_seek = wrapped_cookie->real_seek;
9998  return real_seek(wrapped_cookie->real_cookie, offset, whence);
9999}
10000
10001static int wrapped_funopen2_flush(void *cookie) {
10002  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
10003  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
10004  funopen2_flushfn real_flush = wrapped_cookie->real_flush;
10005  return real_flush(wrapped_cookie->real_cookie);
10006}
10007
10008static int wrapped_funopen2_close(void *cookie) {
10009  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
10010  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
10011  funopen2_closefn real_close = wrapped_cookie->real_close;
10012  int res = real_close(wrapped_cookie->real_cookie);
10013  InternalFree(wrapped_cookie);
10014  return res;
10015}
10016
10017INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn,
10018            funopen2_writefn writefn, funopen2_seekfn seekfn,
10019            funopen2_flushfn flushfn, funopen2_closefn closefn) {
10020  void *ctx;
10021  COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn,
10022                           flushfn, closefn);
10023
10024  WrappedFunopen2Cookie *wrapped_cookie =
10025      (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie));
10026  wrapped_cookie->real_cookie = cookie;
10027  wrapped_cookie->real_read = readfn;
10028  wrapped_cookie->real_write = writefn;
10029  wrapped_cookie->real_seek = seekfn;
10030  wrapped_cookie->real_flush = flushfn;
10031  wrapped_cookie->real_close = closefn;
10032
10033  __sanitizer_FILE *res =
10034      REAL(funopen2)(wrapped_cookie,
10035                     readfn  ? wrapped_funopen2_read  : nullptr,
10036                     writefn ? wrapped_funopen2_write : nullptr,
10037                     seekfn  ? wrapped_funopen2_seek  : nullptr,
10038                     flushfn ? wrapped_funopen2_flush : nullptr,
10039                     closefn ? wrapped_funopen2_close : nullptr);
10040  if (res)
10041    unpoison_file(res);
10042  return res;
10043}
10044#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2)
10045#else
10046#define INIT_FUNOPEN2
10047#endif
10048
10049#if SANITIZER_INTERCEPT_FDEVNAME
10050INTERCEPTOR(char *, fdevname,  int fd) {
10051  void *ctx;
10052  COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd);
10053  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
10054  char *name = REAL(fdevname)(fd);
10055  if (name) {
10056    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
10057    if (fd > 0)
10058      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10059  }
10060  return name;
10061}
10062
10063INTERCEPTOR(char *, fdevname_r,  int fd, char *buf, SIZE_T len) {
10064  void *ctx;
10065  COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len);
10066  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
10067  char *name = REAL(fdevname_r)(fd, buf, len);
10068  if (name && buf && len > 0) {
10069    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
10070    if (fd > 0)
10071      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10072  }
10073  return name;
10074}
10075
10076#define INIT_FDEVNAME \
10077  COMMON_INTERCEPT_FUNCTION(fdevname); \
10078  COMMON_INTERCEPT_FUNCTION(fdevname_r);
10079#else
10080#define INIT_FDEVNAME
10081#endif
10082
10083#if SANITIZER_INTERCEPT_GETUSERSHELL
10084INTERCEPTOR(char *, getusershell) {
10085  void *ctx;
10086  COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
10087  char *res = REAL(getusershell)();
10088  if (res)
10089    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
10090  return res;
10091}
10092
10093#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell);
10094#else
10095#define INIT_GETUSERSHELL
10096#endif
10097
10098#if SANITIZER_INTERCEPT_SL_INIT
10099INTERCEPTOR(void *, sl_init) {
10100  void *ctx;
10101  COMMON_INTERCEPTOR_ENTER(ctx, sl_init);
10102  void *res = REAL(sl_init)();
10103  if (res)
10104    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz);
10105  return res;
10106}
10107
10108INTERCEPTOR(int, sl_add, void *sl, char *item) {
10109  void *ctx;
10110  COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item);
10111  if (sl)
10112    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
10113  if (item)
10114    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
10115  int res = REAL(sl_add)(sl, item);
10116  if (!res)
10117    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
10118  return res;
10119}
10120
10121INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
10122  void *ctx;
10123  COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item);
10124  if (sl)
10125    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
10126  if (item)
10127    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
10128  char *res = REAL(sl_find)(sl, item);
10129  if (res)
10130    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
10131  return res;
10132}
10133
10134INTERCEPTOR(void, sl_free, void *sl, int freeall) {
10135  void *ctx;
10136  COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall);
10137  if (sl)
10138    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
10139  REAL(sl_free)(sl, freeall);
10140}
10141
10142#define INIT_SL_INIT                  \
10143  COMMON_INTERCEPT_FUNCTION(sl_init); \
10144  COMMON_INTERCEPT_FUNCTION(sl_add);  \
10145  COMMON_INTERCEPT_FUNCTION(sl_find); \
10146  COMMON_INTERCEPT_FUNCTION(sl_free);
10147#else
10148#define INIT_SL_INIT
10149#endif
10150
10151#if SANITIZER_INTERCEPT_GETRANDOM
10152INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
10153  void *ctx;
10154  COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
10155  SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
10156  if (n > 0) {
10157    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
10158  }
10159  return n;
10160}
10161#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom)
10162#else
10163#define INIT_GETRANDOM
10164#endif
10165
10166#if SANITIZER_INTERCEPT_CRYPT
10167INTERCEPTOR(char *, crypt, char *key, char *salt) {
10168  void *ctx;
10169  COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
10170  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
10171  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
10172  char *res = REAL(crypt)(key, salt);
10173  if (res != nullptr)
10174    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
10175  return res;
10176}
10177#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
10178#else
10179#define INIT_CRYPT
10180#endif
10181
10182#if SANITIZER_INTERCEPT_CRYPT_R
10183INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
10184  void *ctx;
10185  COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
10186  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
10187  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
10188  char *res = REAL(crypt_r)(key, salt, data);
10189  if (res != nullptr) {
10190    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
10191                                   __sanitizer::struct_crypt_data_sz);
10192    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
10193  }
10194  return res;
10195}
10196#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
10197#else
10198#define INIT_CRYPT_R
10199#endif
10200
10201#if SANITIZER_INTERCEPT_GETENTROPY
10202INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
10203  void *ctx;
10204  COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
10205  int r = REAL(getentropy)(buf, buflen);
10206  if (r == 0) {
10207    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
10208  }
10209  return r;
10210}
10211#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
10212#else
10213#define INIT_GETENTROPY
10214#endif
10215
10216#if SANITIZER_INTERCEPT_QSORT_R
10217typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
10218struct qsort_r_compar_params {
10219  SIZE_T size;
10220  qsort_r_compar_f compar;
10221  void *arg;
10222};
10223static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
10224  qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
10225  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
10226  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size);
10227  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size);
10228  return params->compar(a, b, params->arg);
10229}
10230
10231INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
10232            qsort_r_compar_f compar, void *arg) {
10233  void *ctx;
10234  COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
10235  // Run the comparator over all array elements to detect any memory issues.
10236  if (nmemb > 1) {
10237    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
10238      void *p = (void *)((char *)base + i * size);
10239      void *q = (void *)((char *)base + (i + 1) * size);
10240      COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
10241      compar(p, q, arg);
10242    }
10243  }
10244  qsort_r_compar_params params = {size, compar, arg};
10245  REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, &params);
10246  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
10247}
10248#  define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
10249#else
10250#  define INIT_QSORT_R
10251#endif
10252
10253#if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
10254INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
10255            qsort_r_compar_f compar) {
10256  void *ctx;
10257  COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
10258  WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
10259}
10260#  define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
10261#elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
10262// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
10263// Poisoned memory from there may get copied into the comparator arguments,
10264// where it needs to be dealt with. But even that is not enough - the results of
10265// the sort may be copied into the input/output array based on the results of
10266// the comparator calls, but directly from the temp memory, bypassing the
10267// unpoisoning done in wrapped_qsort_compar. We deal with this by, again,
10268// unpoisoning the entire array after the sort is done.
10269//
10270// We can not check that the entire array is initialized at the beginning. IMHO,
10271// it's fine for parts of the sorted objects to contain uninitialized memory,
10272// ex. as padding in structs.
10273typedef int (*qsort_compar_f)(const void *, const void *);
10274static THREADLOCAL qsort_compar_f qsort_compar;
10275static THREADLOCAL SIZE_T qsort_size;
10276static int wrapped_qsort_compar(const void *a, const void *b) {
10277  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
10278  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
10279  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
10280  return qsort_compar(a, b);
10281}
10282
10283INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
10284            qsort_compar_f compar) {
10285  void *ctx;
10286  COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
10287  // Run the comparator over all array elements to detect any memory issues.
10288  if (nmemb > 1) {
10289    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
10290      void *p = (void *)((char *)base + i * size);
10291      void *q = (void *)((char *)base + (i + 1) * size);
10292      COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
10293      compar(p, q);
10294    }
10295  }
10296  qsort_compar_f old_compar = qsort_compar;
10297  SIZE_T old_size = qsort_size;
10298  // Handle qsort() implementations that recurse using an
10299  // interposable function call:
10300  bool already_wrapped = compar == wrapped_qsort_compar;
10301  if (already_wrapped) {
10302    // This case should only happen if the qsort() implementation calls itself
10303    // using a preemptible function call (e.g. the FreeBSD libc version).
10304    // Check that the size and comparator arguments are as expected.
10305    CHECK_NE(compar, qsort_compar);
10306    CHECK_EQ(qsort_size, size);
10307  } else {
10308    qsort_compar = compar;
10309    qsort_size = size;
10310  }
10311  REAL(qsort)(base, nmemb, size, wrapped_qsort_compar);
10312  if (!already_wrapped) {
10313    qsort_compar = old_compar;
10314    qsort_size = old_size;
10315  }
10316  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
10317}
10318#  define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
10319#else
10320#  define INIT_QSORT
10321#endif
10322
10323#if SANITIZER_INTERCEPT_BSEARCH
10324typedef int (*bsearch_compar_f)(const void *, const void *);
10325struct bsearch_compar_params {
10326  const void *key;
10327  bsearch_compar_f compar;
10328};
10329
10330static int wrapped_bsearch_compar(const void *key, const void *b) {
10331  const bsearch_compar_params *params = (const bsearch_compar_params *)key;
10332  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
10333  return params->compar(params->key, b);
10334}
10335
10336INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
10337            SIZE_T size, bsearch_compar_f compar) {
10338  void *ctx;
10339  COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
10340  bsearch_compar_params params = {key, compar};
10341  return REAL(bsearch)(&params, base, nmemb, size, wrapped_bsearch_compar);
10342}
10343#  define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
10344#else
10345#  define INIT_BSEARCH
10346#endif
10347
10348#if SANITIZER_INTERCEPT_SIGALTSTACK
10349INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
10350  void *ctx;
10351  COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss);
10352  int r = REAL(sigaltstack)(ss, oss);
10353  if (r == 0 && oss != nullptr) {
10354    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz);
10355  }
10356  return r;
10357}
10358#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack)
10359#else
10360#define INIT_SIGALTSTACK
10361#endif
10362
10363#if SANITIZER_INTERCEPT_PROCCTL
10364INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) {
10365   void *ctx;
10366   COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data);
10367   static const int PROC_REAP_ACQUIRE = 2;
10368   static const int PROC_REAP_RELEASE = 3;
10369   static const int PROC_REAP_STATUS = 4;
10370   static const int PROC_REAP_GETPIDS = 5;
10371   static const int PROC_REAP_KILL = 6;
10372   if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) {
10373     COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int));
10374   } else {
10375     // reap_acquire/reap_release bears no arguments.
10376     if (cmd > PROC_REAP_RELEASE) {
10377       unsigned int reapsz;
10378       switch (cmd) {
10379       case PROC_REAP_STATUS:
10380         reapsz = struct_procctl_reaper_status_sz;
10381         break;
10382       case PROC_REAP_GETPIDS:
10383         reapsz = struct_procctl_reaper_pids_sz;
10384         break;
10385       case PROC_REAP_KILL:
10386         reapsz = struct_procctl_reaper_kill_sz;
10387         break;
10388       }
10389       COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz);
10390     }
10391   }
10392   return REAL(procctl)(idtype, id, cmd, data);
10393}
10394#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl)
10395#else
10396#define INIT_PROCCTL
10397#endif
10398
10399#if SANITIZER_INTERCEPT_UNAME
10400INTERCEPTOR(int, uname, struct utsname *utsname) {
10401#if SANITIZER_LINUX
10402  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
10403    return internal_uname(utsname);
10404#endif
10405  void *ctx;
10406  COMMON_INTERCEPTOR_ENTER(ctx, uname, utsname);
10407  int res = REAL(uname)(utsname);
10408  if (!res)
10409    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
10410                                   __sanitizer::struct_utsname_sz);
10411  return res;
10412}
10413#define INIT_UNAME COMMON_INTERCEPT_FUNCTION(uname)
10414#else
10415#define INIT_UNAME
10416#endif
10417
10418#if SANITIZER_INTERCEPT___XUNAME
10419// FreeBSD's <sys/utsname.h> define uname() as
10420// static __inline int uname(struct utsname *name) {
10421//   return __xuname(SYS_NMLN, (void*)name);
10422// }
10423INTERCEPTOR(int, __xuname, int size, void *utsname) {
10424  void *ctx;
10425  COMMON_INTERCEPTOR_ENTER(ctx, __xuname, size, utsname);
10426  int res = REAL(__xuname)(size, utsname);
10427  if (!res)
10428    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
10429                                   __sanitizer::struct_utsname_sz);
10430  return res;
10431}
10432#define INIT___XUNAME COMMON_INTERCEPT_FUNCTION(__xuname)
10433#else
10434#define INIT___XUNAME
10435#endif
10436
10437#include "sanitizer_common_interceptors_netbsd_compat.inc"
10438
10439static void InitializeCommonInterceptors() {
10440#if SI_POSIX
10441  static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
10442  interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
10443#endif
10444
10445  INIT_MMAP;
10446  INIT_MMAP64;
10447  INIT_TEXTDOMAIN;
10448  INIT_STRLEN;
10449  INIT_STRNLEN;
10450  INIT_STRNDUP;
10451  INIT___STRNDUP;
10452  INIT_STRCMP;
10453  INIT_STRNCMP;
10454  INIT_STRCASECMP;
10455  INIT_STRNCASECMP;
10456  INIT_STRSTR;
10457  INIT_STRCASESTR;
10458  INIT_STRCHR;
10459  INIT_STRCHRNUL;
10460  INIT_STRRCHR;
10461  INIT_STRSPN;
10462  INIT_STRTOK;
10463  INIT_STRPBRK;
10464  INIT_STRXFRM;
10465  INIT___STRXFRM_L;
10466  INIT_MEMSET;
10467  INIT_MEMMOVE;
10468  INIT_MEMCPY;
10469  INIT_MEMCHR;
10470  INIT_MEMCMP;
10471  INIT_BCMP;
10472  INIT_MEMRCHR;
10473  INIT_MEMMEM;
10474  INIT_READ;
10475  INIT_FREAD;
10476  INIT_PREAD;
10477  INIT_PREAD64;
10478  INIT_READV;
10479  INIT_PREADV;
10480  INIT_PREADV64;
10481  INIT_WRITE;
10482  INIT_FWRITE;
10483  INIT_PWRITE;
10484  INIT_PWRITE64;
10485  INIT_WRITEV;
10486  INIT_PWRITEV;
10487  INIT_PWRITEV64;
10488  INIT_FGETS;
10489  INIT_FPUTS;
10490  INIT_PUTS;
10491  INIT_PRCTL;
10492  INIT_LOCALTIME_AND_FRIENDS;
10493  INIT_STRPTIME;
10494  INIT_SCANF;
10495  INIT_ISOC99_SCANF;
10496  INIT_PRINTF;
10497  INIT_PRINTF_L;
10498  INIT_ISOC99_PRINTF;
10499  INIT_FREXP;
10500  INIT_FREXPF_FREXPL;
10501  INIT_GETPWNAM_AND_FRIENDS;
10502  INIT_GETPWNAM_R_AND_FRIENDS;
10503  INIT_GETPWENT;
10504  INIT_FGETPWENT;
10505  INIT_GETPWENT_R;
10506  INIT_FGETPWENT_R;
10507  INIT_FGETGRENT_R;
10508  INIT_SETPWENT;
10509  INIT_CLOCK_GETTIME;
10510  INIT_CLOCK_GETCPUCLOCKID;
10511  INIT_GETITIMER;
10512  INIT_TIME;
10513  INIT_GLOB;
10514  INIT_GLOB64;
10515  INIT___B64_TO;
10516  INIT___DN_EXPAND;
10517  INIT_POSIX_SPAWN;
10518  INIT_WAIT;
10519  INIT_WAIT4;
10520  INIT_INET;
10521  INIT_PTHREAD_GETSCHEDPARAM;
10522  INIT_GETADDRINFO;
10523  INIT_GETNAMEINFO;
10524  INIT_GETSOCKNAME;
10525  INIT_GETHOSTBYNAME;
10526  INIT_GETHOSTBYNAME2;
10527  INIT_GETHOSTBYNAME_R;
10528  INIT_GETHOSTBYNAME2_R;
10529  INIT_GETHOSTBYADDR_R;
10530  INIT_GETHOSTENT_R;
10531  INIT_GETSOCKOPT;
10532  INIT_ACCEPT;
10533  INIT_ACCEPT4;
10534  INIT_PACCEPT;
10535  INIT_MODF;
10536  INIT_RECVMSG;
10537  INIT_SENDMSG;
10538  INIT_RECVMMSG;
10539  INIT_SENDMMSG;
10540  INIT_SYSMSG;
10541  INIT_GETPEERNAME;
10542  INIT_IOCTL;
10543  INIT_INET_ATON;
10544  INIT_SYSINFO;
10545  INIT_READDIR;
10546  INIT_READDIR64;
10547  INIT_PTRACE;
10548  INIT_SETLOCALE;
10549  INIT_GETCWD;
10550  INIT_GET_CURRENT_DIR_NAME;
10551  INIT_STRTOIMAX;
10552  INIT_MBSTOWCS;
10553  INIT_MBSNRTOWCS;
10554  INIT_WCSTOMBS;
10555  INIT_WCSNRTOMBS;
10556  INIT_WCRTOMB;
10557  INIT_WCTOMB;
10558  INIT_TCGETATTR;
10559  INIT_REALPATH;
10560  INIT_CANONICALIZE_FILE_NAME;
10561  INIT_CONFSTR;
10562  INIT_SCHED_GETAFFINITY;
10563  INIT_SCHED_GETPARAM;
10564  INIT_STRERROR;
10565  INIT_STRERROR_R;
10566  INIT_XPG_STRERROR_R;
10567  INIT_SCANDIR;
10568  INIT_SCANDIR64;
10569  INIT_GETGROUPS;
10570  INIT_POLL;
10571  INIT_PPOLL;
10572  INIT_WORDEXP;
10573  INIT_SIGWAIT;
10574  INIT_SIGWAITINFO;
10575  INIT_SIGTIMEDWAIT;
10576  INIT_SIGSETOPS;
10577  INIT_SIGSET_LOGICOPS;
10578  INIT_SIGPENDING;
10579  INIT_SIGPROCMASK;
10580  INIT_PTHREAD_SIGMASK;
10581  INIT_BACKTRACE;
10582  INIT__EXIT;
10583  INIT_PTHREAD_MUTEX_LOCK;
10584  INIT_PTHREAD_MUTEX_UNLOCK;
10585  INIT___PTHREAD_MUTEX_LOCK;
10586  INIT___PTHREAD_MUTEX_UNLOCK;
10587  INIT___LIBC_MUTEX_LOCK;
10588  INIT___LIBC_MUTEX_UNLOCK;
10589  INIT___LIBC_THR_SETCANCELSTATE;
10590  INIT_GETMNTENT;
10591  INIT_GETMNTENT_R;
10592  INIT_STATFS;
10593  INIT_STATFS64;
10594  INIT_STATVFS;
10595  INIT_STATVFS64;
10596  INIT_INITGROUPS;
10597  INIT_ETHER_NTOA_ATON;
10598  INIT_ETHER_HOST;
10599  INIT_ETHER_R;
10600  INIT_SHMCTL;
10601  INIT_RANDOM_R;
10602  INIT_PTHREAD_ATTR_GET;
10603  INIT_PTHREAD_ATTR_GET_SCHED;
10604  INIT_PTHREAD_ATTR_GETINHERITSCHED;
10605  INIT_PTHREAD_ATTR_GETAFFINITY_NP;
10606  INIT_PTHREAD_GETAFFINITY_NP;
10607  INIT_PTHREAD_MUTEXATTR_GETPSHARED;
10608  INIT_PTHREAD_MUTEXATTR_GETTYPE;
10609  INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
10610  INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
10611  INIT_PTHREAD_MUTEXATTR_GETROBUST;
10612  INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
10613  INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
10614  INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
10615  INIT_PTHREAD_CONDATTR_GETPSHARED;
10616  INIT_PTHREAD_CONDATTR_GETCLOCK;
10617  INIT_PTHREAD_BARRIERATTR_GETPSHARED;
10618  INIT_TMPNAM;
10619  INIT_TMPNAM_R;
10620  INIT_PTSNAME;
10621  INIT_PTSNAME_R;
10622  INIT_TTYNAME;
10623  INIT_TTYNAME_R;
10624  INIT_TEMPNAM;
10625  INIT_PTHREAD_SETNAME_NP;
10626  INIT_PTHREAD_GETNAME_NP;
10627  INIT_SINCOS;
10628  INIT_REMQUO;
10629  INIT_REMQUOL;
10630  INIT_LGAMMA;
10631  INIT_LGAMMAL;
10632  INIT_LGAMMA_R;
10633  INIT_LGAMMAL_R;
10634  INIT_DRAND48_R;
10635  INIT_RAND_R;
10636  INIT_GETLINE;
10637  INIT_ICONV;
10638  INIT_TIMES;
10639  INIT_TLS_GET_ADDR;
10640  INIT_LISTXATTR;
10641  INIT_GETXATTR;
10642  INIT_GETRESID;
10643  INIT_GETIFADDRS;
10644  INIT_IF_INDEXTONAME;
10645  INIT_CAPGET;
10646  INIT_AEABI_MEM;
10647  INIT___BZERO;
10648  INIT_BZERO;
10649  INIT_FTIME;
10650  INIT_XDR;
10651  INIT_XDRREC_LINUX;
10652  INIT_TSEARCH;
10653  INIT_LIBIO_INTERNALS;
10654  INIT_FOPEN;
10655  INIT_FOPEN64;
10656  INIT_FLOPEN;
10657  INIT_OPEN_MEMSTREAM;
10658  INIT_OBSTACK;
10659  INIT_FFLUSH;
10660  INIT_FCLOSE;
10661  INIT_DLOPEN_DLCLOSE;
10662  INIT_GETPASS;
10663  INIT_TIMERFD;
10664  INIT_MLOCKX;
10665  INIT_FOPENCOOKIE;
10666  INIT_SEM;
10667  INIT_PTHREAD_SETCANCEL;
10668  INIT_MINCORE;
10669  INIT_PROCESS_VM_READV;
10670  INIT_CTERMID;
10671  INIT_CTERMID_R;
10672  INIT_RECV_RECVFROM;
10673  INIT_SEND_SENDTO;
10674  INIT_STAT;
10675  INIT_STAT64;
10676  INIT_EVENTFD_READ_WRITE;
10677  INIT_LSTAT;
10678  INIT_LSTAT64;
10679  INIT___XSTAT;
10680  INIT___XSTAT64;
10681  INIT___LXSTAT;
10682  INIT___LXSTAT64;
10683  // FIXME: add other *stat interceptors.
10684  INIT_UTMP;
10685  INIT_UTMPX;
10686  INIT_GETLOADAVG;
10687  INIT_WCSLEN;
10688  INIT_WCSCAT;
10689  INIT_WCSDUP;
10690  INIT_WCSXFRM;
10691  INIT___WCSXFRM_L;
10692  INIT_ACCT;
10693  INIT_USER_FROM_UID;
10694  INIT_UID_FROM_USER;
10695  INIT_GROUP_FROM_GID;
10696  INIT_GID_FROM_GROUP;
10697  INIT_ACCESS;
10698  INIT_FACCESSAT;
10699  INIT_GETGROUPLIST;
10700  INIT_GETGROUPMEMBERSHIP;
10701  INIT_READLINK;
10702  INIT_READLINKAT;
10703  INIT_NAME_TO_HANDLE_AT;
10704  INIT_OPEN_BY_HANDLE_AT;
10705  INIT_STRLCPY;
10706  INIT_DEVNAME;
10707  INIT_DEVNAME_R;
10708  INIT_FGETLN;
10709  INIT_STRMODE;
10710  INIT_TTYENT;
10711  INIT_PROTOENT;
10712  INIT_PROTOENT_R;
10713  INIT_NETENT;
10714  INIT_GETMNTINFO;
10715  INIT_MI_VECTOR_HASH;
10716  INIT_SETVBUF;
10717  INIT_GETVFSSTAT;
10718  INIT_REGEX;
10719  INIT_REGEXSUB;
10720  INIT_FTS;
10721  INIT_SYSCTL;
10722  INIT_ASYSCTL;
10723  INIT_SYSCTLGETMIBINFO;
10724  INIT_NL_LANGINFO;
10725  INIT_MODCTL;
10726  INIT_STRTONUM;
10727  INIT_FPARSELN;
10728  INIT_STATVFS1;
10729  INIT_STRTOI;
10730  INIT_CAPSICUM;
10731  INIT_SHA1;
10732  INIT_MD4;
10733  INIT_RMD160;
10734  INIT_MD5;
10735  INIT_FSEEK;
10736  INIT_MD2;
10737  INIT_SHA2;
10738  INIT_VIS;
10739  INIT_CDB;
10740  INIT_GETFSENT;
10741  INIT_ARC4RANDOM;
10742  INIT_POPEN;
10743  INIT_POPENVE;
10744  INIT_PCLOSE;
10745  INIT_FUNOPEN;
10746  INIT_FUNOPEN2;
10747  INIT_FDEVNAME;
10748  INIT_GETUSERSHELL;
10749  INIT_SL_INIT;
10750  INIT_GETRANDOM;
10751  INIT_CRYPT;
10752  INIT_CRYPT_R;
10753  INIT_GETENTROPY;
10754  INIT_QSORT;
10755  INIT_QSORT_R;
10756  INIT_BSEARCH;
10757  INIT_SIGALTSTACK;
10758  INIT_PROCCTL
10759  INIT_UNAME;
10760  INIT___XUNAME;
10761
10762  INIT___PRINTF_CHK;
10763}
10764