head	1.15;
access;
symbols
	netbsd-9-5-RELEASE:1.7
	netbsd-11-0-RELEASE:1.14
	netbsd-11-0-RC7:1.14
	netbsd-11-0-RC6:1.14
	netbsd-11-0-RC5:1.14
	netbsd-11-0-RC4:1.14
	netbsd-11-0-RC3:1.14
	netbsd-11-0-RC2:1.14
	netbsd-11-0-RC1:1.14
	gcc-14-3-0:1.1.1.12
	perseant-exfatfs-base-20250801:1.14
	netbsd-11:1.14.0.4
	netbsd-11-base:1.14
	gcc-12-5-0:1.1.1.11
	netbsd-10-1-RELEASE:1.13
	perseant-exfatfs-base-20240630:1.14
	gcc-12-4-0:1.1.1.11
	perseant-exfatfs:1.14.0.2
	perseant-exfatfs-base:1.14
	netbsd-8-3-RELEASE:1.4.8.1
	netbsd-9-4-RELEASE:1.7
	netbsd-10-0-RELEASE:1.13
	netbsd-10-0-RC6:1.13
	netbsd-10-0-RC5:1.13
	netbsd-10-0-RC4:1.13
	netbsd-10-0-RC3:1.13
	netbsd-10-0-RC2:1.13
	netbsd-10-0-RC1:1.13
	gcc-12-3-0:1.1.1.11
	gcc-10-5-0:1.1.1.10
	netbsd-10:1.13.0.6
	netbsd-10-base:1.13
	netbsd-9-3-RELEASE:1.7
	gcc-10-4-0:1.1.1.10
	cjep_sun2x-base1:1.13
	cjep_sun2x:1.13.0.4
	cjep_sun2x-base:1.13
	cjep_staticlib_x-base1:1.13
	netbsd-9-2-RELEASE:1.7
	cjep_staticlib_x:1.13.0.2
	cjep_staticlib_x-base:1.13
	gcc-10-3-0:1.1.1.10
	netbsd-9-1-RELEASE:1.7
	gcc-9-3-0:1.1.1.9
	gcc-7-5-0:1.1.1.7
	phil-wifi-20200421:1.8
	phil-wifi-20200411:1.8
	is-mlppp:1.8.0.2
	is-mlppp-base:1.8
	phil-wifi-20200406:1.8
	netbsd-8-2-RELEASE:1.4.8.1
	gcc-8-4-0:1.1.1.8
	netbsd-9-0-RELEASE:1.7
	netbsd-9-0-RC2:1.7
	netbsd-9-0-RC1:1.7
	phil-wifi-20191119:1.8
	gcc-8-3-0:1.1.1.6
	netbsd-9:1.7.0.2
	netbsd-9-base:1.7
	phil-wifi-20190609:1.7
	netbsd-8-1-RELEASE:1.4.8.1
	netbsd-8-1-RC1:1.4.8.1
	pgoyette-compat-merge-20190127:1.6.2.1
	pgoyette-compat-20190127:1.7
	gcc-7-4-0:1.1.1.5
	pgoyette-compat-20190118:1.6
	pgoyette-compat-1226:1.6
	pgoyette-compat-1126:1.6
	gcc-6-5-0:1.1.1.4
	pgoyette-compat-1020:1.6
	pgoyette-compat-0930:1.6
	pgoyette-compat-0906:1.6
	netbsd-7-2-RELEASE:1.1.1.1.6.1
	pgoyette-compat-0728:1.6
	netbsd-8-0-RELEASE:1.4.8.1
	phil-wifi:1.6.0.4
	phil-wifi-base:1.6
	pgoyette-compat-0625:1.6
	netbsd-8-0-RC2:1.4.8.1
	pgoyette-compat-0521:1.6
	pgoyette-compat-0502:1.6
	pgoyette-compat-0422:1.6
	netbsd-8-0-RC1:1.4.8.1
	pgoyette-compat-0415:1.6
	pgoyette-compat-0407:1.6
	pgoyette-compat-0330:1.6
	pgoyette-compat-0322:1.6
	pgoyette-compat-0315:1.6
	netbsd-7-1-2-RELEASE:1.1.1.1.6.1
	pgoyette-compat:1.6.0.2
	pgoyette-compat-base:1.6
	gcc-6-4-0:1.1.1.4
	netbsd-7-1-1-RELEASE:1.1.1.1.6.1
	gcc-5-5-0:1.1.1.3
	matt-nb8-mediatek:1.4.0.12
	matt-nb8-mediatek-base:1.4
	perseant-stdc-iso10646:1.4.0.10
	perseant-stdc-iso10646-base:1.4
	netbsd-8:1.4.0.8
	netbsd-8-base:1.4
	prg-localcount2-base3:1.4
	prg-localcount2-base2:1.4
	prg-localcount2-base1:1.4
	prg-localcount2:1.4.0.6
	prg-localcount2-base:1.4
	pgoyette-localcount-20170426:1.4
	bouyer-socketcan-base1:1.4
	pgoyette-localcount-20170320:1.4
	netbsd-7-1:1.1.1.1.6.1.0.6
	netbsd-7-1-RELEASE:1.1.1.1.6.1
	netbsd-7-1-RC2:1.1.1.1.6.1
	netbsd-7-nhusb-base-20170116:1.1.1.1.6.1
	bouyer-socketcan:1.4.0.4
	bouyer-socketcan-base:1.4
	pgoyette-localcount-20170107:1.4
	netbsd-7-1-RC1:1.1.1.1.6.1
	pgoyette-localcount-20161104:1.4
	netbsd-7-0-2-RELEASE:1.1.1.1.6.1
	localcount-20160914:1.4
	netbsd-7-nhusb:1.1.1.1.6.1.0.4
	netbsd-7-nhusb-base:1.1.1.1.6.1
	pgoyette-localcount-20160806:1.4
	pgoyette-localcount-20160726:1.4
	pgoyette-localcount:1.4.0.2
	pgoyette-localcount-base:1.4
	gcc-5-4-0:1.1.1.2
	netbsd-7-0-1-RELEASE:1.1.1.1.6.1
	gcc-5-3-0:1.1.1.2
	netbsd-7-0:1.1.1.1.6.1.0.2
	netbsd-7-0-RELEASE:1.1.1.1.6.1
	gcc-4-8-5-pre-gcc-old-import:1.2
	netbsd-7-0-RC3:1.1.1.1.6.1
	netbsd-7-0-RC2:1.1.1.1.6.1
	post-gcc-4-8-5-merge:1.2
	gcc-4-8-5:1.1.1.1
	netbsd-7-0-RC1:1.1.1.1.6.1
	gcc-4-8-4:1.1.1.1
	gcc-4-8-20141009:1.1.1.1
	tls-maxphys-base:1.1.1.1
	tls-maxphys:1.1.1.1.0.8
	netbsd-7:1.1.1.1.0.6
	netbsd-7-base:1.1.1.1
	gcc-4-8-3:1.1.1.1
	yamt-pagecache:1.1.1.1.0.4
	yamt-pagecache-base9:1.1.1.1
	tls-earlyentropy:1.1.1.1.0.2
	tls-earlyentropy-base:1.1.1.1
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.1
	riastradh-drm2-base3:1.1.1.1
	gcc-4-8-3-pre-r208254:1.1.1.1
	gcc-4-8-3-pre-r206687:1.1.1.1
	FSF:1.1.1;
locks; strict;
comment	@# @;


1.15
date	2025.09.14.00.08.56;	author mrg;	state Exp;
branches;
next	1.14;
commitid	x9D5QEnvbeMI4CaG;

1.14
date	2023.07.30.05.51.42;	author mrg;	state Exp;
branches;
next	1.13;
commitid	Iugici1GtQ2mWMyE;

1.13
date	2021.04.11.23.54.26;	author mrg;	state Exp;
branches;
next	1.12;
commitid	wJn7ggfUTEMOWVOC;

1.12
date	2021.04.11.00.02.22;	author mrg;	state Exp;
branches;
next	1.11;
commitid	rXajJcXg3xWG0OOC;

1.11
date	2020.09.12.15.01.38;	author kamil;	state Exp;
branches;
next	1.10;
commitid	v0LgibTWpV2hMLnC;

1.10
date	2020.09.11.01.03.31;	author kamil;	state Exp;
branches;
next	1.9;
commitid	C269FvxTsin6bznC;

1.9
date	2020.09.05.09.12.32;	author mrg;	state Exp;
branches;
next	1.8;
commitid	dS3LXwk3lAvP4QmC;

1.8
date	2019.10.01.10.38.23;	author mrg;	state Exp;
branches;
next	1.7;
commitid	r1DeKUVOMBnJt9FB;

1.7
date	2019.01.19.12.10.12;	author mrg;	state Exp;
branches;
next	1.6;
commitid	k8UsQyKpGt5Abo8B;

1.6
date	2018.02.02.03.41.11;	author mrg;	state Exp;
branches
	1.6.2.1
	1.6.4.1;
next	1.5;
commitid	YbHkrPGCnw2dEepA;

1.5
date	2017.11.12.00.36.47;	author mrg;	state Exp;
branches;
next	1.4;
commitid	qvf6fubay3FAgGeA;

1.4
date	2016.05.31.20.47.25;	author christos;	state Exp;
branches
	1.4.8.1;
next	1.3;
commitid	FzvAXEQe5IKc0G8z;

1.3
date	2016.01.24.09.43.38;	author mrg;	state Exp;
branches;
next	1.2;
commitid	dxhNntGC3MSSqaSy;

1.2
date	2014.10.15.18.44.50;	author christos;	state Exp;
branches;
next	1.1;
commitid	EOhLD54NySkYpkUx;

1.1
date	2014.03.01.08.41.18;	author mrg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	TtaB91QNTknAoYqx;

1.6.2.1
date	2019.01.26.21.59.16;	author pgoyette;	state Exp;
branches;
next	;
commitid	JKpcmvSjdT25dl9B;

1.6.4.1
date	2019.06.10.21.54.28;	author christos;	state Exp;
branches;
next	1.6.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.6.4.2
date	2020.04.13.07.58.21;	author martin;	state Exp;
branches;
next	;
commitid	X01YhRUPVUDaec4C;

1.4.8.1
date	2017.11.23.11.01.56;	author martin;	state Exp;
branches;
next	;
commitid	lA6hq5q2Y1dXl9gA;

1.1.1.1
date	2014.03.01.08.41.18;	author mrg;	state Exp;
branches
	1.1.1.1.4.1
	1.1.1.1.6.1
	1.1.1.1.8.1;
next	1.1.1.2;
commitid	TtaB91QNTknAoYqx;

1.1.1.2
date	2016.01.24.06.05.41;	author mrg;	state Exp;
branches;
next	1.1.1.3;
commitid	uWWfbLp08zOK79Sy;

1.1.1.3
date	2017.11.11.23.50.05;	author mrg;	state Exp;
branches;
next	1.1.1.4;
commitid	KefS4gJN8ajyYFeA;

1.1.1.4
date	2018.02.02.01.58.46;	author mrg;	state Exp;
branches;
next	1.1.1.5;
commitid	XNKaycqpfhzd5epA;

1.1.1.5
date	2019.01.19.10.14.03;	author mrg;	state Exp;
branches;
next	1.1.1.6;
commitid	VQ8OwWIg5RS9kn8B;

1.1.1.6
date	2019.10.01.09.36.38;	author mrg;	state Exp;
branches;
next	1.1.1.7;
commitid	smvgr2IPAQDr89FB;

1.1.1.7
date	2020.08.11.05.10.31;	author mrg;	state Exp;
branches;
next	1.1.1.8;
commitid	5dBRDT7i6e65xBjC;

1.1.1.8
date	2020.08.11.05.30.44;	author mrg;	state Exp;
branches;
next	1.1.1.9;
commitid	7AI4OfpLi4eqEBjC;

1.1.1.9
date	2020.09.05.07.52.57;	author mrg;	state Exp;
branches;
next	1.1.1.10;
commitid	ZRYA7IOuwfMjAPmC;

1.1.1.10
date	2021.04.10.22.09.22;	author mrg;	state Exp;
branches;
next	1.1.1.11;
commitid	eC4g0MRpqTvEkNOC;

1.1.1.11
date	2023.07.30.05.20.40;	author mrg;	state Exp;
branches;
next	1.1.1.12;
commitid	tk6nV4mbc9nVEMyE;

1.1.1.12
date	2025.09.13.23.45.04;	author mrg;	state Exp;
branches;
next	;
commitid	KwhwN4krNWa6XBaG;

1.1.1.1.4.1
date	2014.03.01.08.41.18;	author yamt;	state dead;
branches;
next	1.1.1.1.4.2;
commitid	WU1ij9nRU3v8pyBx;

1.1.1.1.4.2
date	2014.05.22.16.37.02;	author yamt;	state Exp;
branches;
next	;
commitid	WU1ij9nRU3v8pyBx;

1.1.1.1.6.1
date	2015.01.25.00.19.32;	author martin;	state Exp;
branches;
next	;
commitid	Zd18dL7rpT5Z0l7y;

1.1.1.1.8.1
date	2014.03.01.08.41.18;	author tls;	state dead;
branches;
next	1.1.1.1.8.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.1.8.2
date	2014.08.19.23.54.37;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;


desc
@@


1.15
log
@merge GCC 14.3.0.
@
text
@//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Common function interceptors for tools like AddressSanitizer,
// ThreadSanitizer, MemorySanitizer, etc.
//
// This file should be included into the tool's interceptor file,
// which has to define its own macros:
//   COMMON_INTERCEPTOR_ENTER
//   COMMON_INTERCEPTOR_ENTER_NOIGNORE
//   COMMON_INTERCEPTOR_READ_RANGE
//   COMMON_INTERCEPTOR_WRITE_RANGE
//   COMMON_INTERCEPTOR_INITIALIZE_RANGE
//   COMMON_INTERCEPTOR_DIR_ACQUIRE
//   COMMON_INTERCEPTOR_FD_ACQUIRE
//   COMMON_INTERCEPTOR_FD_RELEASE
//   COMMON_INTERCEPTOR_FD_ACCESS
//   COMMON_INTERCEPTOR_SET_THREAD_NAME
//   COMMON_INTERCEPTOR_DLOPEN
//   COMMON_INTERCEPTOR_ON_EXIT
//   COMMON_INTERCEPTOR_SET_PTHREAD_NAME
//   COMMON_INTERCEPTOR_HANDLE_RECVMSG
//   COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
//   COMMON_INTERCEPTOR_MMAP_IMPL
//   COMMON_INTERCEPTOR_MUNMAP_IMPL
//   COMMON_INTERCEPTOR_COPY_STRING
//   COMMON_INTERCEPTOR_STRNDUP_IMPL
//   COMMON_INTERCEPTOR_STRERROR
//===----------------------------------------------------------------------===//

#include <stdarg.h>

#include "interception/interception.h"
#include "sanitizer_addrhashmap.h"
#include "sanitizer_dl.h"
#include "sanitizer_errno.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_platform_interceptors.h"
#include "sanitizer_symbolizer.h"
#include "sanitizer_tls_get_addr.h"

#if SANITIZER_INTERCEPTOR_HOOKS
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
  SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
#else
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)

#endif  // SANITIZER_INTERCEPTOR_HOOKS

#if SANITIZER_WINDOWS && !defined(va_copy)
#define va_copy(dst, src) ((dst) = (src))
#endif // _WIN32

#if SANITIZER_FREEBSD
#define pthread_setname_np pthread_set_name_np
#define inet_aton __inet_aton
#define inet_pton __inet_pton
#define iconv __bsd_iconv
#endif

#if SANITIZER_NETBSD
#define clock_getres __clock_getres50
#define clock_gettime __clock_gettime50
#define clock_settime __clock_settime50
#define ctime __ctime50
#define ctime_r __ctime_r50
#define devname __devname50
#define fgetpos __fgetpos50
#define fsetpos __fsetpos50
#define fstatvfs __fstatvfs90
#define fstatvfs1 __fstatvfs190
#define fts_children __fts_children60
#define fts_close __fts_close60
#define fts_open __fts_open60
#define fts_read __fts_read60
#define fts_set __fts_set60
#define getitimer __getitimer50
#define getmntinfo __getmntinfo90
#define getpwent __getpwent50
#define getpwnam __getpwnam50
#define getpwnam_r __getpwnam_r50
#define getpwuid __getpwuid50
#define getpwuid_r __getpwuid_r50
#define getutent __getutent50
#define getutxent __getutxent50
#define getutxid __getutxid50
#define getutxline __getutxline50
#define getvfsstat __getvfsstat90
#define pututxline __pututxline50
#define glob __glob30
#define gmtime __gmtime50
#define gmtime_r __gmtime_r50
#define localtime __locatime50
#define localtime_r __localtime_r50
#define mktime __mktime50
#define lstat __lstat50
#define opendir __opendir30
#define readdir __readdir30
#define readdir_r __readdir_r30
#define scandir __scandir30
#define setitimer __setitimer50
#define setlocale __setlocale50
#define shmctl __shmctl50
#define sigaltstack __sigaltstack14
#define sigemptyset __sigemptyset14
#define sigfillset __sigfillset14
#define sigpending __sigpending14
#define sigprocmask __sigprocmask14
#define sigtimedwait __sigtimedwait50
#define stat __stat50
#define statvfs __statvfs90
#define statvfs1 __statvfs190
#define time __time50
#define times __times13
#define unvis __unvis50
#define wait3 __wait350
#define wait4 __wait450
extern const unsigned short *_ctype_tab_;
extern const short *_toupper_tab_;
extern const short *_tolower_tab_;
#endif

#if SANITIZER_MUSL && \
  (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
// time-related functions that take 64-bit time_t values.  See
// https://musl.libc.org/time64.html
#define adjtime __adjtime64
#define adjtimex __adjtimex_time64
#define aio_suspend __aio_suspend_time64
#define clock_adjtime __clock_adjtime64
#define clock_getres __clock_getres_time64
#define clock_gettime __clock_gettime64
#define clock_nanosleep __clock_nanosleep_time64
#define clock_settime __clock_settime64
#define cnd_timedwait __cnd_timedwait_time64
#define ctime __ctime64
#define ctime_r __ctime64_r
#define difftime __difftime64
#define dlsym __dlsym_time64
#define fstatat __fstatat_time64
#define fstat __fstat_time64
#define ftime __ftime64
#define futimens __futimens_time64
#define futimesat __futimesat_time64
#define futimes __futimes_time64
#define getitimer __getitimer_time64
#define getrusage __getrusage_time64
#define gettimeofday __gettimeofday_time64
#define gmtime __gmtime64
#define gmtime_r __gmtime64_r
#define localtime __localtime64
#define localtime_r __localtime64_r
#define lstat __lstat_time64
#define lutimes __lutimes_time64
#define mktime __mktime64
#define mq_timedreceive __mq_timedreceive_time64
#define mq_timedsend __mq_timedsend_time64
#define mtx_timedlock __mtx_timedlock_time64
#define nanosleep __nanosleep_time64
#define ppoll __ppoll_time64
#define pselect __pselect_time64
#define pthread_cond_timedwait __pthread_cond_timedwait_time64
#define pthread_mutex_timedlock __pthread_mutex_timedlock_time64
#define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_time64
#define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_time64
#define pthread_timedjoin_np __pthread_timedjoin_np_time64
#define recvmmsg __recvmmsg_time64
#define sched_rr_get_interval __sched_rr_get_interval_time64
#define select __select_time64
#define semtimedop __semtimedop_time64
#define sem_timedwait __sem_timedwait_time64
#define setitimer __setitimer_time64
#define settimeofday __settimeofday_time64
#define sigtimedwait __sigtimedwait_time64
#define stat __stat_time64
#define stime __stime64
#define thrd_sleep __thrd_sleep_time64
#define timegm __timegm_time64
#define timerfd_gettime __timerfd_gettime64
#define timerfd_settime __timerfd_settime64
#define timer_gettime __timer_gettime64
#define timer_settime __timer_settime64
#define timespec_get __timespec_get_time64
#define time __time64
#define utimensat __utimensat_time64
#define utimes __utimes_time64
#define utime __utime64
#define wait3 __wait3_time64
#define wait4 __wait4_time64
#endif

#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
#endif

#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
#endif

#ifndef COMMON_INTERCEPTOR_FD_ACCESS
#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
#endif

#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
#endif

#ifndef COMMON_INTERCEPTOR_FILE_OPEN
#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
#endif

#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
#endif

#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
#endif

#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
#endif

#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
  COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
#endif

#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
#endif

#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n)                   \
    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
      common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )

#ifndef COMMON_INTERCEPTOR_DLOPEN
#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
  ({ CheckNoDeepBind(filename, flag); REAL(dlopen)(filename, flag); })
#endif

#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
#endif

#ifndef COMMON_INTERCEPTOR_ACQUIRE
#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
#endif

#ifndef COMMON_INTERCEPTOR_RELEASE
#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
#endif

#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
#endif

#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
#endif

#ifdef SANITIZER_NLDBL_VERSION
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
#else
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION(fn)
#endif

#if SANITIZER_GLIBC
// If we could not find the versioned symbol, fall back to an unversioned
// lookup. This is needed to work around a GLibc bug that causes dlsym
// with RTLD_NEXT to return the oldest versioned symbol.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=14932.
// For certain symbols (e.g. regexec) we have to perform a versioned lookup,
// but that versioned symbol will only exist for architectures where the
// oldest Glibc version pre-dates support for that architecture.
// For example, regexec@@GLIBC_2.3.4 exists on x86_64, but not RISC-V.
// See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920.
#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
  COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver)
#else
#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
  COMMON_INTERCEPT_FUNCTION(fn)
#endif

#ifndef COMMON_INTERCEPTOR_MMAP_IMPL
#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
                                     off)                                  \
  { return REAL(mmap)(addr, sz, prot, flags, fd, off); }
#endif

#ifndef COMMON_INTERCEPTOR_MUNMAP_IMPL
#define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz) \
  { return REAL(munmap)(addr, sz); }
#endif

#ifndef COMMON_INTERCEPTOR_COPY_STRING
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
#endif

#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size)                         \
  COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size);                            \
  uptr copy_length = internal_strnlen(s, size);                               \
  char *new_mem = (char *)WRAP(malloc)(copy_length + 1);                      \
  if (common_flags()->intercept_strndup) {                                    \
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1));       \
  }                                                                           \
  if (new_mem) {                                                              \
    COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);             \
    internal_memcpy(new_mem, s, copy_length);                                 \
    new_mem[copy_length] = '\0';                                              \
  }                                                                           \
  return new_mem;
#endif

#ifndef COMMON_INTERCEPTOR_STRERROR
#define COMMON_INTERCEPTOR_STRERROR() {}
#endif

struct FileMetadata {
  // For open_memstream().
  char **addr;
  SIZE_T *size;
};

struct CommonInterceptorMetadata {
  enum {
    CIMT_INVALID = 0,
    CIMT_FILE
  } type;
  union {
    FileMetadata file;
  };
};

#if SI_POSIX
typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;

static MetadataHashMap *interceptor_metadata_map;

UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
                                          const FileMetadata &file) {
  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
  CHECK(h.created());
  h->type = CommonInterceptorMetadata::CIMT_FILE;
  h->file = file;
}

UNUSED static const FileMetadata *GetInterceptorMetadata(
    __sanitizer_FILE *addr) {
  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
                            /* remove */ false,
                            /* create */ false);
  if (addr && h.exists()) {
    CHECK(!h.created());
    CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
    return &h->file;
  } else {
    return 0;
  }
}

UNUSED static void DeleteInterceptorMetadata(void *addr) {
  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
  CHECK(h.exists());
}
#endif  // SI_POSIX

#if SANITIZER_INTERCEPT_STRLEN
INTERCEPTOR(SIZE_T, strlen, const char *s) {
  // Sometimes strlen is called prior to InitializeCommonInterceptors,
  // in which case the REAL(strlen) typically used in
  // COMMON_INTERCEPTOR_ENTER will fail.  We use internal_strlen here
  // to handle that.
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strlen(s);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
  SIZE_T result = REAL(strlen)(s);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
  return result;
}
#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
#else
#define INIT_STRLEN
#endif

#if SANITIZER_INTERCEPT_STRNLEN
INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
  SIZE_T length = REAL(strnlen)(s, maxlen);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
  return length;
}
#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
#else
#define INIT_STRNLEN
#endif

#if SANITIZER_INTERCEPT_STRNDUP
INTERCEPTOR(char*, strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
#else
#define INIT_STRNDUP
#endif // SANITIZER_INTERCEPT_STRNDUP

#if SANITIZER_INTERCEPT___STRNDUP
INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
#else
#define INIT___STRNDUP
#endif // SANITIZER_INTERCEPT___STRNDUP

#if SANITIZER_INTERCEPT_TEXTDOMAIN
INTERCEPTOR(char*, textdomain, const char *domainname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
  if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
  char *domain = REAL(textdomain)(domainname);
  if (domain) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, internal_strlen(domain) + 1);
  }
  return domain;
}
#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
#else
#define INIT_TEXTDOMAIN
#endif

#if SANITIZER_INTERCEPT_STRCMP || SANITIZER_INTERCEPT_MEMCMP
static inline int CharCmpX(unsigned char c1, unsigned char c2) {
  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
}
#endif

#if SANITIZER_INTERCEPT_STRCMP
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
                              const char *s1, const char *s2, int result)

INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
  unsigned char c1, c2;
  uptr i;
  for (i = 0;; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (c1 != c2 || c1 == '\0') break;
  }
  if (common_flags()->intercept_strcmp) {
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
  }
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
                             s2, result);
  return result;
}

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
                              const char *s1, const char *s2, uptr n,
                              int result)

INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strncmp(s1, s2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
  unsigned char c1 = 0, c2 = 0;
  uptr i;
  for (i = 0; i < size; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (c1 != c2 || c1 == '\0') break;
  }
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
                             s2, size, result);
  return result;
}

#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
#else
#define INIT_STRCMP
#define INIT_STRNCMP
#endif

#if SANITIZER_INTERCEPT_STRCASECMP
static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
  int c1_low = ToLower(c1);
  int c2_low = ToLower(c2);
  return c1_low - c2_low;
}

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
                              const char *s1, const char *s2, int result)

INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
  unsigned char c1 = 0, c2 = 0;
  uptr i;
  for (i = 0;; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
  }
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
                             s1, s2, result);
  return result;
}

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
                              const char *s1, const char *s2, uptr size,
                              int result)

INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
  unsigned char c1 = 0, c2 = 0;
  uptr i;
  for (i = 0; i < size; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
  }
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
                             s1, s2, size, result);
  return result;
}

#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
#else
#define INIT_STRCASECMP
#define INIT_STRNCASECMP
#endif

#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
static inline void StrstrCheck(void *ctx, char *r, const char *s1,
                               const char *s2) {
    uptr len1 = internal_strlen(s1);
    uptr len2 = internal_strlen(s2);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
}
#endif

#if SANITIZER_INTERCEPT_STRSTR

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strstr(s1, s2);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
  char *r = REAL(strstr)(s1, s2);
  if (common_flags()->intercept_strstr)
    StrstrCheck(ctx, r, s1, s2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
                             s2, r);
  return r;
}

#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
#else
#define INIT_STRSTR
#endif

#if SANITIZER_INTERCEPT_STRCASESTR

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
  char *r = REAL(strcasestr)(s1, s2);
  if (common_flags()->intercept_strstr)
    StrstrCheck(ctx, r, s1, s2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
                             s1, s2, r);
  return r;
}

#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
#else
#define INIT_STRCASESTR
#endif

#if SANITIZER_INTERCEPT_STRTOK

INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
  if (!common_flags()->intercept_strtok) {
    return REAL(strtok)(str, delimiters);
  }
  if (common_flags()->strict_string_checks) {
    // If strict_string_checks is enabled, we check the whole first argument
    // string on the first call (strtok saves this string in a static buffer
    // for subsequent calls). We do not need to check strtok's result.
    // As the delimiters can change, we check them every call.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
                                  internal_strlen(delimiters) + 1);
    return REAL(strtok)(str, delimiters);
  } else {
    // However, when strict_string_checks is disabled we cannot check the
    // whole string on the first call. Instead, we check the result string
    // which is guaranteed to be a NULL-terminated substring of the first
    // argument. We also conservatively check one character of str and the
    // delimiters.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
    char *result = REAL(strtok)(str, delimiters);
    if (result != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, internal_strlen(result) + 1);
    } else if (str != nullptr) {
      // No delimiter were found, it's safe to assume that the entire str was
      // scanned.
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
    }
    return result;
  }
}

#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
#else
#define INIT_STRTOK
#endif

#if SANITIZER_INTERCEPT_MEMMEM
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
                              const void *s1, SIZE_T len1, const void *s2,
                              SIZE_T len2, void *result)

INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
            SIZE_T len2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
  void *r = REAL(memmem)(s1, len1, s2, len2);
  if (common_flags()->intercept_memmem) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
  }
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
                             s1, len1, s2, len2, r);
  return r;
}

#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
#else
#define INIT_MEMMEM
#endif  // SANITIZER_INTERCEPT_MEMMEM

#if SANITIZER_INTERCEPT_STRCHR
INTERCEPTOR(char*, strchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
  char *result = REAL(strchr)(s, c);
  if (common_flags()->intercept_strchr) {
    // Keep strlen as macro argument, as macro may ignore it.
    COMMON_INTERCEPTOR_READ_STRING(ctx, s,
      (result ? result - s : internal_strlen(s)) + 1);
  }
  return result;
}
#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
#else
#define INIT_STRCHR
#endif

#if SANITIZER_INTERCEPT_STRCHRNUL
INTERCEPTOR(char*, strchrnul, const char *s, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
  char *result = REAL(strchrnul)(s, c);
  uptr len = result - s + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
  return result;
}
#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
#else
#define INIT_STRCHRNUL
#endif

#if SANITIZER_INTERCEPT_STRRCHR
INTERCEPTOR(char*, strrchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strrchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
  return REAL(strrchr)(s, c);
}
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
#else
#define INIT_STRRCHR
#endif

#if SANITIZER_INTERCEPT_STRSPN
INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
  SIZE_T r = REAL(strspn)(s1, s2);
  if (common_flags()->intercept_strspn) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
  }
  return r;
}

INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
  SIZE_T r = REAL(strcspn)(s1, s2);
  if (common_flags()->intercept_strspn) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
  }
  return r;
}

#define INIT_STRSPN \
  COMMON_INTERCEPT_FUNCTION(strspn); \
  COMMON_INTERCEPT_FUNCTION(strcspn);
#else
#define INIT_STRSPN
#endif

#if SANITIZER_INTERCEPT_STRPBRK
INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
  char *r = REAL(strpbrk)(s1, s2);
  if (common_flags()->intercept_strpbrk) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
        r ? r - s1 + 1 : internal_strlen(s1) + 1);
  }
  return r;
}

#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
#else
#define INIT_STRPBRK
#endif

#if SANITIZER_INTERCEPT_MEMCMP
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
                              const void *s1, const void *s2, uptr n,
                              int result)

// Common code for `memcmp` and `bcmp`.
int MemcmpInterceptorCommon(void *ctx,
                            int (*real_fn)(const void *, const void *, uptr),
                            const void *a1, const void *a2, uptr size) {
  if (common_flags()->intercept_memcmp) {
    if (common_flags()->strict_memcmp) {
      // Check the entire regions even if the first bytes of the buffers are
      // different.
      COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
      COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
      // Fallthrough to REAL(memcmp) below.
    } else {
      unsigned char c1 = 0, c2 = 0;
      const unsigned char *s1 = (const unsigned char*)a1;
      const unsigned char *s2 = (const unsigned char*)a2;
      uptr i;
      for (i = 0; i < size; i++) {
        c1 = s1[i];
        c2 = s2[i];
        if (c1 != c2) break;
      }
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
      int r = CharCmpX(c1, c2);
      CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
                                 a1, a2, size, r);
      return r;
    }
  }
  int result = real_fn(a1, a2, size);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
                             a2, size, result);
  return result;
}

INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
  return MemcmpInterceptorCommon(ctx, REAL(memcmp), a1, a2, size);
}

#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
#else
#define INIT_MEMCMP
#endif

#if SANITIZER_INTERCEPT_BCMP
INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size);
  return MemcmpInterceptorCommon(ctx, REAL(bcmp), a1, a2, size);
}

#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp)
#else
#define INIT_BCMP
#endif

#if SANITIZER_INTERCEPT_MEMCHR
INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memchr(s, c, n);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
#if SANITIZER_WINDOWS
  void *res;
  if (REAL(memchr)) {
    res = REAL(memchr)(s, c, n);
  } else {
    res = internal_memchr(s, c, n);
  }
#else
  void *res = REAL(memchr)(s, c, n);
#endif
  uptr len = res ? (char *)res - (const char *)s + 1 : n;
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
  return res;
}

#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
#else
#define INIT_MEMCHR
#endif

#if SANITIZER_INTERCEPT_MEMRCHR
INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
  return REAL(memrchr)(s, c, n);
}

#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
#else
#define INIT_MEMRCHR
#endif

#if SANITIZER_INTERCEPT_FREXP
INTERCEPTOR(double, frexp, double x, int *exp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
  // Assuming frexp() always writes to |exp|.
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
  double res = REAL(frexp)(x, exp);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
  return res;
}

#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
#else
#define INIT_FREXP
#endif  // SANITIZER_INTERCEPT_FREXP

#if SANITIZER_INTERCEPT_FREXPF_FREXPL
INTERCEPTOR(float, frexpf, float x, int *exp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
  float res = REAL(frexpf)(x, exp);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
  return res;
}

INTERCEPTOR(long double, frexpl, long double x, int *exp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
  long double res = REAL(frexpl)(x, exp);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
  return res;
}

#define INIT_FREXPF_FREXPL           \
  COMMON_INTERCEPT_FUNCTION(frexpf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
#else
#define INIT_FREXPF_FREXPL
#endif  // SANITIZER_INTERCEPT_FREXPF_FREXPL

#if SI_POSIX
static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
                        SIZE_T iovlen, SIZE_T maxlen) {
  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
    maxlen -= sz;
  }
}

static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
                       SIZE_T iovlen, SIZE_T maxlen) {
  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
    maxlen -= sz;
  }
}
#endif

#if SANITIZER_INTERCEPT_READ
INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(read)(fd, ptr, count);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
#else
#define INIT_READ
#endif

#if SANITIZER_INTERCEPT_FREAD
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
  return res;
}
#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
#else
#define INIT_FREAD
#endif

#if SANITIZER_INTERCEPT_PREAD
INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
#else
#define INIT_PREAD
#endif

#if SANITIZER_INTERCEPT_PREAD64
INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
#else
#define INIT_PREAD64
#endif

#if SANITIZER_INTERCEPT_READV
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
                        int iovcnt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
#else
#define INIT_READV
#endif

#if SANITIZER_INTERCEPT_PREADV
INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
#else
#define INIT_PREADV
#endif

#if SANITIZER_INTERCEPT_PREADV64
INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
#else
#define INIT_PREADV64
#endif

#if SANITIZER_INTERCEPT_WRITE
INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(write)(fd, ptr, count);
  // FIXME: this check should be _before_ the call to REAL(write), not after
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
#else
#define INIT_WRITE
#endif

#if SANITIZER_INTERCEPT_FWRITE
INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
  SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
  return res;
}
#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
#else
#define INIT_FWRITE
#endif

#if SANITIZER_INTERCEPT_PWRITE
INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
#else
#define INIT_PWRITE
#endif

#if SANITIZER_INTERCEPT_PWRITE64
INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
#else
#define INIT_PWRITE64
#endif

#if SANITIZER_INTERCEPT_WRITEV
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
                        int iovcnt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
  return res;
}
#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
#else
#define INIT_WRITEV
#endif

#if SANITIZER_INTERCEPT_PWRITEV
INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
  return res;
}
#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
#else
#define INIT_PWRITEV
#endif

#if SANITIZER_INTERCEPT_PWRITEV64
INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
  return res;
}
#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
#else
#define INIT_PWRITEV64
#endif

#if SANITIZER_INTERCEPT_FGETS
INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgets, s, size, file);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(fgets)(s, size, file);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
  return res;
}
#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
#else
#define INIT_FGETS
#endif

#if SANITIZER_INTERCEPT_FPUTS
INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
  if (!SANITIZER_APPLE || s) {  // `fputs(NULL, file)` is supported on Darwin.
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
  }
  return REAL(fputs)(s, file);
}
#define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs)
#else
#define INIT_FPUTS
#endif

#if SANITIZER_INTERCEPT_PUTS
INTERCEPTOR(int, puts, char *s) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
  if (!SANITIZER_APPLE || s) {  // `puts(NULL)` is supported on Darwin.
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
  }
  return REAL(puts)(s);
}
#define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts)
#else
#define INIT_PUTS
#endif

#if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
            unsigned long arg4, unsigned long arg5) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
  static const int PR_SET_NAME = 15;
  static const int PR_SET_VMA = 0x53564d41;
  static const int PR_SCHED_CORE = 62;
  static const int PR_SCHED_CORE_GET = 0;
  if (option == PR_SET_VMA && arg2 == 0UL) {
    char *name = (char *)arg5;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  }
  int res = REAL(prctl)(option, arg2, arg3, arg4, arg5);
  if (option == PR_SET_NAME) {
    char buff[16];
    internal_strncpy(buff, (char *)arg2, 15);
    buff[15] = 0;
    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
  } else if (res != -1 && option == PR_SCHED_CORE && arg2 == PR_SCHED_CORE_GET) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));
  }
  return res;
}
#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
#else
#define INIT_PRCTL
#endif  // SANITIZER_INTERCEPT_PRCTL

#if SANITIZER_INTERCEPT_TIME
INTERCEPTOR(unsigned long, time, unsigned long *t) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
  unsigned long local_t;
  unsigned long res = REAL(time)(&local_t);
  if (t && res != (unsigned long)-1) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
    *t = local_t;
  }
  return res;
}
#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
#else
#define INIT_TIME
#endif  // SANITIZER_INTERCEPT_TIME

#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
#if !SANITIZER_SOLARIS
  if (tm->tm_zone) {
    // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
    // can point to shared memory and tsan would report a data race.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
                                        internal_strlen(tm->tm_zone) + 1);
  }
#endif
}
INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
  __sanitizer_tm *res = REAL(localtime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    unpoison_tm(ctx, res);
  }
  return res;
}
INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
  __sanitizer_tm *res = REAL(localtime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    unpoison_tm(ctx, res);
  }
  return res;
}
INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
  __sanitizer_tm *res = REAL(gmtime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    unpoison_tm(ctx, res);
  }
  return res;
}
INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
  __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    unpoison_tm(ctx, res);
  }
  return res;
}
INTERCEPTOR(char *, ctime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(ctime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(ctime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(asctime)(tm);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(asctime_r)(tm, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  }
  return res;
}
INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
  long res = REAL(mktime)(tm);
  if (res != -1) unpoison_tm(ctx, tm);
  return res;
}
#define INIT_LOCALTIME_AND_FRIENDS        \
  COMMON_INTERCEPT_FUNCTION(localtime);   \
  COMMON_INTERCEPT_FUNCTION(localtime_r); \
  COMMON_INTERCEPT_FUNCTION(gmtime);      \
  COMMON_INTERCEPT_FUNCTION(gmtime_r);    \
  COMMON_INTERCEPT_FUNCTION(ctime);       \
  COMMON_INTERCEPT_FUNCTION(ctime_r);     \
  COMMON_INTERCEPT_FUNCTION(asctime);     \
  COMMON_INTERCEPT_FUNCTION(asctime_r);   \
  COMMON_INTERCEPT_FUNCTION(mktime);
#else
#define INIT_LOCALTIME_AND_FRIENDS
#endif  // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS

#if SANITIZER_INTERCEPT_STRPTIME
INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
  if (format)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(strptime)(s, format, tm);
  COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
  if (res && tm) {
    // Do not call unpoison_tm here, because strptime does not, in fact,
    // initialize the entire struct tm. For example, tm_zone pointer is left
    // uninitialized.
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
  }
  return res;
}
#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
#else
#define INIT_STRPTIME
#endif

#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
#include "sanitizer_common_interceptors_format.inc"

#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...)                              \
  {                                                                            \
    void *ctx;                                                                 \
    va_list ap;                                                                \
    va_start(ap, format);                                                      \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap);                     \
    int res = WRAP(vname)(__VA_ARGS__, ap);                                    \
    va_end(ap);                                                                \
    return res;                                                                \
  }

#endif

#if SANITIZER_INTERCEPT_SCANF

#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
    va_list aq;                                                                \
    va_copy(aq, ap);                                                           \
    int res = REAL(vname)(__VA_ARGS__);                                        \
    if (res > 0)                                                               \
      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
    va_end(aq);                                                                \
    return res;                                                                \
  }

INTERCEPTOR(int, vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)

INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)

INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)

#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)

INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
            va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)

INTERCEPTOR(int, __isoc23_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vscanf, false, format, ap)

INTERCEPTOR(int, __isoc23_vsscanf, const char *str, const char *format,
            va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc23_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vfscanf, false, stream, format, ap)
#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF

INTERCEPTOR(int, scanf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)

INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)

INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)

#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)

INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)

INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)

INTERCEPTOR(int, __isoc23_scanf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_scanf, __isoc23_vscanf, format)

INTERCEPTOR(int, __isoc23_fscanf, void *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_fscanf, __isoc23_vfscanf, stream, format)

INTERCEPTOR(int, __isoc23_sscanf, const char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_sscanf, __isoc23_vsscanf, str, format)
#endif

#endif

#if SANITIZER_INTERCEPT_SCANF
#define INIT_SCANF                    \
  COMMON_INTERCEPT_FUNCTION_LDBL(scanf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(sscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
#else
#define INIT_SCANF
#endif

#if SANITIZER_INTERCEPT_ISOC99_SCANF
#define INIT_ISOC99_SCANF                      \
  COMMON_INTERCEPT_FUNCTION(__isoc99_scanf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); \
  COMMON_INTERCEPT_FUNCTION(__isoc23_scanf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc23_sscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc23_fscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc23_vscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc23_vsscanf); \
  COMMON_INTERCEPT_FUNCTION(__isoc23_vfscanf);
#else
#define INIT_ISOC99_SCANF
#endif

#if SANITIZER_INTERCEPT_PRINTF

#define VPRINTF_INTERCEPTOR_ENTER(vname, ...)                                  \
  void *ctx;                                                                   \
  COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                           \
  va_list aq;                                                                  \
  va_copy(aq, ap);

#define VPRINTF_INTERCEPTOR_RETURN()                                           \
  va_end(aq);

#define VPRINTF_INTERCEPTOR_IMPL(vname, ...)                                   \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__);                             \
    if (common_flags()->check_printf)                                          \
      printf_common(ctx, format, aq);                                          \
    int res = REAL(vname)(__VA_ARGS__);                                        \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

// FIXME: under ASan the REAL() call below may write to freed memory and
// corrupt its metadata. See
// https://github.com/google/sanitizers/issues/321.
#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...)                             \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__)                         \
    if (common_flags()->check_printf) {                                        \
      printf_common(ctx, format, aq);                                          \
    }                                                                          \
    int res = REAL(vname)(str, __VA_ARGS__);                                   \
    if (res >= 0) {                                                            \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1);                       \
    }                                                                          \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

// FIXME: under ASan the REAL() call below may write to freed memory and
// corrupt its metadata. See
// https://github.com/google/sanitizers/issues/321.
#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...)                      \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__)                   \
    if (common_flags()->check_printf) {                                        \
      printf_common(ctx, format, aq);                                          \
    }                                                                          \
    int res = REAL(vname)(str, size, __VA_ARGS__);                             \
    if (res >= 0) {                                                            \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1)));  \
    }                                                                          \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

// FIXME: under ASan the REAL() call below may write to freed memory and
// corrupt its metadata. See
// https://github.com/google/sanitizers/issues/321.
#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...)                           \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__)                        \
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *));                 \
    if (common_flags()->check_printf) {                                        \
      printf_common(ctx, format, aq);                                          \
    }                                                                          \
    int res = REAL(vname)(strp, __VA_ARGS__);                                  \
    if (res >= 0) {                                                            \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1);                     \
    }                                                                          \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

INTERCEPTOR(int, vprintf, const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)

INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
            va_list ap)
VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)

INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
            va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)

#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag,
            SIZE_T size_to, const char *format, va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
#endif

#if SANITIZER_INTERCEPT_PRINTF_L
INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
            const char *format, va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)

INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
#endif  // SANITIZER_INTERCEPT_PRINTF_L

INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)

#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
            const char *format, va_list ap)
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
#endif

INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)

#if SANITIZER_INTERCEPT_ISOC99_PRINTF
INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)

INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
            const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)

INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
            va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)

INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
            va_list ap)
VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
                          ap)

#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF

INTERCEPTOR(int, printf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)

INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)

#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
#endif

INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)

#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
#endif

INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)

#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
            SIZE_T size_to, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
#endif

INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)

#if SANITIZER_INTERCEPT_ISOC99_PRINTF
INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)

INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
            ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)

INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)

INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
                        format)

#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF

#endif  // SANITIZER_INTERCEPT_PRINTF

#if SANITIZER_INTERCEPT_PRINTF
#define INIT_PRINTF                     \
  COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
#else
#define INIT_PRINTF
#endif

#if SANITIZER_INTERCEPT___PRINTF_CHK
#define INIT___PRINTF_CHK                     \
  COMMON_INTERCEPT_FUNCTION(__sprintf_chk);   \
  COMMON_INTERCEPT_FUNCTION(__snprintf_chk);  \
  COMMON_INTERCEPT_FUNCTION(__vsprintf_chk);  \
  COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \
  COMMON_INTERCEPT_FUNCTION(__fprintf_chk);
#else
#define INIT___PRINTF_CHK
#endif

#if SANITIZER_INTERCEPT_PRINTF_L
#define INIT_PRINTF_L                     \
  COMMON_INTERCEPT_FUNCTION(snprintf_l);  \
  COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
#else
#define INIT_PRINTF_L
#endif

#if SANITIZER_INTERCEPT_ISOC99_PRINTF
#define INIT_ISOC99_PRINTF                       \
  COMMON_INTERCEPT_FUNCTION(__isoc99_printf);    \
  COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
#else
#define INIT_ISOC99_PRINTF
#endif

#if SANITIZER_INTERCEPT_IOCTL
#include "sanitizer_common_interceptors_ioctl.inc"
#include "sanitizer_interceptors_ioctl_netbsd.inc"
INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
  // We need a frame pointer, because we call into ioctl_common_[pre|post] which
  // can trigger a report and we need to be able to unwind through this
  // function.  On Mac in debug mode we might not have a frame pointer, because
  // ioctl_common_[pre|post] doesn't get inlined here.
  ENABLE_FRAME_POINTER;

  void *ctx;
  va_list ap;
  va_start(ap, request);
  void *arg = va_arg(ap, void *);
  va_end(ap);
  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);

  CHECK(ioctl_initialized);

  // Note: TSan does not use common flags, and they are zero-initialized.
  // This effectively disables ioctl handling in TSan.
  if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);

  // Although request is unsigned long, the rest of the interceptor uses it
  // as just "unsigned" to save space, because we know that all values fit in
  // "unsigned" - they are compile-time constants.

  const ioctl_desc *desc = ioctl_lookup(request);
  ioctl_desc decoded_desc;
  if (!desc) {
    VPrintf(2, "Decoding unknown ioctl 0x%lx\n", request);
    if (!ioctl_decode(request, &decoded_desc))
      Printf("WARNING: failed decoding unknown ioctl 0x%lx\n", request);
    else
      desc = &decoded_desc;
  }

  if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
  int res = REAL(ioctl)(d, request, arg);
  // FIXME: some ioctls have different return values for success and failure.
  if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
  return res;
}
#define INIT_IOCTL \
  ioctl_init();    \
  COMMON_INTERCEPT_FUNCTION(ioctl);
#else
#define INIT_IOCTL
#endif

#if SANITIZER_POSIX
UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
  if (pwd) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
    if (pwd->pw_name)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
                                     internal_strlen(pwd->pw_name) + 1);
    if (pwd->pw_passwd)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
                                     internal_strlen(pwd->pw_passwd) + 1);
#if !SANITIZER_ANDROID
    if (pwd->pw_gecos)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
                                     internal_strlen(pwd->pw_gecos) + 1);
#endif
#if SANITIZER_APPLE || SANITIZER_FREEBSD || SANITIZER_NETBSD
    if (pwd->pw_class)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
                                     internal_strlen(pwd->pw_class) + 1);
#endif
    if (pwd->pw_dir)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
                                     internal_strlen(pwd->pw_dir) + 1);
    if (pwd->pw_shell)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
                                     internal_strlen(pwd->pw_shell) + 1);
  }
}

UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
  if (grp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
    if (grp->gr_name)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
                                     internal_strlen(grp->gr_name) + 1);
    if (grp->gr_passwd)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
                                     internal_strlen(grp->gr_passwd) + 1);
    char **p = grp->gr_mem;
    for (; *p; ++p) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
    }
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
                                   (p - grp->gr_mem + 1) * sizeof(*p));
  }
}
#endif  // SANITIZER_POSIX

#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  __sanitizer_passwd *res = REAL(getpwnam)(name);
  unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
  __sanitizer_passwd *res = REAL(getpwuid)(uid);
  unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  __sanitizer_group *res = REAL(getgrnam)(name);
  unpoison_group(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
  __sanitizer_group *res = REAL(getgrgid)(gid);
  unpoison_group(ctx, res);
  return res;
}
#define INIT_GETPWNAM_AND_FRIENDS      \
  COMMON_INTERCEPT_FUNCTION(getpwnam); \
  COMMON_INTERCEPT_FUNCTION(getpwuid); \
  COMMON_INTERCEPT_FUNCTION(getgrnam); \
  COMMON_INTERCEPT_FUNCTION(getgrgid);
#else
#define INIT_GETPWNAM_AND_FRIENDS
#endif

#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
            char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
  if (!res && result)
    unpoison_passwd(ctx, *result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
            SIZE_T buflen, __sanitizer_passwd **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
  if (!res && result)
    unpoison_passwd(ctx, *result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
            char *buf, SIZE_T buflen, __sanitizer_group **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
  if (!res && result)
    unpoison_group(ctx, *result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
            SIZE_T buflen, __sanitizer_group **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
  if (!res && result)
    unpoison_group(ctx, *result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
#define INIT_GETPWNAM_R_AND_FRIENDS      \
  COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
  COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
  COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
  COMMON_INTERCEPT_FUNCTION(getgrgid_r);
#else
#define INIT_GETPWNAM_R_AND_FRIENDS
#endif

#if SANITIZER_INTERCEPT_GETPWENT
INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
  __sanitizer_passwd *res = REAL(getpwent)(dummy);
  unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
  __sanitizer_group *res = REAL(getgrent)(dummy);
  unpoison_group(ctx, res);
  return res;
}
#define INIT_GETPWENT                  \
  COMMON_INTERCEPT_FUNCTION(getpwent); \
  COMMON_INTERCEPT_FUNCTION(getgrent);
#else
#define INIT_GETPWENT
#endif

#if SANITIZER_INTERCEPT_FGETPWENT
INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
  __sanitizer_passwd *res = REAL(fgetpwent)(fp);
  unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
  __sanitizer_group *res = REAL(fgetgrent)(fp);
  unpoison_group(ctx, res);
  return res;
}
#define INIT_FGETPWENT                  \
  COMMON_INTERCEPT_FUNCTION(fgetpwent); \
  COMMON_INTERCEPT_FUNCTION(fgetgrent);
#else
#define INIT_FGETPWENT
#endif

#if SANITIZER_INTERCEPT_GETPWENT_R
INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
  if (!res && pwbufp)
    unpoison_passwd(ctx, *pwbufp);
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
            __sanitizer_group **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
  if (!res && pwbufp)
    unpoison_group(ctx, *pwbufp);
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
#define INIT_GETPWENT_R                   \
  COMMON_INTERCEPT_FUNCTION(getpwent_r);  \
  COMMON_INTERCEPT_FUNCTION(getgrent_r);
#else
#define INIT_GETPWENT_R
#endif

#if SANITIZER_INTERCEPT_FGETPWENT_R
INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
  if (!res && pwbufp)
    unpoison_passwd(ctx, *pwbufp);
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
#define INIT_FGETPWENT_R                  \
  COMMON_INTERCEPT_FUNCTION(fgetpwent_r);
#else
#define INIT_FGETPWENT_R
#endif

#if SANITIZER_INTERCEPT_FGETGRENT_R
INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_group **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
  if (!res && pwbufp)
    unpoison_group(ctx, *pwbufp);
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
#define INIT_FGETGRENT_R                  \
  COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
#else
#define INIT_FGETGRENT_R
#endif

#if SANITIZER_INTERCEPT_SETPWENT
// The only thing these interceptors do is disable any nested interceptors.
// These functions may open nss modules and call uninstrumented functions from
// them, and we don't want things like strlen() to trigger.
INTERCEPTOR(void, setpwent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
  REAL(setpwent)(dummy);
}
INTERCEPTOR(void, endpwent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
  REAL(endpwent)(dummy);
}
INTERCEPTOR(void, setgrent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
  REAL(setgrent)(dummy);
}
INTERCEPTOR(void, endgrent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
  REAL(endgrent)(dummy);
}
#define INIT_SETPWENT                  \
  COMMON_INTERCEPT_FUNCTION(setpwent); \
  COMMON_INTERCEPT_FUNCTION(endpwent); \
  COMMON_INTERCEPT_FUNCTION(setgrent); \
  COMMON_INTERCEPT_FUNCTION(endgrent);
#else
#define INIT_SETPWENT
#endif

#if SANITIZER_INTERCEPT_CLOCK_GETTIME
INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(clock_getres)(clk_id, tp);
  if (!res && tp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
  }
  return res;
}
INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(clock_gettime)(clk_id, tp);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
  }
  return res;
}
#if SANITIZER_GLIBC
namespace __sanitizer {
extern "C" {
int real_clock_gettime(u32 clk_id, void *tp) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_clock_gettime(clk_id, tp);
  return REAL(clock_gettime)(clk_id, tp);
}
}  // extern "C"
}  // namespace __sanitizer
#endif
INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
  return REAL(clock_settime)(clk_id, tp);
}
#define INIT_CLOCK_GETTIME                  \
  COMMON_INTERCEPT_FUNCTION(clock_getres);  \
  COMMON_INTERCEPT_FUNCTION(clock_gettime); \
  COMMON_INTERCEPT_FUNCTION(clock_settime);
#else
#define INIT_CLOCK_GETTIME
#endif

#if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
            __sanitizer_clockid_t *clockid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid);
  int res = REAL(clock_getcpuclockid)(pid, clockid);
  if (!res && clockid) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
  }
  return res;
}

INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
            __sanitizer_clockid_t *clockid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getcpuclockid, thread, clockid);
  int res = REAL(pthread_getcpuclockid)(thread, clockid);
  if (!res && clockid) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
  }
  return res;
}

#define INIT_CLOCK_GETCPUCLOCKID                   \
  COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);  \
  COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
#else
#define INIT_CLOCK_GETCPUCLOCKID
#endif

#if SANITIZER_INTERCEPT_GETITIMER
INTERCEPTOR(int, getitimer, int which, void *curr_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getitimer)(which, curr_value);
  if (!res && curr_value) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
  }
  return res;
}
INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
  if (new_value) {
    // itimerval can contain padding that may be legitimately uninitialized
    const struct __sanitizer_itimerval *nv =
        (const struct __sanitizer_itimerval *)new_value;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec,
                                  sizeof(__sanitizer_time_t));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec,
                                  sizeof(__sanitizer_suseconds_t));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec,
                                  sizeof(__sanitizer_time_t));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec,
                                  sizeof(__sanitizer_suseconds_t));
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(setitimer)(which, new_value, old_value);
  if (!res && old_value) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
  }
  return res;
}
#define INIT_GETITIMER                  \
  COMMON_INTERCEPT_FUNCTION(getitimer); \
  COMMON_INTERCEPT_FUNCTION(setitimer);
#else
#define INIT_GETITIMER
#endif

#if SANITIZER_INTERCEPT_GLOB
static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
  // +1 for NULL pointer at the end.
  if (pglob->gl_pathv)
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
    char *p = pglob->gl_pathv[i];
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
  }
}

#if SANITIZER_SOLARIS
INTERCEPTOR(int, glob, const char *pattern, int flags,
            int (*errfunc)(const char *epath, int eerrno),
            __sanitizer_glob_t *pglob) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
  int res = REAL(glob)(pattern, flags, errfunc, pglob);
  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
  return res;
}
#else
static THREADLOCAL __sanitizer_glob_t *pglob_copy;

static void wrapped_gl_closedir(void *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  pglob_copy->gl_closedir(dir);
}

static void *wrapped_gl_readdir(void *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  return pglob_copy->gl_readdir(dir);
}

static void *wrapped_gl_opendir(const char *s) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
  return pglob_copy->gl_opendir(s);
}

static int wrapped_gl_lstat(const char *s, void *st) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
  return pglob_copy->gl_lstat(s, st);
}

static int wrapped_gl_stat(const char *s, void *st) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
  return pglob_copy->gl_stat(s, st);
}

static const __sanitizer_glob_t kGlobCopy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};

INTERCEPTOR(int, glob, const char *pattern, int flags,
            int (*errfunc)(const char *epath, int eerrno),
            __sanitizer_glob_t *pglob) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
    pglob_copy = &glob_copy;
  }
  int res = REAL(glob)(pattern, flags, errfunc, pglob);
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
  }
  pglob_copy = 0;
  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
  return res;
}
#endif  // SANITIZER_SOLARIS
#define INIT_GLOB                  \
  COMMON_INTERCEPT_FUNCTION(glob);
#else  // SANITIZER_INTERCEPT_GLOB
#define INIT_GLOB
#endif  // SANITIZER_INTERCEPT_GLOB

#if SANITIZER_INTERCEPT_GLOB64
INTERCEPTOR(int, glob64, const char *pattern, int flags,
            int (*errfunc)(const char *epath, int eerrno),
            __sanitizer_glob_t *pglob) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
    pglob_copy = &glob_copy;
  }
  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
  }
  pglob_copy = 0;
  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
  return res;
}
#define INIT_GLOB64                \
  COMMON_INTERCEPT_FUNCTION(glob64);
#else  // SANITIZER_INTERCEPT_GLOB64
#define INIT_GLOB64
#endif  // SANITIZER_INTERCEPT_GLOB64

#if SANITIZER_INTERCEPT___B64_TO
INTERCEPTOR(int, __b64_ntop, unsigned char const *src, SIZE_T srclength,
            char *target, SIZE_T targsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __b64_ntop, src, srclength, target, targsize);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclength);
  int res = REAL(__b64_ntop)(src, srclength, target, targsize);
  if (res >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res + 1);
  return res;
}
INTERCEPTOR(int, __b64_pton, char const *src, char *target, SIZE_T targsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __b64_pton, src, target, targsize);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int res = REAL(__b64_pton)(src, target, targsize);
  if (res >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res);
  return res;
}
#define INIT___B64_TO                      \
    COMMON_INTERCEPT_FUNCTION(__b64_ntop); \
    COMMON_INTERCEPT_FUNCTION(__b64_pton);
#else  // SANITIZER_INTERCEPT___B64_TO
#define INIT___B64_TO
#endif  // SANITIZER_INTERCEPT___B64_TO

#if SANITIZER_INTERCEPT_DN_COMP_EXPAND
#  if __GLIBC_PREREQ(2, 34)
// Changed with https://sourceware.org/git/?p=glibc.git;h=640bbdf
#    define DN_COMP_INTERCEPTOR_NAME dn_comp
#    define DN_EXPAND_INTERCEPTOR_NAME dn_expand
#  else
#    define DN_COMP_INTERCEPTOR_NAME __dn_comp
#    define DN_EXPAND_INTERCEPTOR_NAME __dn_expand
#  endif
INTERCEPTOR(int, DN_COMP_INTERCEPTOR_NAME, unsigned char *exp_dn,
            unsigned char *comp_dn, int length, unsigned char **dnptrs,
            unsigned char **lastdnptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, DN_COMP_INTERCEPTOR_NAME, exp_dn, comp_dn,
                           length, dnptrs, lastdnptr);
  int res = REAL(DN_COMP_INTERCEPTOR_NAME)(exp_dn, comp_dn, length, dnptrs,
                                           lastdnptr);
  if (res >= 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, comp_dn, res);
    if (dnptrs && lastdnptr) {
      unsigned char **p = dnptrs;
      for (; p != lastdnptr && *p; ++p)
        ;
      if (p != lastdnptr)
        ++p;
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dnptrs, (p - dnptrs) * sizeof(*p));
    }
  }
  return res;
}
INTERCEPTOR(int, DN_EXPAND_INTERCEPTOR_NAME, unsigned char const *base,
            unsigned char const *end, unsigned char const *src, char *dest,
            int space) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, DN_EXPAND_INTERCEPTOR_NAME, base, end, src,
                           dest, space);
  // TODO: add read check if __dn_comp intercept added
  int res = REAL(DN_EXPAND_INTERCEPTOR_NAME)(base, end, src, dest, space);
  if (res >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, internal_strlen(dest) + 1);
  return res;
}
#  define INIT_DN_COMP_EXPAND                            \
    COMMON_INTERCEPT_FUNCTION(DN_COMP_INTERCEPTOR_NAME); \
    COMMON_INTERCEPT_FUNCTION(DN_EXPAND_INTERCEPTOR_NAME);
#else  // SANITIZER_INTERCEPT_DN_COMP_EXPAND
#  define INIT_DN_COMP_EXPAND
#endif  // SANITIZER_INTERCEPT_DN_COMP_EXPAND

#if SANITIZER_INTERCEPT_POSIX_SPAWN

template <class RealSpawnPtr>
static int PosixSpawnImpl(void *ctx, RealSpawnPtr *real_posix_spawn, pid_t *pid,
                          const char *file_or_path, const void *file_actions,
                          const void *attrp, char *const argv[],
                          char *const envp[]) {
  COMMON_INTERCEPTOR_READ_RANGE(ctx, file_or_path,
                                internal_strlen(file_or_path) + 1);
  if (argv) {
    for (char *const *s = argv; ; ++s) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
      if (!*s) break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
    }
  }
  if (envp) {
    for (char *const *s = envp; ; ++s) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
      if (!*s) break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
    }
  }
  int res =
      real_posix_spawn(pid, file_or_path, file_actions, attrp, argv, envp);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pid, sizeof(*pid));
  return res;
}
INTERCEPTOR(int, posix_spawn, pid_t *pid, const char *path,
            const void *file_actions, const void *attrp, char *const argv[],
            char *const envp[]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, posix_spawn, pid, path, file_actions, attrp,
                           argv, envp);
  return PosixSpawnImpl(ctx, REAL(posix_spawn), pid, path, file_actions, attrp,
                        argv, envp);
}
INTERCEPTOR(int, posix_spawnp, pid_t *pid, const char *file,
            const void *file_actions, const void *attrp, char *const argv[],
            char *const envp[]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, posix_spawnp, pid, file, file_actions, attrp,
                           argv, envp);
  return PosixSpawnImpl(ctx, REAL(posix_spawnp), pid, file, file_actions, attrp,
                        argv, envp);
}
#  define INIT_POSIX_SPAWN                  \
    COMMON_INTERCEPT_FUNCTION(posix_spawn); \
    COMMON_INTERCEPT_FUNCTION(posix_spawnp);
#else  // SANITIZER_INTERCEPT_POSIX_SPAWN
#  define INIT_POSIX_SPAWN
#endif  // SANITIZER_INTERCEPT_POSIX_SPAWN

#if SANITIZER_INTERCEPT_WAIT
// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
// details.
INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(wait)(status);
  if (res != -1 && status)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
  return res;
}
// On FreeBSD id_t is always 64-bit wide.
#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
                        int options) {
#else
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
                        int options) {
#endif
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(waitid)(idtype, id, infop, options);
  if (res != -1 && infop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
  return res;
}
INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(waitpid)(pid, status, options);
  if (res != -1 && status)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
  return res;
}
INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(wait3)(status, options, rusage);
  if (res != -1) {
    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
  }
  return res;
}
#if SANITIZER_ANDROID
INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(__wait4)(pid, status, options, rusage);
  if (res != -1) {
    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
  }
  return res;
}
#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
#else
INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(wait4)(pid, status, options, rusage);
  if (res != -1) {
    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
  }
  return res;
}
#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
#endif  // SANITIZER_ANDROID
#define INIT_WAIT                     \
  COMMON_INTERCEPT_FUNCTION(wait);    \
  COMMON_INTERCEPT_FUNCTION(waitid);  \
  COMMON_INTERCEPT_FUNCTION(waitpid); \
  COMMON_INTERCEPT_FUNCTION(wait3);
#else
#define INIT_WAIT
#define INIT_WAIT4
#endif

#if SANITIZER_INTERCEPT_INET
INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
  uptr sz = __sanitizer_in_addr_sz(af);
  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
  // FIXME: figure out read size based on the address family.
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(inet_ntop)(af, src, dst, size);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}
INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
  COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
  // FIXME: figure out read size based on the address family.
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(inet_pton)(af, src, dst);
  if (res == 1) {
    uptr sz = __sanitizer_in_addr_sz(af);
    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
  }
  return res;
}
#define INIT_INET                       \
  COMMON_INTERCEPT_FUNCTION(inet_ntop); \
  COMMON_INTERCEPT_FUNCTION(inet_pton);
#else
#define INIT_INET
#endif

#if SANITIZER_INTERCEPT_INET
INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, internal_strlen(cp) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(inet_aton)(cp, dst);
  if (res != 0) {
    uptr sz = __sanitizer_in_addr_sz(af_inet);
    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
  }
  return res;
}
#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
#else
#define INIT_INET_ATON
#endif

#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_getschedparam)(thread, policy, param);
  if (res == 0) {
    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
  }
  return res;
}
#define INIT_PTHREAD_GETSCHEDPARAM \
  COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
#else
#define INIT_PTHREAD_GETSCHEDPARAM
#endif

#if SANITIZER_INTERCEPT_GETADDRINFO
INTERCEPTOR(int, getaddrinfo, char *node, char *service,
            struct __sanitizer_addrinfo *hints,
            struct __sanitizer_addrinfo **out) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, internal_strlen(node) + 1);
  if (service)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, internal_strlen(service) + 1);
  if (hints)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getaddrinfo)(node, service, hints, out);
  if (res == 0 && out) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
    struct __sanitizer_addrinfo *p = *out;
    while (p) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
      if (p->ai_addr)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
      if (p->ai_canonname)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
                                       internal_strlen(p->ai_canonname) + 1);
      p = p->ai_next;
    }
  }
  return res;
}
#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
#else
#define INIT_GETADDRINFO
#endif

#if SANITIZER_INTERCEPT_GETNAMEINFO
INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
            unsigned hostlen, char *serv, unsigned servlen, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
                           serv, servlen, flags);
  // FIXME: consider adding READ_RANGE(sockaddr, salen)
  // There is padding in in_addr that may make this too noisy
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res =
      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
  if (res == 0) {
    if (host && hostlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, internal_strlen(host) + 1);
    if (serv && servlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, internal_strlen(serv) + 1);
  }
  return res;
}
#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
#else
#define INIT_GETNAMEINFO
#endif

#if SANITIZER_INTERCEPT_GETSOCKNAME
INTERCEPTOR(int, getsockname, int sock_fd, void *addr, unsigned *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
  unsigned addr_sz;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addr_sz = *addrlen;
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getsockname)(sock_fd, addr, addrlen);
  if (!res && addr && addrlen) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
  }
  return res;
}
#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
#else
#define INIT_GETSOCKNAME
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
  if (h->h_name)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, internal_strlen(h->h_name) + 1);
  char **p = h->h_aliases;
  while (*p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
    ++p;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(
      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
  p = h->h_addr_list;
  while (*p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
    ++p;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(
      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
}
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
  if (res) write_hostent(ctx, res);
  return res;
}

INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
            int type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
  if (res) write_hostent(ctx, res);
  return res;
}

INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
  struct __sanitizer_hostent *res = REAL(gethostent)(fake);
  if (res) write_hostent(ctx, res);
  return res;
}
#define INIT_GETHOSTBYNAME                  \
  COMMON_INTERCEPT_FUNCTION(gethostent);    \
  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
  COMMON_INTERCEPT_FUNCTION(gethostbyname);
#else
#define INIT_GETHOSTBYNAME
#endif  // SANITIZER_INTERCEPT_GETHOSTBYNAME

#if SANITIZER_INTERCEPT_GETHOSTBYNAME2
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
  if (res) write_hostent(ctx, res);
  return res;
}
#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2);
#else
#define INIT_GETHOSTBYNAME2
#endif  // SANITIZER_INTERCEPT_GETHOSTBYNAME2

#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
            int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
                           h_errnop);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
#else
#define INIT_GETHOSTBYNAME_R
#endif

#if SANITIZER_INTERCEPT_GETHOSTENT_R
INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
                           h_errnop);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTENT_R                  \
  COMMON_INTERCEPT_FUNCTION(gethostent_r);
#else
#define INIT_GETHOSTENT_R
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
            __sanitizer_hostent **result, int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
                           buflen, result, h_errnop);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
                                  h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTBYADDR_R                  \
  COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
#else
#define INIT_GETHOSTBYADDR_R
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
            __sanitizer_hostent **result, int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
                           result, h_errnop);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res =
      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTBYNAME2_R                  \
  COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
#else
#define INIT_GETHOSTBYNAME2_R
#endif

#if SANITIZER_INTERCEPT_GETSOCKOPT
INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
            int *optlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
                           optlen);
  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
  if (res == 0)
    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
  return res;
}
#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
#else
#define INIT_GETSOCKOPT
#endif

#if SANITIZER_INTERCEPT_ACCEPT
INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
  unsigned addrlen0 = 0;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addrlen0 = *addrlen;
  }
  int fd2 = REAL(accept)(fd, addr, addrlen);
  if (fd2 >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
    if (addr && addrlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
  }
  return fd2;
}
#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
#else
#define INIT_ACCEPT
#endif

#if SANITIZER_INTERCEPT_ACCEPT4
INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
  unsigned addrlen0 = 0;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addrlen0 = *addrlen;
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
  if (fd2 >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
    if (addr && addrlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
  }
  return fd2;
}
#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
#else
#define INIT_ACCEPT4
#endif

#if SANITIZER_INTERCEPT_PACCEPT
INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen,
            __sanitizer_sigset_t *set, int f) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, paccept, fd, addr, addrlen, set, f);
  unsigned addrlen0 = 0;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addrlen0 = *addrlen;
  }
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  int fd2 = REAL(paccept)(fd, addr, addrlen, set, f);
  if (fd2 >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
    if (addr && addrlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
  }
  return fd2;
}
#define INIT_PACCEPT COMMON_INTERCEPT_FUNCTION(paccept);
#else
#define INIT_PACCEPT
#endif

#if SANITIZER_INTERCEPT_MODF
INTERCEPTOR(double, modf, double x, double *iptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  double res = REAL(modf)(x, iptr);
  if (iptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
  }
  return res;
}
INTERCEPTOR(float, modff, float x, float *iptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  float res = REAL(modff)(x, iptr);
  if (iptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
  }
  return res;
}
INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  long double res = REAL(modfl)(x, iptr);
  if (iptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
  }
  return res;
}
#define INIT_MODF                   \
  COMMON_INTERCEPT_FUNCTION(modf);  \
  COMMON_INTERCEPT_FUNCTION(modff); \
  COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
#else
#define INIT_MODF
#endif

#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                         SSIZE_T maxlen) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
  if (msg->msg_name && msg->msg_namelen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
  if (msg->msg_iov && msg->msg_iovlen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
  if (msg->msg_control && msg->msg_controllen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
}
#endif

#if SANITIZER_INTERCEPT_RECVMSG
INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
            int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
  if (res >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
    if (msg) {
      write_msghdr(ctx, msg, res);
      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
    }
  }
  return res;
}
#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
#else
#define INIT_RECVMSG
#endif

#if SANITIZER_INTERCEPT_RECVMMSG
INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
            unsigned int vlen, int flags, void *timeout) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
  int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
  if (res >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
    for (int i = 0; i < res; ++i) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
                                     sizeof(msgvec[i].msg_len));
      write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
    }
  }
  return res;
}
#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
#else
#define INIT_RECVMMSG
#endif

#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
  const unsigned kCmsgDataOffset =
      RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));

  char *p = (char *)control;
  char *const control_end = p + controllen;
  while (true) {
    if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
    __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));

    if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;

    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
                                  sizeof(cmsg->cmsg_level));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
                                  sizeof(cmsg->cmsg_type));

    if (cmsg->cmsg_len > kCmsgDataOffset) {
      char *data = p + kCmsgDataOffset;
      unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
      if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
    }

    p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
  }
}

static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                        SSIZE_T maxlen) {
#define R(f) \
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
  R(name);
  R(namelen);
  R(iov);
  R(iovlen);
  R(control);
  R(controllen);
  R(flags);
#undef R
  if (msg->msg_name && msg->msg_namelen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
  if (msg->msg_iov && msg->msg_iovlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
                                  sizeof(*msg->msg_iov) * msg->msg_iovlen);
  read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
  if (msg->msg_control && msg->msg_controllen)
    read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
}
#endif

#if SANITIZER_INTERCEPT_SENDMSG
INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
            int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
  if (common_flags()->intercept_send && res >= 0 && msg)
    read_msghdr(ctx, msg, res);
  return res;
}
#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
#else
#define INIT_SENDMSG
#endif

#if SANITIZER_INTERCEPT_SENDMMSG
INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
            unsigned vlen, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
  if (res >= 0 && msgvec) {
    for (int i = 0; i < res; ++i) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
                                     sizeof(msgvec[i].msg_len));
      if (common_flags()->intercept_send)
        read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
    }
  }
  return res;
}
#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
#else
#define INIT_SENDMMSG
#endif

#if SANITIZER_INTERCEPT_SYSMSG
INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz,
            int msgflg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg);
  if (msgp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz);
  int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
  return res;
}

INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz,
            long msgtyp, int msgflg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
  SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
  if (len != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len);
  return len;
}

#define INIT_SYSMSG                  \
  COMMON_INTERCEPT_FUNCTION(msgsnd); \
  COMMON_INTERCEPT_FUNCTION(msgrcv);
#else
#define INIT_SYSMSG
#endif

#if SANITIZER_INTERCEPT_GETPEERNAME
INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
  unsigned addr_sz;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addr_sz = *addrlen;
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getpeername)(sockfd, addr, addrlen);
  if (!res && addr && addrlen) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
  }
  return res;
}
#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
#else
#define INIT_GETPEERNAME
#endif

#if SANITIZER_INTERCEPT_SYSINFO
INTERCEPTOR(int, sysinfo, void *info) {
  void *ctx;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
  int res = REAL(sysinfo)(info);
  if (!res && info)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
  return res;
}
#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
#else
#define INIT_SYSINFO
#endif

#if SANITIZER_INTERCEPT_READDIR
INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  __sanitizer_dirent *res = REAL(opendir)(path);
  if (res)
    COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
  return res;
}

INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  __sanitizer_dirent *res = REAL(readdir)(dirp);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer_dirsiz(res));
  return res;
}

INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
            __sanitizer_dirent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(readdir_r)(dirp, entry, result);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (*result)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, __sanitizer_dirsiz(*result));
  }
  return res;
}

#define INIT_READDIR                  \
  COMMON_INTERCEPT_FUNCTION(opendir); \
  COMMON_INTERCEPT_FUNCTION(readdir); \
  COMMON_INTERCEPT_FUNCTION(readdir_r);
#else
#define INIT_READDIR
#endif

#if SANITIZER_INTERCEPT_READDIR64
INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer_dirsiz(res));
  return res;
}

INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
            __sanitizer_dirent64 **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(readdir64_r)(dirp, entry, result);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (*result)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, __sanitizer_dirsiz(*result));
  }
  return res;
}
#define INIT_READDIR64                  \
  COMMON_INTERCEPT_FUNCTION(readdir64); \
  COMMON_INTERCEPT_FUNCTION(readdir64_r);
#else
#define INIT_READDIR64
#endif

#if SANITIZER_INTERCEPT_PTRACE
INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
  __sanitizer_iovec local_iovec;

  if (data) {
    if (request == ptrace_setregs) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
    } else if (request == ptrace_setfpregs) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
    } else if (request == ptrace_setfpxregs) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
    } else if (request == ptrace_setvfpregs) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
    } else if (request == ptrace_setsiginfo) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);

    // Some kernel might zero the iovec::iov_base in case of invalid
    // write access.  In this case copy the invalid address for further
    // inspection.
    } else if (request == ptrace_setregset || request == ptrace_getregset) {
      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
      local_iovec = *iovec;
      if (request == ptrace_setregset)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
    }
  }

  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  uptr res = REAL(ptrace)(request, pid, addr, data);

  if (!res && data) {
    // Note that PEEK* requests assign different meaning to the return value.
    // This function does not handle them (nor does it need to).
    if (request == ptrace_getregs) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
    } else if (request == ptrace_getfpregs) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
    } else if (request == ptrace_getfpxregs) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
    } else if (request == ptrace_getvfpregs) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
    } else if (request == ptrace_getsiginfo) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
    } else if (request == ptrace_geteventmsg) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
    } else if (request == ptrace_getregset) {
      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
                                     local_iovec.iov_len);
    }
  }
  return res;
}

#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
#else
#define INIT_PTRACE
#endif

#if SANITIZER_INTERCEPT_SETLOCALE
static void unpoison_ctype_arrays(void *ctx) {
#if SANITIZER_NETBSD
  // These arrays contain 256 regular elements in unsigned char range + 1 EOF
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short));
#endif
}

INTERCEPTOR(char *, setlocale, int category, char *locale) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
  if (locale)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, internal_strlen(locale) + 1);
  char *res = REAL(setlocale)(category, locale);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
    unpoison_ctype_arrays(ctx);
  }
  return res;
}

#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
#else
#define INIT_SETLOCALE
#endif

#if SANITIZER_INTERCEPT_GETCWD
INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(getcwd)(buf, size);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}
#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
#else
#define INIT_GETCWD
#endif

#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
INTERCEPTOR(char *, get_current_dir_name, int fake) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(get_current_dir_name)(fake);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}

#define INIT_GET_CURRENT_DIR_NAME \
  COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
#else
#define INIT_GET_CURRENT_DIR_NAME
#endif

UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
  CHECK(endptr);
  if (nptr == *endptr) {
    // No digits were found at strtol call, we need to find out the last
    // symbol accessed by strtoll on our own.
    // We get this symbol by skipping leading blanks and optional +/- sign.
    while (IsSpace(*nptr)) nptr++;
    if (*nptr == '+' || *nptr == '-') nptr++;
    *endptr = const_cast<char *>(nptr);
  }
  CHECK(*endptr >= nptr);
}

UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
                             char **endptr, char *real_endptr, int base) {
  if (endptr) {
    *endptr = real_endptr;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
  }
  // If base has unsupported value, strtol can exit with EINVAL
  // without reading any characters. So do additional checks only
  // if base is valid.
  bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
  if (is_valid_base) {
    FixRealStrtolEndptr(nptr, &real_endptr);
  }
  COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
                                 (real_endptr - nptr) + 1 : 0);
}

#if SANITIZER_INTERCEPT_STRTOIMAX
template <typename Fn>
static ALWAYS_INLINE auto StrtoimaxImpl(void *ctx, Fn real, const char *nptr,
                                        char **endptr, int base)
    -> decltype(real(nullptr, nullptr, 0)) {
  char *real_endptr;
  auto res = real(nptr, &real_endptr, base);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  return res;
}

INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(strtoimax), nptr, endptr, base);
}
INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(strtoumax), nptr, endptr, base);
}

#define INIT_STRTOIMAX                  \
  COMMON_INTERCEPT_FUNCTION(strtoimax); \
  COMMON_INTERCEPT_FUNCTION(strtoumax);
#else
#define INIT_STRTOIMAX
#endif

#if SANITIZER_INTERCEPT_STRTOIMAX && SANITIZER_GLIBC
INTERCEPTOR(INTMAX_T, __isoc23_strtoimax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoimax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(__isoc23_strtoimax), nptr, endptr, base);
}
INTERCEPTOR(UINTMAX_T, __isoc23_strtoumax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoumax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(__isoc23_strtoumax), nptr, endptr, base);
}

#  define INIT_STRTOIMAX_C23                       \
    COMMON_INTERCEPT_FUNCTION(__isoc23_strtoimax); \
    COMMON_INTERCEPT_FUNCTION(__isoc23_strtoumax);
#else
#  define INIT_STRTOIMAX_C23
#endif

#if SANITIZER_INTERCEPT_MBSTOWCS
INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(mbstowcs)(dest, src, len);
  if (res != (SIZE_T) - 1 && dest) {
    SIZE_T write_cnt = res + (res < len);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
  }
  return res;
}

INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
            void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
  if (res != (SIZE_T)(-1) && dest && src) {
    // This function, and several others, may or may not write the terminating
    // \0 character. They write it iff they clear *src.
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
  }
  return res;
}

#define INIT_MBSTOWCS                  \
  COMMON_INTERCEPT_FUNCTION(mbstowcs); \
  COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
#else
#define INIT_MBSTOWCS
#endif

#if SANITIZER_INTERCEPT_MBSNRTOWCS
INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
            SIZE_T len, void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
  if (src) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
  }
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
  if (res != (SIZE_T)(-1) && dest && src) {
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
  }
  return res;
}

#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
#else
#define INIT_MBSNRTOWCS
#endif

#if SANITIZER_INTERCEPT_WCSTOMBS
INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(wcstombs)(dest, src, len);
  if (res != (SIZE_T) - 1 && dest) {
    SIZE_T write_cnt = res + (res < len);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
            void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
  if (res != (SIZE_T) - 1 && dest && src) {
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

#define INIT_WCSTOMBS                  \
  COMMON_INTERCEPT_FUNCTION(wcstombs); \
  COMMON_INTERCEPT_FUNCTION(wcsrtombs);
#else
#define INIT_WCSTOMBS
#endif

#if SANITIZER_INTERCEPT_WCSNRTOMBS
INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
            SIZE_T len, void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
  if (src) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
  }
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
  if (res != ((SIZE_T)-1) && dest && src) {
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
#else
#define INIT_WCSNRTOMBS
#endif


#if SANITIZER_INTERCEPT_WCRTOMB
INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);

  if (!dest)
    return REAL(wcrtomb)(dest, src, ps);

  char local_dest[32];
  SIZE_T res = REAL(wcrtomb)(local_dest, src, ps);
  if (res != ((SIZE_T)-1)) {
    CHECK_LE(res, sizeof(local_dest));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
    REAL(memcpy)(dest, local_dest, res);
  }
  return res;
}

#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
#else
#define INIT_WCRTOMB
#endif

#if SANITIZER_INTERCEPT_WCTOMB
INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src);
  if (!dest)
    return REAL(wctomb)(dest, src);

  char local_dest[32];
  int res = REAL(wctomb)(local_dest, src);
  if (res != -1) {
    CHECK_LE(res, sizeof(local_dest));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
    REAL(memcpy)(dest, local_dest, res);
  }
  return res;
}

#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb);
#else
#define INIT_WCTOMB
#endif

#if SANITIZER_INTERCEPT_TCGETATTR
INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(tcgetattr)(fd, termios_p);
  if (!res && termios_p)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
  return res;
}

#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
#else
#define INIT_TCGETATTR
#endif

#if SANITIZER_INTERCEPT_REALPATH
INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);

  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
  // version of a versioned symbol. For realpath(), this gives us something
  // (called __old_realpath) that does not handle NULL in the second argument.
  // Handle it as part of the interceptor.
  char *allocated_path = nullptr;
  if (!resolved_path)
    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);

  char *res = REAL(realpath)(path, resolved_path);
  if (allocated_path && !res)
    WRAP(free)(allocated_path);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}
#  define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
#else
#define INIT_REALPATH
#endif

#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  char *res = REAL(canonicalize_file_name)(path);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}
#define INIT_CANONICALIZE_FILE_NAME \
  COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
#else
#define INIT_CANONICALIZE_FILE_NAME
#endif

#if SANITIZER_INTERCEPT_CONFSTR
INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(confstr)(name, buf, len);
  if (buf && res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
  return res;
}
#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
#else
#define INIT_CONFSTR
#endif

#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
  return res;
}
#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
#else
#define INIT_SCHED_GETAFFINITY
#endif

#if SANITIZER_INTERCEPT_SCHED_GETPARAM
INTERCEPTOR(int, sched_getparam, int pid, void *param) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
  int res = REAL(sched_getparam)(pid, param);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
  return res;
}
#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
#else
#define INIT_SCHED_GETPARAM
#endif

#if SANITIZER_INTERCEPT_STRERROR
INTERCEPTOR(char *, strerror, int errnum) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
  COMMON_INTERCEPTOR_STRERROR();
  char *res = REAL(strerror)(errnum);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
#else
#define INIT_STRERROR
#endif

#if SANITIZER_INTERCEPT_STRERROR_R
// There are 2 versions of strerror_r:
//  * POSIX version returns 0 on success, negative error code on failure,
//    writes message to buf.
//  * GNU version returns message pointer, which points to either buf or some
//    static storage.
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
    SANITIZER_APPLE || SANITIZER_ANDROID || SANITIZER_NETBSD ||                 \
    SANITIZER_FREEBSD
// POSIX version. Spec is not clear on whether buf is NULL-terminated.
// At least on OSX, buf contents are valid even when the call fails.
INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(strerror_r)(errnum, buf, buflen);

  SIZE_T sz = internal_strnlen(buf, buflen);
  if (sz < buflen) ++sz;
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  return res;
}
#else
// GNU version.
INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(strerror_r)(errnum, buf, buflen);
  if (res == buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  else
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
       //SANITIZER_APPLE
#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
#else
#define INIT_STRERROR_R
#endif

#if SANITIZER_INTERCEPT_XPG_STRERROR_R
INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
  // This version always returns a null-terminated string.
  if (buf && buflen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
  return res;
}
#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
#else
#define INIT_XPG_STRERROR_R
#endif

#if SANITIZER_INTERCEPT_SCANDIR
typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
                                const struct __sanitizer_dirent **);

static THREADLOCAL scandir_filter_f scandir_filter;
static THREADLOCAL scandir_compar_f scandir_compar;

static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, __sanitizer_dirsiz(dir));
  return scandir_filter(dir);
}

static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
                                  const struct __sanitizer_dirent **b) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, __sanitizer_dirsiz(*a));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, __sanitizer_dirsiz(*b));
  return scandir_compar(a, b);
}

INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
            scandir_filter_f filter, scandir_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
  scandir_filter = filter;
  scandir_compar = compar;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(scandir)(dirp, namelist,
                          filter ? wrapped_scandir_filter : nullptr,
                          compar ? wrapped_scandir_compar : nullptr);
  scandir_filter = nullptr;
  scandir_compar = nullptr;
  if (namelist && res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
    for (int i = 0; i < res; ++i)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
                                     __sanitizer_dirsiz((*namelist)[i]));
  }
  return res;
}
#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
#else
#define INIT_SCANDIR
#endif

#if SANITIZER_INTERCEPT_SCANDIR64
typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
                                  const struct __sanitizer_dirent64 **);

static THREADLOCAL scandir64_filter_f scandir64_filter;
static THREADLOCAL scandir64_compar_f scandir64_compar;

static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, __sanitizer_dirsiz(dir));
  return scandir64_filter(dir);
}

static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
                                    const struct __sanitizer_dirent64 **b) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, __sanitizer_dirsiz(*a));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, __sanitizer_dirsiz(*b));
  return scandir64_compar(a, b);
}

INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
            scandir64_filter_f filter, scandir64_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
  scandir64_filter = filter;
  scandir64_compar = compar;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res =
      REAL(scandir64)(dirp, namelist,
                      filter ? wrapped_scandir64_filter : nullptr,
                      compar ? wrapped_scandir64_compar : nullptr);
  scandir64_filter = nullptr;
  scandir64_compar = nullptr;
  if (namelist && res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
    for (int i = 0; i < res; ++i)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
                                     __sanitizer_dirsiz((*namelist)[i]));
  }
  return res;
}
#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
#else
#define INIT_SCANDIR64
#endif

#if SANITIZER_INTERCEPT_GETGROUPS
INTERCEPTOR(int, getgroups, int size, u32 *lst) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getgroups)(size, lst);
  if (res >= 0 && lst && size > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
  return res;
}
#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
#else
#define INIT_GETGROUPS
#endif

#if SANITIZER_INTERCEPT_POLL
static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
                        __sanitizer_nfds_t nfds) {
  for (unsigned i = 0; i < nfds; ++i) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
  }
}

static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
                         __sanitizer_nfds_t nfds) {
  for (unsigned i = 0; i < nfds; ++i)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
                                   sizeof(fds[i].revents));
}

INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
            int timeout) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
  if (fds && nfds) read_pollfd(ctx, fds, nfds);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
  if (fds && nfds) write_pollfd(ctx, fds, nfds);
  return res;
}
#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
#else
#define INIT_POLL
#endif

#if SANITIZER_INTERCEPT_PPOLL
INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
            void *timeout_ts, __sanitizer_sigset_t *sigmask) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
  if (fds && nfds) read_pollfd(ctx, fds, nfds);
  if (timeout_ts)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
  if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
  int res =
      COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
  if (fds && nfds) write_pollfd(ctx, fds, nfds);
  return res;
}
#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
#else
#define INIT_PPOLL
#endif

#if SANITIZER_INTERCEPT_WORDEXP
INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(wordexp)(s, p, flags);
  if (!res && p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
    uptr we_wordc =
        ((flags & wordexp_wrde_dooffs) ? p->we_offs : 0) + p->we_wordc;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
                                   sizeof(*p->we_wordv) * (we_wordc + 1));
    for (uptr i = 0; i < we_wordc; ++i) {
      char *w = p->we_wordv[i];
      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1);
    }
  }
  return res;
}
#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
#else
#define INIT_WORDEXP
#endif

#if SANITIZER_INTERCEPT_SIGWAIT
INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwait)(set, sig);
  if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
  return res;
}
#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
#else
#define INIT_SIGWAIT
#endif

#if SANITIZER_INTERCEPT_SIGWAITINFO
INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwaitinfo)(set, info);
  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
  return res;
}
#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
#else
#define INIT_SIGWAITINFO
#endif

#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
            void *timeout) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigtimedwait)(set, info, timeout);
  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
  return res;
}
#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
#else
#define INIT_SIGTIMEDWAIT
#endif

#if SANITIZER_INTERCEPT_SIGSETOPS
INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(sigemptyset)(set);
  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
  return res;
}

INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(sigfillset)(set);
  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
  return res;
}
#define INIT_SIGSETOPS                    \
  COMMON_INTERCEPT_FUNCTION(sigemptyset); \
  COMMON_INTERCEPT_FUNCTION(sigfillset);
#else
#define INIT_SIGSETOPS
#endif

#if SANITIZER_INTERCEPT_SIGSET_LOGICOPS
INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst,
            __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigandset, dst, src1, src2);
  if (src1)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
  if (src2)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
  int res = REAL(sigandset)(dst, src1, src2);
  if (!res && dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
  return res;
}

INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst,
            __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigorset, dst, src1, src2);
  if (src1)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
  if (src2)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
  int res = REAL(sigorset)(dst, src1, src2);
  if (!res && dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
  return res;
}
#define INIT_SIGSET_LOGICOPS                    \
  COMMON_INTERCEPT_FUNCTION(sigandset);   \
  COMMON_INTERCEPT_FUNCTION(sigorset);
#else
#define INIT_SIGSET_LOGICOPS
#endif

#if SANITIZER_INTERCEPT_SIGPENDING
INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(sigpending)(set);
  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
  return res;
}
#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
#else
#define INIT_SIGPENDING
#endif

#if SANITIZER_INTERCEPT_SIGPROCMASK
INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
            __sanitizer_sigset_t *oldset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(sigprocmask)(how, set, oldset);
  if (!res && oldset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
  return res;
}
#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
#else
#define INIT_SIGPROCMASK
#endif

#if SANITIZER_INTERCEPT_PTHREAD_SIGMASK
INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
            __sanitizer_sigset_t *oldset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_sigmask)(how, set, oldset);
  if (!res && oldset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
  return res;
}
#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask);
#else
#define INIT_PTHREAD_SIGMASK
#endif

#if SANITIZER_INTERCEPT_BACKTRACE
INTERCEPTOR(int, backtrace, void **buffer, int size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
  // 'buffer' might be freed memory, hence it is unsafe to directly call
  // REAL(backtrace)(buffer, size). Instead, we use our own known-good
  // scratch buffer.
  void **scratch = (void**)InternalAlloc(sizeof(void*) * size);
  int res = REAL(backtrace)(scratch, size);
  if (res && buffer) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
    internal_memcpy(buffer, scratch, res * sizeof(*buffer));
  }
  InternalFree(scratch);
  return res;
}

INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
  if (buffer && size)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
  // The COMMON_INTERCEPTOR_READ_RANGE above ensures that 'buffer' is
  // valid for reading.
  char **res = REAL(backtrace_symbols)(buffer, size);
  if (res && size) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
    for (int i = 0; i < size; ++i)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], internal_strlen(res[i]) + 1);
  }
  return res;
}
#define INIT_BACKTRACE                  \
  COMMON_INTERCEPT_FUNCTION(backtrace); \
  COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
#else
#define INIT_BACKTRACE
#endif

#if SANITIZER_INTERCEPT__EXIT
INTERCEPTOR(void, _exit, int status) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
  COMMON_INTERCEPTOR_USER_CALLBACK_START();
  int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
  COMMON_INTERCEPTOR_USER_CALLBACK_END();
  if (status == 0) status = status1;
  REAL(_exit)(status);
}
#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
#else
#define INIT__EXIT
#endif

#if SANITIZER_INTERCEPT___LIBC_MUTEX
INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate)
ALIAS(WRAP(pthread_setcancelstate));

#define INIT___LIBC_THR_SETCANCELSTATE \
  COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate)
#else
#define INIT___LIBC_THR_SETCANCELSTATE
#endif

#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
  if (mnt->mnt_fsname)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
                                   internal_strlen(mnt->mnt_fsname) + 1);
  if (mnt->mnt_dir)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
                                   internal_strlen(mnt->mnt_dir) + 1);
  if (mnt->mnt_type)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
                                   internal_strlen(mnt->mnt_type) + 1);
  if (mnt->mnt_opts)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
                                   internal_strlen(mnt->mnt_opts) + 1);
}
#endif

#if SANITIZER_INTERCEPT_GETMNTENT
INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
  __sanitizer_mntent *res = REAL(getmntent)(fp);
  if (res) write_mntent(ctx, res);
  return res;
}
#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
#else
#define INIT_GETMNTENT
#endif

#if SANITIZER_INTERCEPT_GETMNTENT_R
INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
            __sanitizer_mntent *mntbuf, char *buf, int buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
  __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
  if (res) write_mntent(ctx, res);
  return res;
}
#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
#else
#define INIT_GETMNTENT_R
#endif

#if SANITIZER_INTERCEPT_STATFS
INTERCEPTOR(int, statfs, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(statfs)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
  return res;
}
INTERCEPTOR(int, fstatfs, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(fstatfs)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
  return res;
}
#define INIT_STATFS                  \
  COMMON_INTERCEPT_FUNCTION(statfs); \
  COMMON_INTERCEPT_FUNCTION(fstatfs);
#else
#define INIT_STATFS
#endif

#if SANITIZER_INTERCEPT_STATFS64
INTERCEPTOR(int, statfs64, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(statfs64)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
  return res;
}
INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(fstatfs64)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
  return res;
}
#define INIT_STATFS64                  \
  COMMON_INTERCEPT_FUNCTION(statfs64); \
  COMMON_INTERCEPT_FUNCTION(fstatfs64);
#else
#define INIT_STATFS64
#endif

#if SANITIZER_INTERCEPT_STATVFS
INTERCEPTOR(int, statvfs, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(statvfs)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(fstatvfs)(fd, buf);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
    if (fd >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
#define INIT_STATVFS                  \
  COMMON_INTERCEPT_FUNCTION(statvfs); \
  COMMON_INTERCEPT_FUNCTION(fstatvfs);
#else
#define INIT_STATVFS
#endif

#if SANITIZER_INTERCEPT_STATVFS64
INTERCEPTOR(int, statvfs64, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(statvfs64)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(fstatvfs64)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
  return res;
}
#define INIT_STATVFS64                  \
  COMMON_INTERCEPT_FUNCTION(statvfs64); \
  COMMON_INTERCEPT_FUNCTION(fstatvfs64);
#else
#define INIT_STATVFS64
#endif

#if SANITIZER_INTERCEPT_INITGROUPS
INTERCEPTOR(int, initgroups, char *user, u32 group) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, internal_strlen(user) + 1);
  int res = REAL(initgroups)(user, group);
  return res;
}
#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
#else
#define INIT_INITGROUPS
#endif

#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
  char *res = REAL(ether_ntoa)(addr);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
  __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
  return res;
}
#define INIT_ETHER_NTOA_ATON             \
  COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
  COMMON_INTERCEPT_FUNCTION(ether_aton);
#else
#define INIT_ETHER_NTOA_ATON
#endif

#if SANITIZER_INTERCEPT_ETHER_HOST
INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(ether_ntohost)(hostname, addr);
  if (!res && hostname)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
  return res;
}
INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
  if (hostname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(ether_hostton)(hostname, addr);
  if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
  return res;
}
INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
            char *hostname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, internal_strlen(line) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(ether_line)(line, addr, hostname);
  if (!res) {
    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
    if (hostname)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
  }
  return res;
}
#define INIT_ETHER_HOST                     \
  COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
  COMMON_INTERCEPT_FUNCTION(ether_hostton); \
  COMMON_INTERCEPT_FUNCTION(ether_line);
#else
#define INIT_ETHER_HOST
#endif

#if SANITIZER_INTERCEPT_ETHER_R
INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(ether_ntoa_r)(addr, buf);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
            __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
  return res;
}
#define INIT_ETHER_R                       \
  COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
  COMMON_INTERCEPT_FUNCTION(ether_aton_r);
#else
#define INIT_ETHER_R
#endif

#if SANITIZER_INTERCEPT_SHMCTL
INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(shmctl)(shmid, cmd, buf);
  if (res >= 0) {
    unsigned sz = 0;
    if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
      sz = sizeof(__sanitizer_shmid_ds);
    else if (cmd == shmctl_ipc_info)
      sz = struct_shminfo_sz;
    else if (cmd == shmctl_shm_info)
      sz = struct_shm_info_sz;
    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  }
  return res;
}
#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
#else
#define INIT_SHMCTL
#endif

#if SANITIZER_INTERCEPT_RANDOM_R
INTERCEPTOR(int, random_r, void *buf, u32 *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(random_r)(buf, result);
  if (!res && result)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
#else
#define INIT_RANDOM_R
#endif

// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET ||              \
    SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED ||        \
    SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
    SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET ||         \
    SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET ||        \
    SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET ||          \
    SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz)            \
  INTERCEPTOR(int, fn, void *attr, void *r) {                  \
    void *ctx;                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r);                \
    int res = REAL(fn)(attr, r);                               \
    if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
    return res;                                                \
  }
#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_attr_getstack)(attr, addr, size);
  if (!res) {
    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
    if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
  }
  return res;
}

// We may need to call the real pthread_attr_getstack from the run-time
// in sanitizer_common, but we don't want to include the interception headers
// there. So, just define this function here.
namespace __sanitizer {
extern "C" {
int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
  return REAL(pthread_attr_getstack)(attr, addr, size);
}
}  // extern "C"
}  // namespace __sanitizer

#define INIT_PTHREAD_ATTR_GET                             \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize);   \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope);       \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize);   \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
#else
#define INIT_PTHREAD_ATTR_GET
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED
INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))

#define INIT_PTHREAD_ATTR_GET_SCHED                      \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy);
#else
#define INIT_PTHREAD_ATTR_GET_SCHED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))

#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
#else
#define INIT_PTHREAD_ATTR_GETINHERITSCHED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
            void *cpuset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
                           cpuset);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
  if (!res && cpusetsize && cpuset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
  return res;
}

#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
#else
#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP
INTERCEPTOR(int, pthread_getaffinity_np, void *attr, SIZE_T cpusetsize,
            void *cpuset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getaffinity_np, attr, cpusetsize,
                           cpuset);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_getaffinity_np)(attr, cpusetsize, cpuset);
  if (!res && cpusetsize && cpuset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
  return res;
}

#define INIT_PTHREAD_GETAFFINITY_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np);
#else
#define INIT_PTHREAD_GETAFFINITY_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
#else
#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
#else
#define INIT_PTHREAD_MUTEXATTR_GETTYPE
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
#else
#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
#else
#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
#else
#define INIT_PTHREAD_MUTEXATTR_GETROBUST
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
#else
#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
#else
#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
#else
#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
#define INIT_PTHREAD_CONDATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
#else
#define INIT_PTHREAD_CONDATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
#define INIT_PTHREAD_CONDATTR_GETCLOCK \
  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
#else
#define INIT_PTHREAD_CONDATTR_GETCLOCK
#endif

#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
#else
#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_TMPNAM
INTERCEPTOR(char *, tmpnam, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
  char *res = REAL(tmpnam)(s);
  if (res) {
    if (s)
      // FIXME: under ASan the call below may write to freed memory and corrupt
      // its metadata. See
      // https://github.com/google/sanitizers/issues/321.
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
    else
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  }
  return res;
}
#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
#else
#define INIT_TMPNAM
#endif

#if SANITIZER_INTERCEPT_TMPNAM_R
INTERCEPTOR(char *, tmpnam_r, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(tmpnam_r)(s);
  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
  return res;
}
#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
#else
#define INIT_TMPNAM_R
#endif

#if SANITIZER_INTERCEPT_PTSNAME
INTERCEPTOR(char *, ptsname, int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd);
  char *res = REAL(ptsname)(fd);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname);
#else
#define INIT_PTSNAME
#endif

#if SANITIZER_INTERCEPT_PTSNAME_R
INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize);
  int res = REAL(ptsname_r)(fd, name, namesize);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
  return res;
}
#define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r);
#else
#define INIT_PTSNAME_R
#endif

#if SANITIZER_INTERCEPT_TTYNAME
INTERCEPTOR(char *, ttyname, int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
  char *res = REAL(ttyname)(fd);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
#else
#define INIT_TTYNAME
#endif

#if SANITIZER_INTERCEPT_TTYNAME_R
INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
  int res = REAL(ttyname_r)(fd, name, namesize);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
  return res;
}
#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
#else
#define INIT_TTYNAME_R
#endif

#if SANITIZER_INTERCEPT_TEMPNAM
INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, internal_strlen(dir) + 1);
  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, internal_strlen(pfx) + 1);
  char *res = REAL(tempnam)(dir, pfx);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
#else
#define INIT_TEMPNAM
#endif

#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
  return REAL(pthread_setname_np)(thread, name);
}
#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) {
  void *ctx;
  char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
  internal_snprintf(newname, sizeof(newname), name, arg);
  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
  return REAL(pthread_setname_np)(thread, name, arg);
}
#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
#else
#define INIT_PTHREAD_SETNAME_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP
INTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len);
  int res = REAL(pthread_getname_np)(thread, name, len);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1);
  return res;
}
#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
#else
#define INIT_PTHREAD_GETNAME_NP
#endif

#if SANITIZER_INTERCEPT_SINCOS
INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  REAL(sincos)(x, sin, cos);
  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
}
INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  REAL(sincosf)(x, sin, cos);
  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
}
INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  REAL(sincosl)(x, sin, cos);
  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
}
#define INIT_SINCOS                   \
  COMMON_INTERCEPT_FUNCTION(sincos);  \
  COMMON_INTERCEPT_FUNCTION(sincosf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
#else
#define INIT_SINCOS
#endif

#if SANITIZER_INTERCEPT_REMQUO
INTERCEPTOR(double, remquo, double x, double y, int *quo) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  double res = REAL(remquo)(x, y, quo);
  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
  return res;
}
INTERCEPTOR(float, remquof, float x, float y, int *quo) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  float res = REAL(remquof)(x, y, quo);
  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
  return res;
}
#define INIT_REMQUO                   \
  COMMON_INTERCEPT_FUNCTION(remquo);  \
  COMMON_INTERCEPT_FUNCTION(remquof);
#else
#define INIT_REMQUO
#endif

#if SANITIZER_INTERCEPT_REMQUOL
INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  long double res = REAL(remquol)(x, y, quo);
  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
  return res;
}
#define INIT_REMQUOL                  \
  COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
#else
#define INIT_REMQUOL
#endif

#if SANITIZER_INTERCEPT_LGAMMA
extern int signgam;
INTERCEPTOR(double, lgamma, double x) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
  double res = REAL(lgamma)(x);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
  return res;
}
INTERCEPTOR(float, lgammaf, float x) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
  float res = REAL(lgammaf)(x);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
  return res;
}
#define INIT_LGAMMA                   \
  COMMON_INTERCEPT_FUNCTION(lgamma);  \
  COMMON_INTERCEPT_FUNCTION(lgammaf);
#else
#define INIT_LGAMMA
#endif

#if SANITIZER_INTERCEPT_LGAMMAL
INTERCEPTOR(long double, lgammal, long double x) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
  long double res = REAL(lgammal)(x);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
  return res;
}
#define INIT_LGAMMAL                  \
  COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
#else
#define INIT_LGAMMAL
#endif

#if SANITIZER_INTERCEPT_LGAMMA_R
INTERCEPTOR(double, lgamma_r, double x, int *signp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  double res = REAL(lgamma_r)(x, signp);
  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
  return res;
}
INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  float res = REAL(lgammaf_r)(x, signp);
  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
  return res;
}
#define INIT_LGAMMA_R                   \
  COMMON_INTERCEPT_FUNCTION(lgamma_r);  \
  COMMON_INTERCEPT_FUNCTION(lgammaf_r);
#else
#define INIT_LGAMMA_R
#endif

#if SANITIZER_INTERCEPT_LGAMMAL_R
INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  long double res = REAL(lgammal_r)(x, signp);
  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
  return res;
}
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
#else
#define INIT_LGAMMAL_R
#endif

#if SANITIZER_INTERCEPT_DRAND48_R
INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(drand48_r)(buffer, result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(lrand48_r)(buffer, result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
#define INIT_DRAND48_R                  \
  COMMON_INTERCEPT_FUNCTION(drand48_r); \
  COMMON_INTERCEPT_FUNCTION(lrand48_r);
#else
#define INIT_DRAND48_R
#endif

#if SANITIZER_INTERCEPT_RAND_R
INTERCEPTOR(int, rand_r, unsigned *seedp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
  return REAL(rand_r)(seedp);
}
#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
#else
#define INIT_RAND_R
#endif

#if SANITIZER_INTERCEPT_GETLINE
INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(getline)(lineptr, n, stream);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
  }
  return res;
}

// FIXME: under ASan the call below may write to freed memory and corrupt its
// metadata. See
// https://github.com/google/sanitizers/issues/321.
#define GETDELIM_INTERCEPTOR_IMPL(vname)                                       \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream);           \
    SSIZE_T res = REAL(vname)(lineptr, n, delim, stream);                      \
    if (res > 0) {                                                             \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));          \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));                      \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);                  \
    }                                                                          \
    return res;                                                                \
  }

INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
            void *stream)
GETDELIM_INTERCEPTOR_IMPL(__getdelim)

// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
// with its own body.
INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
            void *stream)
GETDELIM_INTERCEPTOR_IMPL(getdelim)

#define INIT_GETLINE                     \
  COMMON_INTERCEPT_FUNCTION(getline);    \
  COMMON_INTERCEPT_FUNCTION(__getdelim); \
  COMMON_INTERCEPT_FUNCTION(getdelim);
#else
#define INIT_GETLINE
#endif

#if SANITIZER_INTERCEPT_ICONV
INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
            char **outbuf, SIZE_T *outbytesleft) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
                           outbytesleft);
  if (inbytesleft)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
  if (inbuf && inbytesleft)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
  if (outbytesleft)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
  void *outbuf_orig = outbuf ? *outbuf : nullptr;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
  if (outbuf && *outbuf > outbuf_orig) {
    SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
  }
  return res;
}
#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
#else
#define INIT_ICONV
#endif

#if SANITIZER_INTERCEPT_TIMES
INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  __sanitizer_clock_t res = REAL(times)(tms);
  if (res != (__sanitizer_clock_t)-1 && tms)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
  return res;
}
#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
#else
#define INIT_TIMES
#endif

#if SANITIZER_S390 && \
    (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
#endif

#if SANITIZER_INTERCEPT_TLS_GET_ADDR
#if !SANITIZER_S390
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
// If you see any crashes around this functions, there are 2 known issues with
// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
// 2. It can be called recursively if sanitizer code uses __tls_get_addr
// to access thread local variables (it should not happen normally,
// because sanitizers use initial-exec tls model).
INTERCEPTOR(void *, __tls_get_addr, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
  void *res = REAL(__tls_get_addr)(arg);
  uptr tls_begin, tls_end;
  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
  if (dtv) {
    // New DTLS block has been allocated.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
  }
  return res;
}
#if SANITIZER_PPC
// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
// mostly the same semantics as __tls_get_addr, but its presence enables
// some optimizations in linker (which are safe to ignore here).
INTERCEPTOR(void *, __tls_get_addr_opt, void *arg) ALIAS(WRAP(__tls_get_addr));
#endif
#else // SANITIZER_S390
// On s390, we have to intercept two functions here:
// - __tls_get_addr_internal, which is a glibc-internal function that is like
//   the usual __tls_get_addr, but returns a TP-relative offset instead of
//   a proper pointer.  It is used by dlsym for TLS symbols.
// - __tls_get_offset, which is like the above, but also takes a GOT-relative
//   descriptor offset as an argument instead of a pointer.  GOT address
//   is passed in r12, so it's necessary to write it in assembly.  This is
//   the function used by the compiler.
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
  uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
  uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
  void *ptr = reinterpret_cast<void *>(res + tp);
  uptr tls_begin, tls_end;
  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
  if (dtv) {
    // New DTLS block has been allocated.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
  }
  return res;
}
#endif // SANITIZER_S390
#else
#define INIT_TLS_GET_ADDR
#endif

#if SANITIZER_S390 && \
    (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
// We need a hidden symbol aliasing the above, so that we can jump
// directly to it from the assembly below.
extern "C" __attribute__((visibility("hidden"))) uptr __tls_get_addr_hidden(
    void *arg) ALIAS(WRAP(__tls_get_addr_internal));
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr TRAMPOLINE(__tls_get_offset)(void *arg);
extern "C" uptr WRAP(__tls_get_offset)(void *arg);
// Now carefully intercept __tls_get_offset.
asm(
  ".text\n"
// The __intercept_ version has to exist, so that gen_dynamic_list.py
// exports our symbol.
  ".weak __tls_get_offset\n"
  ".set __tls_get_offset, __interceptor___tls_get_offset\n"
  ".global __interceptor___tls_get_offset\n"
  ".type __interceptor___tls_get_offset, @@function\n"
  "__interceptor___tls_get_offset:\n"
#ifdef __s390x__
  "la %r2, 0(%r2,%r12)\n"
  "jg __tls_get_addr_hidden\n"
#else
  "basr %r3,0\n"
  "0: la %r2,0(%r2,%r12)\n"
  "l %r4,1f-0b(%r3)\n"
  "b 0(%r4,%r3)\n"
  "1: .long __tls_get_addr_hidden - 0b\n"
#endif
  ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
// Assembly wrapper to call REAL(__tls_get_offset)(arg)
  ".type __tls_get_offset_wrapper, @@function\n"
  "__tls_get_offset_wrapper:\n"
#ifdef __s390x__
  "sgr %r2,%r12\n"
#else
  "sr %r2,%r12\n"
#endif
  "br %r3\n"
  ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
);
#endif

#if SANITIZER_INTERCEPT_LISTXATTR
INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(listxattr)(path, list, size);
  // Here and below, size == 0 is a special case where nothing is written to the
  // buffer, and res contains the desired buffer size.
  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
  return res;
}
INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(llistxattr)(path, list, size);
  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
  return res;
}
INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(flistxattr)(fd, list, size);
  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
  return res;
}
#define INIT_LISTXATTR                   \
  COMMON_INTERCEPT_FUNCTION(listxattr);  \
  COMMON_INTERCEPT_FUNCTION(llistxattr); \
  COMMON_INTERCEPT_FUNCTION(flistxattr);
#else
#define INIT_LISTXATTR
#endif

#if SANITIZER_INTERCEPT_GETXATTR
INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
            SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(getxattr)(path, name, value, size);
  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
  return res;
}
INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
            SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
  return res;
}
INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
            SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
  return res;
}
#define INIT_GETXATTR                   \
  COMMON_INTERCEPT_FUNCTION(getxattr);  \
  COMMON_INTERCEPT_FUNCTION(lgetxattr); \
  COMMON_INTERCEPT_FUNCTION(fgetxattr);
#else
#define INIT_GETXATTR
#endif

#if SANITIZER_INTERCEPT_GETRESID
INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getresuid)(ruid, euid, suid);
  if (res >= 0) {
    if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
    if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
    if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
  }
  return res;
}
INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getresgid)(rgid, egid, sgid);
  if (res >= 0) {
    if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
    if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
    if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
  }
  return res;
}
#define INIT_GETRESID                   \
  COMMON_INTERCEPT_FUNCTION(getresuid); \
  COMMON_INTERCEPT_FUNCTION(getresgid);
#else
#define INIT_GETRESID
#endif

#if SANITIZER_INTERCEPT_GETIFADDRS
// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
// intercept freeifaddrs(). If that ceases to be the case, we might need to
// intercept it to poison the memory again.
INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(getifaddrs)(ifap);
  if (res == 0 && ifap) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
    __sanitizer_ifaddrs *p = *ifap;
    while (p) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
      if (p->ifa_name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
                                       internal_strlen(p->ifa_name) + 1);
      if (p->ifa_addr)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
      if (p->ifa_netmask)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
      // On Linux this is a union, but the other member also points to a
      // struct sockaddr, so the following is sufficient.
      if (p->ifa_dstaddr)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
      // FIXME(smatveev): Unpoison p->ifa_data as well.
      p = p->ifa_next;
    }
  }
  return res;
}
#define INIT_GETIFADDRS                  \
  COMMON_INTERCEPT_FUNCTION(getifaddrs);
#else
#define INIT_GETIFADDRS
#endif

#if SANITIZER_INTERCEPT_IF_INDEXTONAME
INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(if_indextoname)(ifindex, ifname);
  if (res && ifname)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
  return res;
}
INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
  if (ifname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
  return REAL(if_nametoindex)(ifname);
}
#define INIT_IF_INDEXTONAME                  \
  COMMON_INTERCEPT_FUNCTION(if_indextoname); \
  COMMON_INTERCEPT_FUNCTION(if_nametoindex);
#else
#define INIT_IF_INDEXTONAME
#endif

#if SANITIZER_INTERCEPT_CAPGET
INTERCEPTOR(int, capget, void *hdrp, void *datap) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
  if (hdrp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(capget)(hdrp, datap);
  if (res == 0 && datap) {
    unsigned datasz = __user_cap_data_struct_sz(hdrp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, datasz);
  }
  // We can also return -1 and write to hdrp->version if the version passed in
  // hdrp->version is unsupported. But that's not a trivial condition to check,
  // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
  return res;
}
INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
  if (hdrp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
  if (datap) {
    unsigned datasz = __user_cap_data_struct_sz(hdrp);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, datasz);
  }
  return REAL(capset)(hdrp, datap);
}
#define INIT_CAPGET                  \
  COMMON_INTERCEPT_FUNCTION(capget); \
  COMMON_INTERCEPT_FUNCTION(capset);
#else
#define INIT_CAPGET
#endif

#if SANITIZER_INTERCEPT_FTIME
INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(ftime)(tp);
  if (tp)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
  return res;
}
#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
#else
#define INIT_FTIME
#endif  // SANITIZER_INTERCEPT_FTIME

#if SANITIZER_INTERCEPT_XDR
INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
            unsigned size, int op) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  REAL(xdrmem_create)(xdrs, addr, size, op);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
  if (op == __sanitizer_XDR_ENCODE) {
    // It's not obvious how much data individual xdr_ routines write.
    // Simply unpoison the entire target buffer in advance.
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
  }
}

INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  REAL(xdrstdio_create)(xdrs, file, op);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
}

// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
#define XDR_INTERCEPTOR(F, T)                             \
  INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) {      \
    void *ctx;                                            \
    COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p);            \
    if (p && xdrs->x_op == __sanitizer_XDR_ENCODE)        \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));  \
    int res = REAL(F)(xdrs, p);                           \
    if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
    return res;                                           \
  }

XDR_INTERCEPTOR(xdr_short, short)
XDR_INTERCEPTOR(xdr_u_short, unsigned short)
XDR_INTERCEPTOR(xdr_int, int)
XDR_INTERCEPTOR(xdr_u_int, unsigned)
XDR_INTERCEPTOR(xdr_long, long)
XDR_INTERCEPTOR(xdr_u_long, unsigned long)
XDR_INTERCEPTOR(xdr_hyper, long long)
XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
XDR_INTERCEPTOR(xdr_longlong_t, long long)
XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
XDR_INTERCEPTOR(xdr_int8_t, u8)
XDR_INTERCEPTOR(xdr_uint8_t, u8)
XDR_INTERCEPTOR(xdr_int16_t, u16)
XDR_INTERCEPTOR(xdr_uint16_t, u16)
XDR_INTERCEPTOR(xdr_int32_t, u32)
XDR_INTERCEPTOR(xdr_uint32_t, u32)
XDR_INTERCEPTOR(xdr_int64_t, u64)
XDR_INTERCEPTOR(xdr_uint64_t, u64)
XDR_INTERCEPTOR(xdr_quad_t, long long)
XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
XDR_INTERCEPTOR(xdr_bool, bool)
XDR_INTERCEPTOR(xdr_enum, int)
XDR_INTERCEPTOR(xdr_char, char)
XDR_INTERCEPTOR(xdr_u_char, unsigned char)
XDR_INTERCEPTOR(xdr_float, float)
XDR_INTERCEPTOR(xdr_double, double)

// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
// wrapstring, sizeof

INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
            unsigned maxsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
  if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
  if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
    if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
  }
  return res;
}

INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
            unsigned maxsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
  if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, internal_strlen(*p) + 1);
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(xdr_string)(xdrs, p, maxsize);
  if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
    if (res && *p)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
  }
  return res;
}

#define INIT_XDR                               \
  COMMON_INTERCEPT_FUNCTION(xdrmem_create);    \
  COMMON_INTERCEPT_FUNCTION(xdrstdio_create);  \
  COMMON_INTERCEPT_FUNCTION(xdr_short);        \
  COMMON_INTERCEPT_FUNCTION(xdr_u_short);      \
  COMMON_INTERCEPT_FUNCTION(xdr_int);          \
  COMMON_INTERCEPT_FUNCTION(xdr_u_int);        \
  COMMON_INTERCEPT_FUNCTION(xdr_long);         \
  COMMON_INTERCEPT_FUNCTION(xdr_u_long);       \
  COMMON_INTERCEPT_FUNCTION(xdr_hyper);        \
  COMMON_INTERCEPT_FUNCTION(xdr_u_hyper);      \
  COMMON_INTERCEPT_FUNCTION(xdr_longlong_t);   \
  COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
  COMMON_INTERCEPT_FUNCTION(xdr_int8_t);       \
  COMMON_INTERCEPT_FUNCTION(xdr_uint8_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_int16_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_uint16_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_int32_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_uint32_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_int64_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_uint64_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_quad_t);       \
  COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_bool);         \
  COMMON_INTERCEPT_FUNCTION(xdr_enum);         \
  COMMON_INTERCEPT_FUNCTION(xdr_char);         \
  COMMON_INTERCEPT_FUNCTION(xdr_u_char);       \
  COMMON_INTERCEPT_FUNCTION(xdr_float);        \
  COMMON_INTERCEPT_FUNCTION(xdr_double);       \
  COMMON_INTERCEPT_FUNCTION(xdr_bytes);        \
  COMMON_INTERCEPT_FUNCTION(xdr_string);
#else
#define INIT_XDR
#endif  // SANITIZER_INTERCEPT_XDR

#if SANITIZER_INTERCEPT_XDRREC
typedef int (*xdrrec_cb)(char*, char*, int);
struct XdrRecWrapper {
  char *handle;
  xdrrec_cb rd, wr;
};
typedef AddrHashMap<XdrRecWrapper *, 11> XdrRecWrapMap;
static XdrRecWrapMap *xdrrec_wrap_map;

static int xdrrec_wr_wrap(char *handle, char *buf, int count) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(buf, count);
  XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
  return wrap->wr(wrap->handle, buf, count);
}

static int xdrrec_rd_wrap(char *handle, char *buf, int count) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
  return wrap->rd(wrap->handle, buf, count);
}

// This doesn't apply to the solaris version as it has a different function
// signature.
INTERCEPTOR(void, xdrrec_create, __sanitizer_XDR *xdr, unsigned sndsize,
            unsigned rcvsize, char *handle, int (*rd)(char*, char*, int),
            int (*wr)(char*, char*, int)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdrrec_create, xdr, sndsize, rcvsize,
                           handle, rd, wr);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &xdr->x_op, sizeof xdr->x_op);

  // We can't allocate a wrapper on the stack, as the handle is used outside
  // this stack frame. So we put it on the heap, and keep track of it with
  // the HashMap (keyed by x_private). When we later need to xdr_destroy,
  // we can index the map, free the wrapper, and then clean the map entry.
  XdrRecWrapper *wrap_data =
      (XdrRecWrapper *)InternalAlloc(sizeof(XdrRecWrapper));
  wrap_data->handle = handle;
  wrap_data->rd = rd;
  wrap_data->wr = wr;
  if (wr)
    wr = xdrrec_wr_wrap;
  if (rd)
    rd = xdrrec_rd_wrap;
  handle = (char *)wrap_data;

  REAL(xdrrec_create)(xdr, sndsize, rcvsize, handle, rd, wr);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdr, sizeof *xdr);

  XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, false, true);
  *wrap = wrap_data;
}

// We have to intercept this to be able to free wrapper memory;
// otherwise it's not necessary.
INTERCEPTOR(void, xdr_destroy, __sanitizer_XDR *xdr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdr_destroy, xdr);

  XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, true);
  InternalFree(*wrap);
  REAL(xdr_destroy)(xdr);
}
#define INIT_XDRREC_LINUX \
  static u64 xdrrec_wrap_mem[sizeof(XdrRecWrapMap) / sizeof(u64) + 1]; \
  xdrrec_wrap_map = new ((void *)&xdrrec_wrap_mem) XdrRecWrapMap(); \
  COMMON_INTERCEPT_FUNCTION(xdrrec_create); \
  COMMON_INTERCEPT_FUNCTION(xdr_destroy);
#else
#define INIT_XDRREC_LINUX
#endif

#if SANITIZER_INTERCEPT_TSEARCH
INTERCEPTOR(void *, tsearch, void *key, void **rootp,
            int (*compar)(const void *, const void *)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  void *res = REAL(tsearch)(key, rootp, compar);
  if (res && *(void **)res == key)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
  return res;
}
#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
#else
#define INIT_TSEARCH
#endif

#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
    SANITIZER_INTERCEPT_OPEN_MEMSTREAM
void unpoison_file(__sanitizer_FILE *fp) {
#if SANITIZER_HAS_STRUCT_FILE
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
#if SANITIZER_NETBSD
  if (fp->_bf._base && fp->_bf._size > 0)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base,
                                        fp->_bf._size);
#else
  if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
                                        fp->_IO_read_end - fp->_IO_read_base);
  if (fp->_IO_write_base && fp->_IO_write_base < fp->_IO_write_end)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_write_base,
                                        fp->_IO_write_end - fp->_IO_write_base);
#endif
#endif  // SANITIZER_HAS_STRUCT_FILE
}
#endif

#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
// These guys are called when a .c source is built with -O2.
INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
  int res = REAL(__uflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
  int res = REAL(__underflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
  int res = REAL(__overflow)(fp, ch);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
  int res = REAL(__wuflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
  int res = REAL(__wunderflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
  int res = REAL(__woverflow)(fp, ch);
  unpoison_file(fp);
  return res;
}
#define INIT_LIBIO_INTERNALS               \
  COMMON_INTERCEPT_FUNCTION(__uflow);      \
  COMMON_INTERCEPT_FUNCTION(__underflow);  \
  COMMON_INTERCEPT_FUNCTION(__overflow);   \
  COMMON_INTERCEPT_FUNCTION(__wuflow);     \
  COMMON_INTERCEPT_FUNCTION(__wunderflow); \
  COMMON_INTERCEPT_FUNCTION(__woverflow);
#else
#define INIT_LIBIO_INTERNALS
#endif

#if SANITIZER_INTERCEPT_FOPEN
INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
  __sanitizer_FILE *res = REAL(fopen)(path, mode);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
  __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
  if (res) unpoison_file(res);
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
            __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_FOPEN                   \
  COMMON_INTERCEPT_FUNCTION(fopen);  \
  COMMON_INTERCEPT_FUNCTION(fdopen); \
  COMMON_INTERCEPT_FUNCTION(freopen);
#else
#define INIT_FOPEN
#endif

#if SANITIZER_INTERCEPT_FLOPEN
INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
  void *ctx;
  va_list ap;
  va_start(ap, flags);
  u16 mode = static_cast<u16>(va_arg(ap, u32));
  va_end(ap);
  COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
  if (path) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  }
  return REAL(flopen)(path, flags, mode);
}

INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
  void *ctx;
  va_list ap;
  va_start(ap, flags);
  u16 mode = static_cast<u16>(va_arg(ap, u32));
  va_end(ap);
  COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
  if (path) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  }
  return REAL(flopenat)(dirfd, path, flags, mode);
}

#define INIT_FLOPEN    \
  COMMON_INTERCEPT_FUNCTION(flopen); \
  COMMON_INTERCEPT_FUNCTION(flopenat);
#else
#define INIT_FLOPEN
#endif

#if SANITIZER_INTERCEPT_FOPEN64
INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
  __sanitizer_FILE *res = REAL(fopen64)(path, mode);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
            __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_FOPEN64                  \
  COMMON_INTERCEPT_FUNCTION(fopen64); \
  COMMON_INTERCEPT_FUNCTION(freopen64);
#else
#define INIT_FOPEN64
#endif

#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
  if (res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
    unpoison_file(res);
    FileMetadata file = {ptr, sizeloc};
    SetInterceptorMetadata(res, file);
  }
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
            SIZE_T *sizeloc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
  __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
  if (res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
    unpoison_file(res);
    FileMetadata file = {(char **)ptr, sizeloc};
    SetInterceptorMetadata(res, file);
  }
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
            const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_OPEN_MEMSTREAM                   \
  COMMON_INTERCEPT_FUNCTION(open_memstream);  \
  COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
  COMMON_INTERCEPT_FUNCTION(fmemopen);
#else
#define INIT_OPEN_MEMSTREAM
#endif

#if SANITIZER_INTERCEPT_OBSTACK
static void initialize_obstack(__sanitizer_obstack *obstack) {
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
  if (obstack->chunk)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
                                        sizeof(*obstack->chunk));
}

INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
            int align, void *(*alloc_fn)(uptr arg, uptr sz),
            void (*free_fn)(uptr arg, void *p)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
                           free_fn);
  int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
  if (res) initialize_obstack(obstack);
  return res;
}
INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
            int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
                           free_fn);
  int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
  if (res) initialize_obstack(obstack);
  return res;
}
INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
  REAL(_obstack_newchunk)(obstack, length);
  if (obstack->chunk)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(
        obstack->chunk, obstack->next_free - (char *)obstack->chunk);
}
#define INIT_OBSTACK                           \
  COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
  COMMON_INTERCEPT_FUNCTION(_obstack_begin);   \
  COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
#else
#define INIT_OBSTACK
#endif

#if SANITIZER_INTERCEPT_FFLUSH
INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
  if (fp)
    unpoison_file(fp);
  int res = REAL(fflush)(fp);
  // FIXME: handle fp == NULL
  if (fp) {
    const FileMetadata *m = GetInterceptorMetadata(fp);
    if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
  }
  return res;
}
#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
#else
#define INIT_FFLUSH
#endif

#if SANITIZER_INTERCEPT_FCLOSE
INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  const FileMetadata *m = GetInterceptorMetadata(fp);
  if (fp)
    unpoison_file(fp);
  int res = REAL(fclose)(fp);
  if (m) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
    DeleteInterceptorMetadata(fp);
  }
  return res;
}
#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
#else
#define INIT_FCLOSE
#endif

#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);

  if (filename) {
    COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);

#  if !SANITIZER_DYNAMIC
    // We care about a very specific use-case: dladdr on
    // statically-linked ASan may return <main program>
    // instead of the library.
    // We therefore only take effect if the sanitizer is statically
    // linked, and we don't bother canonicalizing paths because
    // dladdr should return the same address both times (we assume
    // the user did not canonicalize the result from dladdr).
    if (common_flags()->test_only_replace_dlopen_main_program) {
      VPrintf(1, "dlopen interceptor: filename: %s\n", filename);

      const char *SelfFName = DladdrSelfFName();
      VPrintf(1, "dlopen interceptor: DladdrSelfFName: %p %s\n",
              (void *)SelfFName, SelfFName);

      if (internal_strcmp(SelfFName, filename) == 0) {
        // It's possible they copied the string from dladdr, so
        // we do a string comparison rather than pointer comparison.
        VPrintf(1, "dlopen interceptor: replacing %s because it matches %s\n",
                filename, SelfFName);
        filename = (char *)0;  // RTLD_DEFAULT
      }
    }
#  endif  // !SANITIZER_DYNAMIC
  }

  void *res = COMMON_INTERCEPTOR_DLOPEN(filename, flag);
  Symbolizer::GetOrInit()->InvalidateModuleList();
  COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
  return res;
}

INTERCEPTOR(int, dlclose, void *handle) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
  int res = REAL(dlclose)(handle);
  Symbolizer::GetOrInit()->InvalidateModuleList();
  COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
  return res;
}
#define INIT_DLOPEN_DLCLOSE          \
  COMMON_INTERCEPT_FUNCTION(dlopen); \
  COMMON_INTERCEPT_FUNCTION(dlclose);
#else
#define INIT_DLOPEN_DLCLOSE
#endif

#if SANITIZER_INTERCEPT_GETPASS
INTERCEPTOR(char *, getpass, const char *prompt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
  if (prompt)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, internal_strlen(prompt)+1);
  char *res = REAL(getpass)(prompt);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res)+1);
  return res;
}

#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
#else
#define INIT_GETPASS
#endif

#if SANITIZER_INTERCEPT_TIMERFD
INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
            void *old_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
                           old_value);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
  int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
  if (res != -1 && old_value)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
  return res;
}

INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
  int res = REAL(timerfd_gettime)(fd, curr_value);
  if (res != -1 && curr_value)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
  return res;
}
#define INIT_TIMERFD                          \
  COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
  COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
#else
#define INIT_TIMERFD
#endif

#if SANITIZER_INTERCEPT_MLOCKX
// Linux kernel has a bug that leads to kernel deadlock if a process
// maps TBs of memory and then calls mlock().
static void MlockIsUnsupported() {
  static atomic_uint8_t printed;
  if (atomic_exchange(&printed, 1, memory_order_relaxed))
    return;
  VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
          SanitizerToolName);
}

INTERCEPTOR(int, mlock, const void *addr, uptr len) {
  MlockIsUnsupported();
  return 0;
}

INTERCEPTOR(int, munlock, const void *addr, uptr len) {
  MlockIsUnsupported();
  return 0;
}

INTERCEPTOR(int, mlockall, int flags) {
  MlockIsUnsupported();
  return 0;
}

INTERCEPTOR(int, munlockall, void) {
  MlockIsUnsupported();
  return 0;
}

#define INIT_MLOCKX                                                            \
  COMMON_INTERCEPT_FUNCTION(mlock);                                            \
  COMMON_INTERCEPT_FUNCTION(munlock);                                          \
  COMMON_INTERCEPT_FUNCTION(mlockall);                                         \
  COMMON_INTERCEPT_FUNCTION(munlockall);

#else
#define INIT_MLOCKX
#endif  // SANITIZER_INTERCEPT_MLOCKX

#if SANITIZER_INTERCEPT_FOPENCOOKIE
struct WrappedCookie {
  void *real_cookie;
  __sanitizer_cookie_io_functions_t real_io_funcs;
};

static uptr wrapped_read(void *cookie, char *buf, uptr size) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
  return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
}

static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
  return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
}

static int wrapped_seek(void *cookie, u64 *offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
  return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
                   : -1;
}

static int wrapped_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
  int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
            __sanitizer_cookie_io_functions_t io_funcs) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
  WrappedCookie *wrapped_cookie =
      (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_io_funcs = io_funcs;
  __sanitizer_FILE *res =
      REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
                                               wrapped_seek, wrapped_close});
  return res;
}

#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
#else
#define INIT_FOPENCOOKIE
#endif  // SANITIZER_INTERCEPT_FOPENCOOKIE

#if SANITIZER_INTERCEPT_SEM
INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
  // Workaround a bug in glibc's "old" semaphore implementation by
  // zero-initializing the sem_t contents. This has to be done here because
  // interceptors bind to the lowest version before glibc 2.36, hitting the
  // buggy code path while the non-sanitized build of the same code works fine.
  REAL(memset)(s, 0, sizeof(*s));
  int res = REAL(sem_init)(s, pshared, value);
  return res;
}

INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
  int res = REAL(sem_destroy)(s);
  return res;
}

INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
  }
  return res;
}

INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
  int res = REAL(sem_trywait)(s);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
  }
  return res;
}

INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
  }
  return res;
}

INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
  COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
  int res = REAL(sem_post)(s);
  return res;
}

INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
  int res = REAL(sem_getvalue)(s, sval);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
  }
  return res;
}

INTERCEPTOR(__sanitizer_sem_t *, sem_open, const char *name, int oflag, ...) {
  void *ctx;
  va_list ap;
  va_start(ap, oflag);
  u32 mode = va_arg(ap, u32);
  u32 value = va_arg(ap, u32);
  COMMON_INTERCEPTOR_ENTER(ctx, sem_open, name, oflag, mode, value);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  __sanitizer_sem_t *s = REAL(sem_open)(name, oflag, mode, value);
  if (s)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, sizeof(*s));
  va_end(ap);
  return s;
}

INTERCEPTOR(int, sem_unlink, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_unlink, name);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  return REAL(sem_unlink)(name);
}

#  define INIT_SEM                            \
    COMMON_INTERCEPT_FUNCTION(sem_init);      \
    COMMON_INTERCEPT_FUNCTION(sem_destroy);   \
    COMMON_INTERCEPT_FUNCTION(sem_wait);      \
    COMMON_INTERCEPT_FUNCTION(sem_trywait);   \
    COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
    COMMON_INTERCEPT_FUNCTION(sem_post);      \
    COMMON_INTERCEPT_FUNCTION(sem_getvalue);  \
    COMMON_INTERCEPT_FUNCTION(sem_open);      \
    COMMON_INTERCEPT_FUNCTION(sem_unlink);
#else
#  define INIT_SEM
#endif  // SANITIZER_INTERCEPT_SEM

#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
  int res = REAL(pthread_setcancelstate)(state, oldstate);
  if (res == 0 && oldstate != nullptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
  return res;
}

INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
  int res = REAL(pthread_setcanceltype)(type, oldtype);
  if (res == 0 && oldtype != nullptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
  return res;
}
#define INIT_PTHREAD_SETCANCEL                                                 \
  COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate);                           \
  COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
#else
#define INIT_PTHREAD_SETCANCEL
#endif

#if SANITIZER_INTERCEPT_MINCORE
INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
  int res = REAL(mincore)(addr, length, vec);
  if (res == 0) {
    uptr page_size = GetPageSizeCached();
    uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
  }
  return res;
}
#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
#else
#define INIT_MINCORE
#endif

#if SANITIZER_INTERCEPT_PROCESS_VM_READV
INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
            uptr flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
                           remote_iov, riovcnt, flags);
  SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
                                       riovcnt, flags);
  if (res > 0)
    write_iovec(ctx, local_iov, liovcnt, res);
  return res;
}

INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
            uptr flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
                           remote_iov, riovcnt, flags);
  SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
                                        riovcnt, flags);
  if (res > 0)
    read_iovec(ctx, local_iov, liovcnt, res);
  return res;
}
#define INIT_PROCESS_VM_READV                                                  \
  COMMON_INTERCEPT_FUNCTION(process_vm_readv);                                 \
  COMMON_INTERCEPT_FUNCTION(process_vm_writev);
#else
#define INIT_PROCESS_VM_READV
#endif

#if SANITIZER_INTERCEPT_CTERMID
INTERCEPTOR(char *, ctermid, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
  char *res = REAL(ctermid)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  }
  return res;
}
#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
#else
#define INIT_CTERMID
#endif

#if SANITIZER_INTERCEPT_CTERMID_R
INTERCEPTOR(char *, ctermid_r, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
  char *res = REAL(ctermid_r)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  }
  return res;
}
#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
#else
#define INIT_CTERMID_R
#endif

#if SANITIZER_INTERCEPT_RECV_RECVFROM
INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
  }
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}

INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
            void *srcaddr, int *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
                           addrlen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SIZE_T srcaddr_sz;
  if (srcaddr) srcaddr_sz = *addrlen;
  (void)srcaddr_sz;  // prevent "set but not used" warning
  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
  if (res >= 0 && srcaddr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
                                        Min((SIZE_T)*addrlen, srcaddr_sz));
  return res;
}
#define INIT_RECV_RECVFROM          \
  COMMON_INTERCEPT_FUNCTION(recv);  \
  COMMON_INTERCEPT_FUNCTION(recvfrom);
#else
#define INIT_RECV_RECVFROM
#endif

#if SANITIZER_INTERCEPT_SEND_SENDTO
INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(send)(fd, buf, len, flags);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}

INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
            void *dstaddr, int addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  // Can't check dstaddr as it may have uninitialized padding at the end.
  SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}
#define INIT_SEND_SENDTO           \
  COMMON_INTERCEPT_FUNCTION(send); \
  COMMON_INTERCEPT_FUNCTION(sendto);
#else
#define INIT_SEND_SENDTO
#endif

#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(eventfd_read)(fd, value);
  if (res == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  int res = REAL(eventfd_write)(fd, value);
  return res;
}
#define INIT_EVENTFD_READ_WRITE            \
  COMMON_INTERCEPT_FUNCTION(eventfd_read); \
  COMMON_INTERCEPT_FUNCTION(eventfd_write)
#else
#define INIT_EVENTFD_READ_WRITE
#endif

#if SANITIZER_INTERCEPT_STAT
INTERCEPTOR(int, stat, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(stat)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
#else
#define INIT_STAT
#endif

#if SANITIZER_INTERCEPT_STAT64
INTERCEPTOR(int, stat64, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stat64, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(stat64)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT_STAT64 COMMON_INTERCEPT_FUNCTION(stat64)
#else
#define INIT_STAT64
#endif


#if SANITIZER_INTERCEPT_LSTAT
INTERCEPTOR(int, lstat, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lstat, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(lstat)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT_LSTAT COMMON_INTERCEPT_FUNCTION(lstat)
#else
#define INIT_LSTAT
#endif

#if SANITIZER_INTERCEPT_STAT64
INTERCEPTOR(int, lstat64, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lstat64, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(lstat64)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT_LSTAT64 COMMON_INTERCEPT_FUNCTION(lstat64)
#else
#define INIT_LSTAT64
#endif

#if SANITIZER_INTERCEPT___XSTAT
INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
#else
#define INIT___XSTAT
#endif

#if SANITIZER_INTERCEPT___XSTAT64
INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
#else
#define INIT___XSTAT64
#endif

#if SANITIZER_INTERCEPT___LXSTAT
INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
#else
#define INIT___LXSTAT
#endif

#if SANITIZER_INTERCEPT___LXSTAT64
INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
#else
#define INIT___LXSTAT64
#endif

// FIXME: add other *stat interceptor

#if SANITIZER_INTERCEPT_UTMP
INTERCEPTOR(void *, getutent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
  void *res = REAL(getutent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
  void *res = REAL(getutid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
  void *res = REAL(getutline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
#define INIT_UTMP                      \
  COMMON_INTERCEPT_FUNCTION(getutent); \
  COMMON_INTERCEPT_FUNCTION(getutid);  \
  COMMON_INTERCEPT_FUNCTION(getutline);
#else
#define INIT_UTMP
#endif

#if SANITIZER_INTERCEPT_UTMPX
INTERCEPTOR(void *, getutxent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
  void *res = REAL(getutxent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
  void *res = REAL(getutxid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
  void *res = REAL(getutxline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, pututxline, const void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut);
  if (ut)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz);
  void *res = REAL(pututxline)(ut);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz);
  return res;
}
#define INIT_UTMPX                      \
  COMMON_INTERCEPT_FUNCTION(getutxent); \
  COMMON_INTERCEPT_FUNCTION(getutxid);  \
  COMMON_INTERCEPT_FUNCTION(getutxline); \
  COMMON_INTERCEPT_FUNCTION(pututxline);
#else
#define INIT_UTMPX
#endif

#if SANITIZER_INTERCEPT_GETLOADAVG
INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
  int res = REAL(getloadavg)(loadavg, nelem);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
  return res;
}
#define INIT_GETLOADAVG                      \
  COMMON_INTERCEPT_FUNCTION(getloadavg);
#else
#define INIT_GETLOADAVG
#endif

#if SANITIZER_INTERCEPT_MCHECK_MPROBE
INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mprobe, void *ptr) {
  return 0;
}
#endif

#if SANITIZER_INTERCEPT_WCSLEN
INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
  SIZE_T res = REAL(wcslen)(s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
  return res;
}

INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
  SIZE_T res = REAL(wcsnlen)(s, n);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
  return res;
}
#define INIT_WCSLEN                  \
  COMMON_INTERCEPT_FUNCTION(wcslen); \
  COMMON_INTERCEPT_FUNCTION(wcsnlen);
#else
#define INIT_WCSLEN
#endif

#if SANITIZER_INTERCEPT_WCSCAT
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
  SIZE_T src_size = internal_wcslen(src);
  SIZE_T dst_size = internal_wcslen(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcscat)(dst, src);
}

INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
  SIZE_T src_size = internal_wcsnlen(src, n);
  SIZE_T dst_size = internal_wcslen(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
                                Min(src_size + 1, n) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcsncat)(dst, src, n);
}
#define INIT_WCSCAT                  \
  COMMON_INTERCEPT_FUNCTION(wcscat); \
  COMMON_INTERCEPT_FUNCTION(wcsncat);
#else
#define INIT_WCSCAT
#endif

#if SANITIZER_INTERCEPT_WCSDUP
INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
  SIZE_T len = internal_wcslen(s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
  wchar_t *result = REAL(wcsdup)(s);
  if (result)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(wchar_t) * (len + 1));
  return result;
}

#define INIT_WCSDUP COMMON_INTERCEPT_FUNCTION(wcsdup);
#else
#define INIT_WCSDUP
#endif

#if SANITIZER_INTERCEPT_STRXFRM
static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }

static SIZE_T RealStrLen(const wchar_t *str) { return internal_wcslen(str); }

#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...)             \
  {                                                                        \
    void *ctx;                                                             \
    COMMON_INTERCEPTOR_ENTER(ctx, strxfrm, dest, src, len, ##__VA_ARGS__); \
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src,                                \
                                  sizeof(*src) * (RealStrLen(src) + 1));   \
    SIZE_T res = REAL(strxfrm)(dest, src, len, ##__VA_ARGS__);             \
    if (res < len)                                                         \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, sizeof(*src) * (res + 1)); \
    return res;                                                            \
  }

INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T len) {
  STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len);
}

INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(strxfrm_l, dest, src, len, locale);
}

#define INIT_STRXFRM                  \
  COMMON_INTERCEPT_FUNCTION(strxfrm); \
  COMMON_INTERCEPT_FUNCTION(strxfrm_l);
#else
#define INIT_STRXFRM
#endif

#if SANITIZER_INTERCEPT___STRXFRM_L
INTERCEPTOR(SIZE_T, __strxfrm_l, char *dest, const char *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(__strxfrm_l, dest, src, len, locale);
}

#define INIT___STRXFRM_L COMMON_INTERCEPT_FUNCTION(__strxfrm_l);
#else
#define INIT___STRXFRM_L
#endif

#if SANITIZER_INTERCEPT_WCSXFRM
INTERCEPTOR(SIZE_T, wcsxfrm, wchar_t *dest, const wchar_t *src, SIZE_T len) {
  STRXFRM_INTERCEPTOR_IMPL(wcsxfrm, dest, src, len);
}

INTERCEPTOR(SIZE_T, wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(wcsxfrm_l, dest, src, len, locale);
}

#define INIT_WCSXFRM                  \
  COMMON_INTERCEPT_FUNCTION(wcsxfrm); \
  COMMON_INTERCEPT_FUNCTION(wcsxfrm_l);
#else
#define INIT_WCSXFRM
#endif

#if SANITIZER_INTERCEPT___WCSXFRM_L
INTERCEPTOR(SIZE_T, __wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(__wcsxfrm_l, dest, src, len, locale);
}

#define INIT___WCSXFRM_L COMMON_INTERCEPT_FUNCTION(__wcsxfrm_l);
#else
#define INIT___WCSXFRM_L
#endif

#if SANITIZER_INTERCEPT_ACCT
INTERCEPTOR(int, acct, const char *file) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
  if (file)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
  return REAL(acct)(file);
}
#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
#else
#define INIT_ACCT
#endif

#if SANITIZER_INTERCEPT_USER_FROM_UID
INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
  void *ctx;
  const char *user;
  COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
  user = REAL(user_from_uid)(uid, nouser);
  if (user)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, internal_strlen(user) + 1);
  return user;
}
#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
#else
#define INIT_USER_FROM_UID
#endif

#if SANITIZER_INTERCEPT_UID_FROM_USER
INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  res = REAL(uid_from_user)(name, uid);
  if (uid)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
  return res;
}
#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user)
#else
#define INIT_UID_FROM_USER
#endif

#if SANITIZER_INTERCEPT_GROUP_FROM_GID
INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
  void *ctx;
  const char *group;
  COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
  group = REAL(group_from_gid)(gid, nogroup);
  if (group)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, internal_strlen(group) + 1);
  return group;
}
#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
#else
#define INIT_GROUP_FROM_GID
#endif

#if SANITIZER_INTERCEPT_GID_FROM_GROUP
INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
  if (group)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, group, internal_strlen(group) + 1);
  res = REAL(gid_from_group)(group, gid);
  if (gid)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
  return res;
}
#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group)
#else
#define INIT_GID_FROM_GROUP
#endif

#if SANITIZER_INTERCEPT_ACCESS
INTERCEPTOR(int, access, const char *path, int mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  return REAL(access)(path, mode);
}
#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
#else
#define INIT_ACCESS
#endif

#if SANITIZER_INTERCEPT_FACCESSAT
INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  return REAL(faccessat)(fd, path, mode, flags);
}
#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
#else
#define INIT_FACCESSAT
#endif

#if SANITIZER_INTERCEPT_GETGROUPLIST
INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
            int *ngroups) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  if (ngroups)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
  res = REAL(getgrouplist)(name, basegid, groups, ngroups);
  if (!res && groups && ngroups) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
  }
  return res;
}

#define INIT_GETGROUPLIST COMMON_INTERCEPT_FUNCTION(getgrouplist);
#else
#define INIT_GETGROUPLIST
#endif

#if SANITIZER_INTERCEPT_GETGROUPMEMBERSHIP
INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
            int maxgrp, int *ngroups) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
                           maxgrp, ngroups);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
  if (!res && groups && ngroups) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
  }
  return res;
}

#define INIT_GETGROUPMEMBERSHIP COMMON_INTERCEPT_FUNCTION(getgroupmembership);
#else
#define INIT_GETGROUPMEMBERSHIP
#endif

#if SANITIZER_INTERCEPT_READLINK
INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
  return res;
}

#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink)
#else
#define INIT_READLINK
#endif

#if SANITIZER_INTERCEPT_READLINKAT
INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
            SIZE_T bufsiz) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
  return res;
}

#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat)
#else
#define INIT_READLINKAT
#endif

#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT
INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
            struct file_handle *handle, int *mount_id, int flags) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
                           mount_id, flags);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, internal_strlen(pathname) + 1);

  __sanitizer_file_handle *sanitizer_handle =
      reinterpret_cast<__sanitizer_file_handle*>(handle);
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->handle_bytes,
      sizeof(sanitizer_handle->handle_bytes));

  int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, &sanitizer_handle->handle_bytes,
        sizeof(sanitizer_handle->handle_bytes));
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, &sanitizer_handle->handle_type,
        sizeof(sanitizer_handle->handle_type));
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id));
  }
  return res;
}

#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at)
#else
#define INIT_NAME_TO_HANDLE_AT
#endif

#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT
INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
            int flags) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags);

  __sanitizer_file_handle *sanitizer_handle =
      reinterpret_cast<__sanitizer_file_handle*>(handle);
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->handle_bytes,
      sizeof(sanitizer_handle->handle_bytes));
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->handle_type,
      sizeof(sanitizer_handle->handle_type));
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);

  return REAL(open_by_handle_at)(mount_fd, handle, flags);
}

#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
#else
#define INIT_OPEN_BY_HANDLE_AT
#endif

#if SANITIZER_INTERCEPT_STRLCPY
INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
  void *ctx;
  SIZE_T res;
  COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size);
  if (src) {
    // Keep strnlen as macro argument, as macro may ignore it.
    COMMON_INTERCEPTOR_READ_STRING(
        ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
  }
  res = REAL(strlcpy)(dst, src, size);
  COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, internal_strlen(dst) + 1);
  return res;
}

INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) {
  void *ctx;
  SIZE_T len = 0;
  COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size);
  // src is checked in the strlcpy() interceptor
  if (dst) {
    len = internal_strnlen(dst, size);
    COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1);
  }
  // Reuse the rest of the code in the strlcpy() interceptor
  return WRAP(strlcpy)(dst + len, src, size - len) + len;
}
#define INIT_STRLCPY \
  COMMON_INTERCEPT_FUNCTION(strlcpy); \
  COMMON_INTERCEPT_FUNCTION(strlcat);
#else
#define INIT_STRLCPY
#endif

#if SANITIZER_INTERCEPT_MMAP
INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
            OFF_T off) {
  void *ctx;
  if (common_flags()->detect_write_exec)
    ReportMmapWriteExec(prot, flags);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off);
}

INTERCEPTOR(int, munmap, void *addr, SIZE_T sz) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (int)internal_munmap(addr, sz);
  COMMON_INTERCEPTOR_ENTER(ctx, munmap, addr, sz);
  COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz);
}

INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
  void *ctx;
  if (common_flags()->detect_write_exec)
    ReportMmapWriteExec(prot, 0);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (int)internal_mprotect(addr, sz, prot);
  COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot);
  MprotectMallocZones(addr, prot);
  return REAL(mprotect)(addr, sz, prot);
}
#define INIT_MMAP                                                              \
  COMMON_INTERCEPT_FUNCTION(mmap);                                             \
  COMMON_INTERCEPT_FUNCTION(munmap);                                           \
  COMMON_INTERCEPT_FUNCTION(mprotect);
#else
#define INIT_MMAP
#endif

#if SANITIZER_INTERCEPT_MMAP64
INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
            OFF64_T off) {
  void *ctx;
  if (common_flags()->detect_write_exec)
    ReportMmapWriteExec(prot, flags);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap64, addr, sz, prot, flags, fd, off);
}
#define INIT_MMAP64 COMMON_INTERCEPT_FUNCTION(mmap64);
#else
#define INIT_MMAP64
#endif

#if SANITIZER_INTERCEPT_DEVNAME
INTERCEPTOR(char *, devname, u64 dev, u32 type) {
  void *ctx;
  char *name;
  COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
  name = REAL(devname)(dev, type);
  if (name)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
  return name;
}
#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
#else
#define INIT_DEVNAME
#endif

#if SANITIZER_INTERCEPT_DEVNAME_R
#if SANITIZER_NETBSD
#define DEVNAME_R_RETTYPE int
#define DEVNAME_R_SUCCESS(x) (!(x))
#else
#define DEVNAME_R_RETTYPE char*
#define DEVNAME_R_SUCCESS(x) (x)
#endif
INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
            uptr len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
  DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
  if (DEVNAME_R_SUCCESS(res))
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, internal_strlen(path) + 1);
  return res;
}
#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
#else
#define INIT_DEVNAME_R
#endif

#if SANITIZER_INTERCEPT_FGETLN
INTERCEPTOR(char *, fgetln, __sanitizer_FILE *stream, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetln, stream, len);
  char *str = REAL(fgetln)(stream, len);
  if (str && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, *len);
  }
  return str;
}
#define INIT_FGETLN COMMON_INTERCEPT_FUNCTION(fgetln)
#else
#define INIT_FGETLN
#endif

#if SANITIZER_INTERCEPT_STRMODE
INTERCEPTOR(void, strmode, u32 mode, char *bp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
  REAL(strmode)(mode, bp);
  if (bp)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, internal_strlen(bp) + 1);
}
#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
#else
#define INIT_STRMODE
#endif

#if SANITIZER_INTERCEPT_TTYENT
INTERCEPTOR(struct __sanitizer_ttyent *, getttyent, void) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getttyent);
  struct __sanitizer_ttyent *ttyent = REAL(getttyent)();
  if (ttyent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
  return ttyent;
}
INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
  if (ttyent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
  return ttyent;
}
#define INIT_TTYENT \
  COMMON_INTERCEPT_FUNCTION(getttyent); \
  COMMON_INTERCEPT_FUNCTION(getttynam);
#else
#define INIT_TTYENT
#endif

#if SANITIZER_INTERCEPT_TTYENTPATH
INTERCEPTOR(int, setttyentpath, char *path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  return REAL(setttyentpath)(path);
}
#define INIT_TTYENTPATH COMMON_INTERCEPT_FUNCTION(setttyentpath);
#else
#define INIT_TTYENTPATH
#endif

#if SANITIZER_INTERCEPT_PROTOENT
static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, internal_strlen(p->p_name) + 1);

  SIZE_T pp_size = 1; // One handles the trailing \0

  for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *));
}

INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
  struct __sanitizer_protoent *p = REAL(getprotoent)();
  if (p)
    write_protoent(ctx, p);
  return p;
}

INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
  if (p)
    write_protoent(ctx, p);
  return p;
}

INTERCEPTOR(struct __sanitizer_protoent *, getprotobynumber, int proto) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber, proto);
  struct __sanitizer_protoent *p = REAL(getprotobynumber)(proto);
  if (p)
    write_protoent(ctx, p);
  return p;
}
#define INIT_PROTOENT \
  COMMON_INTERCEPT_FUNCTION(getprotoent); \
  COMMON_INTERCEPT_FUNCTION(getprotobyname); \
  COMMON_INTERCEPT_FUNCTION(getprotobynumber)
#else
#define INIT_PROTOENT
#endif

#if SANITIZER_INTERCEPT_PROTOENT_R
INTERCEPTOR(int, getprotoent_r, struct __sanitizer_protoent *result_buf,
            char *buf, SIZE_T buflen, struct __sanitizer_protoent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent_r, result_buf, buf, buflen,
                           result);
  int res = REAL(getprotoent_r)(result_buf, buf, buflen, result);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
  if (!res && *result)
    write_protoent(ctx, *result);
  return res;
}

INTERCEPTOR(int, getprotobyname_r, const char *name,
            struct __sanitizer_protoent *result_buf, char *buf, SIZE_T buflen,
            struct __sanitizer_protoent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
                           buflen, result);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
  if (!res && *result)
    write_protoent(ctx, *result);
  return res;
}

INTERCEPTOR(int, getprotobynumber_r, int num,
            struct __sanitizer_protoent *result_buf, char *buf,
            SIZE_T buflen, struct __sanitizer_protoent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber_r, num, result_buf, buf,
                           buflen, result);
  int res = REAL(getprotobynumber_r)(num, result_buf, buf, buflen, result);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
  if (!res && *result)
    write_protoent(ctx, *result);
  return res;
}

#define INIT_PROTOENT_R \
  COMMON_INTERCEPT_FUNCTION(getprotoent_r); \
  COMMON_INTERCEPT_FUNCTION(getprotobyname_r); \
  COMMON_INTERCEPT_FUNCTION(getprotobynumber_r);
#else
#define INIT_PROTOENT_R
#endif

#if SANITIZER_INTERCEPT_NETENT
INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnetent);
  struct __sanitizer_netent *n = REAL(getnetent)();
  if (n) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);

    SIZE_T nn_size = 1; // One handles the trailing \0

    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
  }
  return n;
}

INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  struct __sanitizer_netent *n = REAL(getnetbyname)(name);
  if (n) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);

    SIZE_T nn_size = 1; // One handles the trailing \0

    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
  }
  return n;
}

INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type);
  struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type);
  if (n) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);

    SIZE_T nn_size = 1; // One handles the trailing \0

    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
  }
  return n;
}
#define INIT_NETENT \
  COMMON_INTERCEPT_FUNCTION(getnetent); \
  COMMON_INTERCEPT_FUNCTION(getnetbyname); \
  COMMON_INTERCEPT_FUNCTION(getnetbyaddr)
#else
#define INIT_NETENT
#endif

#if SANITIZER_INTERCEPT_GETMNTINFO
INTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags);
  int cnt = REAL(getmntinfo)(mntbufp, flags);
  if (cnt > 0 && mntbufp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
    if (*mntbufp)
#if SANITIZER_NETBSD
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz);
#else
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz);
#endif
  }
  return cnt;
}
#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo)
#else
#define INIT_GETMNTINFO
#endif

#if SANITIZER_INTERCEPT_MI_VECTOR_HASH
INTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed,
            u32 hashes[3]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes);
  if (key)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len);
  REAL(mi_vector_hash)(key, len, seed, hashes);
  if (hashes)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3);
}
#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash)
#else
#define INIT_MI_VECTOR_HASH
#endif

#if SANITIZER_INTERCEPT_SETVBUF
INTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode,
  SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size);
  int ret = REAL(setvbuf)(stream, buf, mode, size);
  if (buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
  if (stream)
      unpoison_file(stream);
  return ret;
}

INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf);
  REAL(setbuf)(stream, buf);
  if (buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
  }
  if (stream)
      unpoison_file(stream);
}

INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, size);
  REAL(setbuffer)(stream, buf, size);
  if (buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
  }
  if (stream)
    unpoison_file(stream);
}

INTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream);
  REAL(setlinebuf)(stream);
  if (stream)
    unpoison_file(stream);
}
#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \
    COMMON_INTERCEPT_FUNCTION(setbuf); \
    COMMON_INTERCEPT_FUNCTION(setbuffer); \
    COMMON_INTERCEPT_FUNCTION(setlinebuf)
#else
#define INIT_SETVBUF
#endif

#if SANITIZER_INTERCEPT_GETVFSSTAT
INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
  int ret = REAL(getvfsstat)(buf, bufsize, flags);
  if (buf && ret > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz);
  return ret;
}
#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat)
#else
#define INIT_GETVFSSTAT
#endif

#if SANITIZER_INTERCEPT_REGEX
INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
  if (pattern)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, internal_strlen(pattern) + 1);
  int res = REAL(regcomp)(preg, pattern, cflags);
  if (preg)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
  return res;
}
INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
            struct __sanitizer_regmatch *pmatch[], int eflags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  if (string)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, string, internal_strlen(string) + 1);
  int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
  if (!res && pmatch)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
  return res;
}
INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
            SIZE_T errbuf_size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
  if (errbuf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, internal_strlen(errbuf) + 1);
  return res;
}
INTERCEPTOR(void, regfree, const void *preg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  REAL(regfree)(preg);
}
#define INIT_REGEX                                                             \
  COMMON_INTERCEPT_FUNCTION(regcomp);                                          \
  COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4");             \
  COMMON_INTERCEPT_FUNCTION(regerror);                                         \
  COMMON_INTERCEPT_FUNCTION(regfree);
#else
#define INIT_REGEX
#endif

#if SANITIZER_INTERCEPT_REGEXSUB
INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
            const struct __sanitizer_regmatch *rm, const char *str) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
  if (sub)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
  // The implementation demands and hardcodes 10 elements
  if (rm)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
  if (str)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
  SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
  if (res > 0 && buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
  return res;
}
INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
            const struct __sanitizer_regmatch *rm, const char *sstr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
  if (sub)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
  // Hardcode 10 elements as this is hardcoded size
  if (rm)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
  if (sstr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, internal_strlen(sstr) + 1);
  SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
  if (res > 0 && buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, internal_strlen(*buf) + 1);
  }
  return res;
}

#define INIT_REGEXSUB                                                          \
  COMMON_INTERCEPT_FUNCTION(regnsub);                                          \
  COMMON_INTERCEPT_FUNCTION(regasub);
#else
#define INIT_REGEXSUB
#endif

#if SANITIZER_INTERCEPT_FTS
INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
            int (*compar)(void **, void **)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar);
  if (path_argv) {
    for (char *const *pa = path_argv; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
    }
  }
  // TODO(kamil): handle compar callback
  void *fts = REAL(fts_open)(path_argv, options, compar);
  if (fts)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz);
  return fts;
}

INTERCEPTOR(void *, fts_read, void *ftsp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  void *ftsent = REAL(fts_read)(ftsp);
  if (ftsent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
  return ftsent;
}

INTERCEPTOR(void *, fts_children, void *ftsp, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  void *ftsent = REAL(fts_children)(ftsp, options);
  if (ftsent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
  return ftsent;
}

INTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  if (f)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz);
  return REAL(fts_set)(ftsp, f, options);
}

INTERCEPTOR(int, fts_close, void *ftsp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  return REAL(fts_close)(ftsp);
}
#define INIT_FTS                                                               \
  COMMON_INTERCEPT_FUNCTION(fts_open);                                         \
  COMMON_INTERCEPT_FUNCTION(fts_read);                                         \
  COMMON_INTERCEPT_FUNCTION(fts_children);                                     \
  COMMON_INTERCEPT_FUNCTION(fts_set);                                          \
  COMMON_INTERCEPT_FUNCTION(fts_close);
#else
#define INIT_FTS
#endif

#if SANITIZER_INTERCEPT_SYSCTL
INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
            SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
  COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
                           newlen);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
  if (oldlenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
  if (newp && newlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
  int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
  if (!res) {
    if (oldlenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
      if (oldp)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
    }
  }
  return res;
}

INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
            void *newp, SIZE_T newlen) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen);
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
                           newlen);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
  if (oldlenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
  if (newp && newlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
  int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
  if (!res) {
    if (oldlenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
      if (oldp)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
    }
  }
  return res;
}

INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
            SIZE_T *namelenp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
  if (namelenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
  int res = REAL(sysctlnametomib)(sname, name, namelenp);
  if (!res) {
    if (namelenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
      if (name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
    }
  }
  return res;
}

#define INIT_SYSCTL                        \
  COMMON_INTERCEPT_FUNCTION(sysctl);       \
  COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
  COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
#else
#define INIT_SYSCTL
#endif

#if SANITIZER_INTERCEPT_ASYSCTL
INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
  void *res = REAL(asysctl)(name, namelen, len);
  if (res && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
  }
  return res;
}

INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
  void *res = REAL(asysctlbyname)(sname, len);
  if (res && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
  }
  return res;
}
#define INIT_ASYSCTL                           \
  COMMON_INTERCEPT_FUNCTION(asysctl);          \
  COMMON_INTERCEPT_FUNCTION(asysctlbyname);
#else
#define INIT_ASYSCTL
#endif

#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
            unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
            int v) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
                           csz, rnode, v);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
  if (namelenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
  if (csz)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
  // Skip rnode, it's rarely used and not trivial to sanitize
  // It's also used mostly internally
  int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
  if (!res) {
    if (namelenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
      if (name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
    }
    if (csz) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
      if (cname)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
    }
  }
  return res;
}
#define INIT_SYSCTLGETMIBINFO                  \
  COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
#else
#define INIT_SYSCTLGETMIBINFO
#endif

#if SANITIZER_INTERCEPT_NL_LANGINFO
INTERCEPTOR(char *, nl_langinfo, long item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
  char *ret = REAL(nl_langinfo)(item);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
  return ret;
}
#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
#else
#define INIT_NL_LANGINFO
#endif

#if SANITIZER_INTERCEPT_MODCTL
INTERCEPTOR(int, modctl, int operation, void *argp) {
  void *ctx;
  int ret;
  COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp);

  if (operation == modctl_load) {
    if (argp) {
      __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
      if (ml->ml_filename)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
                                      internal_strlen(ml->ml_filename) + 1);
      if (ml->ml_props)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
    }
    ret = REAL(modctl)(operation, argp);
  } else if (operation == modctl_unload) {
    if (argp) {
      const char *name = (const char *)argp;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
    }
    ret = REAL(modctl)(operation, argp);
  } else if (operation == modctl_stat) {
    uptr iov_len;
    struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp;
    if (iov) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov));
      iov_len = iov->iov_len;
    }
    ret = REAL(modctl)(operation, argp);
    if (iov)
      COMMON_INTERCEPTOR_WRITE_RANGE(
          ctx, iov->iov_base, Min(iov_len,  iov->iov_len));
  } else if (operation == modctl_exists) {
    ret = REAL(modctl)(operation, argp);
  } else {
    ret = REAL(modctl)(operation, argp);
  }

  return ret;
}
#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl)
#else
#define INIT_MODCTL
#endif

#if SANITIZER_INTERCEPT_STRTONUM
INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
            long long maxval, const char **errstr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);

  // TODO(kamil): Implement strtoll as a common inteceptor
  char *real_endptr;
  long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
  StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);

  ret = REAL(strtonum)(nptr, minval, maxval, errstr);
  if (errstr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
     if (*errstr)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, internal_strlen(*errstr) + 1);
  }
  return ret;
}
#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
#else
#define INIT_STRTONUM
#endif

#if SANITIZER_INTERCEPT_FPARSELN
INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
            SIZE_T *lineno, const char delim[3], int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags);
  if (lineno)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno));
  if (delim)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
  char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
  if (ret) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
    if (len)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    if (lineno)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno));
  }
  return ret;
}
#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln)
#else
#define INIT_FPARSELN
#endif

#if SANITIZER_INTERCEPT_STATVFS1
INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  int res = REAL(statvfs1)(path, buf, flags);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(fstatvfs1)(fd, buf, flags);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
    if (fd >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
#define INIT_STATVFS1                  \
  COMMON_INTERCEPT_FUNCTION(statvfs1);  \
  COMMON_INTERCEPT_FUNCTION(fstatvfs1);
#else
#define INIT_STATVFS1
#endif

#if SANITIZER_INTERCEPT_STRTOI
INTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base,
            INTMAX_T low, INTMAX_T high, int *rstatus) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus);
  char *real_endptr;
  INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  if (rstatus)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
  return ret;
}

INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base,
            UINTMAX_T low, UINTMAX_T high, int *rstatus) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus);
  char *real_endptr;
  UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  if (rstatus)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
  return ret;
}
#define INIT_STRTOI                                                            \
  COMMON_INTERCEPT_FUNCTION(strtoi);                                           \
  COMMON_INTERCEPT_FUNCTION(strtou)
#else
#define INIT_STRTOI
#endif

#if SANITIZER_INTERCEPT_CAPSICUM
#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...)          \
  {                                                                        \
    void *ctx;                                                             \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \
    if (rights)                                                            \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));         \
    __sanitizer_cap_rights_t *ret =                                        \
        REAL(cap_rights_init)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                               \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));              \
    return ret;                                                            \
  }

#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...)           \
  {                                                                       \
    void *ctx;                                                            \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \
    if (rights)                                                           \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));        \
    __sanitizer_cap_rights_t *ret =                                       \
        REAL(cap_rights_set)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                              \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));             \
    return ret;                                                           \
  }

#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...)         \
  {                                                                         \
    void *ctx;                                                              \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \
    if (rights)                                                             \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));          \
    __sanitizer_cap_rights_t *ret =                                         \
        REAL(cap_rights_clear)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                                \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));               \
    return ret;                                                             \
  }

#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...)        \
  {                                                                          \
    void *ctx;                                                               \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \
    if (rights)                                                              \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));           \
    return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__);                   \
  }

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights);
}

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights);
}

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights);
}

INTERCEPTOR(bool, cap_rights_is_set,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights);
}

INTERCEPTOR(int, cap_rights_limit, int fd,
            const __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights);
  if (rights)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));

  return REAL(cap_rights_limit)(fd, rights);
}

INTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights);
  int ret = REAL(cap_rights_get)(fd, rights);
  if (!ret && rights)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights));

  return ret;
}

INTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights);
  if (rights)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));

  return REAL(cap_rights_is_valid(rights));
}

INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge,
  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));

  __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));

  return ret;
}

INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove,
  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));

  __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));

  return ret;
}

INTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big,
  const __sanitizer_cap_rights *little) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little);
  if (little)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little));
  if (big)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big));

  return REAL(cap_rights_contains)(big, little);
}

INTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds);
  if (cmds)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds);

  return REAL(cap_ioctls_limit)(fd, cmds, ncmds);
}

INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds);
  int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds);
  if (!ret && cmds)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds);

  return ret;
}
#define INIT_CAPSICUM                          \
  COMMON_INTERCEPT_FUNCTION(cap_rights_init); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_set); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_get);   \
  COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \
  COMMON_INTERCEPT_FUNCTION(cap_ioctls_get);   \
  COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit)
#else
#define INIT_CAPSICUM
#endif

#if SANITIZER_INTERCEPT_SHA1
INTERCEPTOR(void, SHA1Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context);
  REAL(SHA1Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
}
INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  REAL(SHA1Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
}
INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  REAL(SHA1Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
}
INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer);
  if (state)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
  if (buffer)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64);
  REAL(SHA1Transform)(state, buffer);
  if (state)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
}
INTERCEPTOR(char *, SHA1End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  char *ret = REAL(SHA1End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(SHA1File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
  OFF_T length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf);
  if (data)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(SHA1Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
#define INIT_SHA1                                                              \
  COMMON_INTERCEPT_FUNCTION(SHA1Init);                                         \
  COMMON_INTERCEPT_FUNCTION(SHA1Update);                                       \
  COMMON_INTERCEPT_FUNCTION(SHA1Final);                                        \
  COMMON_INTERCEPT_FUNCTION(SHA1Transform);                                    \
  COMMON_INTERCEPT_FUNCTION(SHA1End);                                          \
  COMMON_INTERCEPT_FUNCTION(SHA1File);                                         \
  COMMON_INTERCEPT_FUNCTION(SHA1FileChunk);                                    \
  COMMON_INTERCEPT_FUNCTION(SHA1Data)
#else
#define INIT_SHA1
#endif

#if SANITIZER_INTERCEPT_MD4
INTERCEPTOR(void, MD4Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context);
  REAL(MD4Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
}

INTERCEPTOR(void, MD4Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  REAL(MD4Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
}

INTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  REAL(MD4Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD4End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  char *ret = REAL(MD4End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(MD4File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

INTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD4Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

#define INIT_MD4                                                               \
  COMMON_INTERCEPT_FUNCTION(MD4Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD4Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD4Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD4End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD4File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD4Data)
#else
#define INIT_MD4
#endif

#if SANITIZER_INTERCEPT_RMD160
INTERCEPTOR(void, RMD160Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context);
  REAL(RMD160Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
}
INTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  REAL(RMD160Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
}
INTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  REAL(RMD160Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
}
INTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer);
  if (state)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
  if (buffer)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16);
  REAL(RMD160Transform)(state, buffer);
  if (state)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
}
INTERCEPTOR(char *, RMD160End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  char *ret = REAL(RMD160End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(RMD160File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
  OFF_T length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(RMD160Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
#define INIT_RMD160                                                            \
  COMMON_INTERCEPT_FUNCTION(RMD160Init);                                       \
  COMMON_INTERCEPT_FUNCTION(RMD160Update);                                     \
  COMMON_INTERCEPT_FUNCTION(RMD160Final);                                      \
  COMMON_INTERCEPT_FUNCTION(RMD160Transform);                                  \
  COMMON_INTERCEPT_FUNCTION(RMD160End);                                        \
  COMMON_INTERCEPT_FUNCTION(RMD160File);                                       \
  COMMON_INTERCEPT_FUNCTION(RMD160FileChunk);                                  \
  COMMON_INTERCEPT_FUNCTION(RMD160Data)
#else
#define INIT_RMD160
#endif

#if SANITIZER_INTERCEPT_MD5
INTERCEPTOR(void, MD5Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
  REAL(MD5Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
}

INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  REAL(MD5Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
}

INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  REAL(MD5Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD5End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  char *ret = REAL(MD5End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(MD5File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD5Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

#define INIT_MD5                                                               \
  COMMON_INTERCEPT_FUNCTION(MD5Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD5Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD5Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD5End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD5File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD5Data)
#else
#define INIT_MD5
#endif

#if SANITIZER_INTERCEPT_FSEEK
INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence);
  return REAL(fseek)(stream, offset, whence);
}
INTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence);
  return REAL(fseeko)(stream, offset, whence);
}
INTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream);
  return REAL(ftell)(stream);
}
INTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream);
  return REAL(ftello)(stream);
}
INTERCEPTOR(void, rewind, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream);
  return REAL(rewind)(stream);
}
INTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos);
  int ret = REAL(fgetpos)(stream, pos);
  if (pos && !ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz);
  return ret;
}
INTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos);
  if (pos)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz);
  return REAL(fsetpos)(stream, pos);
}
#define INIT_FSEEK \
  COMMON_INTERCEPT_FUNCTION(fseek); \
  COMMON_INTERCEPT_FUNCTION(fseeko); \
  COMMON_INTERCEPT_FUNCTION(ftell); \
  COMMON_INTERCEPT_FUNCTION(ftello); \
  COMMON_INTERCEPT_FUNCTION(rewind); \
  COMMON_INTERCEPT_FUNCTION(fgetpos); \
  COMMON_INTERCEPT_FUNCTION(fsetpos)
#else
#define INIT_FSEEK
#endif

#if SANITIZER_INTERCEPT_MD2
INTERCEPTOR(void, MD2Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context);
  REAL(MD2Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
}

INTERCEPTOR(void, MD2Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  REAL(MD2Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
}

INTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  REAL(MD2Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD2End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  char *ret = REAL(MD2End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
  char *ret = REAL(MD2File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD2Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

#define INIT_MD2                                                               \
  COMMON_INTERCEPT_FUNCTION(MD2Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD2Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD2Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD2End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD2File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD2Data)
#else
#define INIT_MD2
#endif

#if SANITIZER_INTERCEPT_SHA2
#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
  INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
    REAL(SHA##LEN##_Init)(context); \
    if (context) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
  } \
  INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
              const u8 *data, SIZE_T len) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
    if (data && len > 0) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    REAL(SHA##LEN##_Update)(context, data, len); \
    if (context) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
  } \
  INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
  void *context) { \
    void *ctx; \
    CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    REAL(SHA##LEN##_Final)(digest, context); \
    if (digest) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
                                     sizeof(digest[0]) * \
  SHA##LEN##_digest_length); \
  } \
  INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    char *ret = REAL(SHA##LEN##_End)(context, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
    if (filename) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
    char *ret = REAL(SHA##LEN##_File)(filename, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
              OFF_T offset, OFF_T length) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
  length); \
    if (filename) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
    char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
    if (data && len > 0) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
    char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  }

SHA2_INTERCEPTORS(224, u32)
SHA2_INTERCEPTORS(256, u32)
SHA2_INTERCEPTORS(384, u64)
SHA2_INTERCEPTORS(512, u64)

#define INIT_SHA2_INTECEPTORS(LEN) \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)

#define INIT_SHA2 \
  INIT_SHA2_INTECEPTORS(224); \
  INIT_SHA2_INTECEPTORS(256); \
  INIT_SHA2_INTECEPTORS(384); \
  INIT_SHA2_INTECEPTORS(512)
#undef SHA2_INTERCEPTORS
#else
#define INIT_SHA2
#endif

#if SANITIZER_INTERCEPT_VIS
INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
  char *end = REAL(vis)(dst, c, flag, nextc);
  // dst is NULL terminated and end points to the NULL char
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
  char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
  // nvis cannot make sure the dst is NULL terminated
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int len = REAL(strvis)(dst, src, flag);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int len = REAL(stravis)(dst, src, flag);
  if (dst) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
    if (*dst)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
  }
  return len;
}
INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int len = REAL(strnvis)(dst, dlen, src, flag);
  // The interface will be valid even if there is no space for NULL char
  if (dst && len > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  int ret = REAL(strvisx)(dst, src, len, flag);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag, int *cerr_ptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
  // according to the implementation
  if (cerr_ptr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
  int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  if (cerr_ptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
  return ret;
}
INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  char *end = REAL(svis)(dst, c, flag, nextc, extra);
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
                                   Min((SIZE_T)(end - dst + 1), dlen));
  return end;
}
INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  int len = REAL(strsvis)(dst, src, flag, extra);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
  // The interface will be valid even if there is no space for NULL char
  if (dst && len >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  int ret = REAL(strsvisx)(dst, src, len, flag, extra);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag, const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
            SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
                           cerr_ptr);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
  // according to the implementation
  if (cerr_ptr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
  int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  if (cerr_ptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
  return ret;
}
INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
  if (astate)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
  int ret = REAL(unvis)(cp, c, astate, flag);
  if (ret == unvis_valid || ret == unvis_validpush) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
  }
  return ret;
}
INTERCEPTOR(int, strunvis, char *dst, const char *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int ret = REAL(strunvis)(dst, src);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int ret = REAL(strnunvis)(dst, dlen, src);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int ret = REAL(strunvisx)(dst, src, flag);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
            int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int ret = REAL(strnunvisx)(dst, dlen, src, flag);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
#define INIT_VIS                                                               \
  COMMON_INTERCEPT_FUNCTION(vis);                                              \
  COMMON_INTERCEPT_FUNCTION(nvis);                                             \
  COMMON_INTERCEPT_FUNCTION(strvis);                                           \
  COMMON_INTERCEPT_FUNCTION(stravis);                                          \
  COMMON_INTERCEPT_FUNCTION(strnvis);                                          \
  COMMON_INTERCEPT_FUNCTION(strvisx);                                          \
  COMMON_INTERCEPT_FUNCTION(strnvisx);                                         \
  COMMON_INTERCEPT_FUNCTION(strenvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(svis);                                             \
  COMMON_INTERCEPT_FUNCTION(snvis);                                            \
  COMMON_INTERCEPT_FUNCTION(strsvis);                                          \
  COMMON_INTERCEPT_FUNCTION(strsnvis);                                         \
  COMMON_INTERCEPT_FUNCTION(strsvisx);                                         \
  COMMON_INTERCEPT_FUNCTION(strsnvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(strsenvisx);                                       \
  COMMON_INTERCEPT_FUNCTION(unvis);                                            \
  COMMON_INTERCEPT_FUNCTION(strunvis);                                         \
  COMMON_INTERCEPT_FUNCTION(strnunvis);                                        \
  COMMON_INTERCEPT_FUNCTION(strunvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(strnunvisx)
#else
#define INIT_VIS
#endif

#if SANITIZER_INTERCEPT_CDB
INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
  if (cdbr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
  return cdbr;
}

INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
  int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
    cookie);
  if (base && size)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
  struct __sanitizer_cdbr *cdbr =
    REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
  if (cdbr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
  return cdbr;
}

INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  return REAL(cdbr_entries)(cdbr);
}

INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
            const void **data, SIZE_T *datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
  if (!ret) {
    if (data)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
    if (datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
    if (data && datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
  }
  return ret;
}

INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
            SIZE_T keylen, const void **data, SIZE_T *datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  if (key)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
  if (!ret) {
    if (data)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
    if (datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
    if (data && datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
  }
  return ret;
}

INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  REAL(cdbr_close)(cdbr);
}

INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
  struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
  return ret;
}

INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
  SIZE_T keylen, const void *data, SIZE_T datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (data && datalen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
  if (key && keylen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
  if (!ret && cdbw)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  return ret;
}

INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
  SIZE_T datalen, u32 *index) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (data && datalen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
  int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
  if (!ret) {
    if (index)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
    if (cdbw)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  }
  return ret;
}

INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
  SIZE_T keylen, u32 index) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (key && keylen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
  if (!ret && cdbw)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  return ret;
}

INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
  const char descr[16], u32 (*seedgen)(void)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (descr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
  if (seedgen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
  int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
  if (!ret) {
    if (cdbw)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
    if (output >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
  }
  return ret;
}

INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  REAL(cdbw_close)(cdbw);
}

#define INIT_CDB \
  COMMON_INTERCEPT_FUNCTION(cdbr_open); \
  COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
  COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
  COMMON_INTERCEPT_FUNCTION(cdbr_get); \
  COMMON_INTERCEPT_FUNCTION(cdbr_find); \
  COMMON_INTERCEPT_FUNCTION(cdbr_close); \
  COMMON_INTERCEPT_FUNCTION(cdbw_open); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
  COMMON_INTERCEPT_FUNCTION(cdbw_output); \
  COMMON_INTERCEPT_FUNCTION(cdbw_close)
#else
#define INIT_CDB
#endif

#if SANITIZER_INTERCEPT_GETFSENT
INTERCEPTOR(void *, getfsent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsent);
  void *ret = REAL(getfsent)();
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

INTERCEPTOR(void *, getfsspec, const char *spec) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
  if (spec)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, internal_strlen(spec) + 1);
  void *ret = REAL(getfsspec)(spec);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

INTERCEPTOR(void *, getfsfile, const char *file) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
  if (file)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
  void *ret = REAL(getfsfile)(file);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

#define INIT_GETFSENT \
  COMMON_INTERCEPT_FUNCTION(getfsent); \
  COMMON_INTERCEPT_FUNCTION(getfsspec); \
  COMMON_INTERCEPT_FUNCTION(getfsfile);
#else
#define INIT_GETFSENT
#endif

#if SANITIZER_INTERCEPT_ARC4RANDOM
INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len);
  REAL(arc4random_buf)(buf, len);
  if (buf && len)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len);
}

INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen);
  if (dat && datlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen);
  REAL(arc4random_addrandom)(dat, datlen);
}

#define INIT_ARC4RANDOM \
  COMMON_INTERCEPT_FUNCTION(arc4random_buf); \
  COMMON_INTERCEPT_FUNCTION(arc4random_addrandom);
#else
#define INIT_ARC4RANDOM
#endif

#if SANITIZER_INTERCEPT_POPEN
INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
  if (command)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, command, internal_strlen(command) + 1);
  if (type)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
  __sanitizer_FILE *res = REAL(popen)(command, type);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
#else
#define INIT_POPEN
#endif

#if SANITIZER_INTERCEPT_POPENVE
INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
            char *const *argv, char *const *envp, const char *type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  if (argv) {
    for (char *const *pa = argv; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
    }
  }
  if (envp) {
    for (char *const *pa = envp; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
    }
  }
  if (type)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
  __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
#else
#define INIT_POPENVE
#endif

#if SANITIZER_INTERCEPT_PCLOSE
INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  const FileMetadata *m = GetInterceptorMetadata(fp);
  int res = REAL(pclose)(fp);
  if (m) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
    DeleteInterceptorMetadata(fp);
  }
  return res;
}
#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
#else
#define INIT_PCLOSE
#endif

#if SANITIZER_INTERCEPT_FUNOPEN
typedef int (*funopen_readfn)(void *cookie, char *buf, int len);
typedef int (*funopen_writefn)(void *cookie, const char *buf, int len);
typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence);
typedef int (*funopen_closefn)(void *cookie);

struct WrappedFunopenCookie {
  void *real_cookie;
  funopen_readfn real_read;
  funopen_writefn real_write;
  funopen_seekfn real_seek;
  funopen_closefn real_close;
};

static int wrapped_funopen_read(void *cookie, char *buf, int len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_readfn real_read = wrapped_cookie->real_read;
  return real_read(wrapped_cookie->real_cookie, buf, len);
}

static int wrapped_funopen_write(void *cookie, const char *buf, int len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_writefn real_write = wrapped_cookie->real_write;
  return real_write(wrapped_cookie->real_cookie, buf, len);
}

static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_seekfn real_seek = wrapped_cookie->real_seek;
  return real_seek(wrapped_cookie->real_cookie, offset, whence);
}

static int wrapped_funopen_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_closefn real_close = wrapped_cookie->real_close;
  int res = real_close(wrapped_cookie->real_cookie);
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn,
            funopen_writefn writefn, funopen_seekfn seekfn,
            funopen_closefn closefn) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn,
                           closefn);

  WrappedFunopenCookie *wrapped_cookie =
      (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_read = readfn;
  wrapped_cookie->real_write = writefn;
  wrapped_cookie->real_seek = seekfn;
  wrapped_cookie->real_close = closefn;

  __sanitizer_FILE *res =
      REAL(funopen)(wrapped_cookie,
                    readfn  ? wrapped_funopen_read  : nullptr,
                    writefn ? wrapped_funopen_write : nullptr,
                    seekfn  ? wrapped_funopen_seek  : nullptr,
                    closefn ? wrapped_funopen_close : nullptr);
  if (res)
    unpoison_file(res);
  return res;
}
#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen)
#else
#define INIT_FUNOPEN
#endif

#if SANITIZER_INTERCEPT_FUNOPEN2
typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len);
typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len);
typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence);
typedef int (*funopen2_flushfn)(void *cookie);
typedef int (*funopen2_closefn)(void *cookie);

struct WrappedFunopen2Cookie {
  void *real_cookie;
  funopen2_readfn real_read;
  funopen2_writefn real_write;
  funopen2_seekfn real_seek;
  funopen2_flushfn real_flush;
  funopen2_closefn real_close;
};

static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_readfn real_read = wrapped_cookie->real_read;
  return real_read(wrapped_cookie->real_cookie, buf, len);
}

static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf,
                                      SIZE_T len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_writefn real_write = wrapped_cookie->real_write;
  return real_write(wrapped_cookie->real_cookie, buf, len);
}

static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_seekfn real_seek = wrapped_cookie->real_seek;
  return real_seek(wrapped_cookie->real_cookie, offset, whence);
}

static int wrapped_funopen2_flush(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_flushfn real_flush = wrapped_cookie->real_flush;
  return real_flush(wrapped_cookie->real_cookie);
}

static int wrapped_funopen2_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_closefn real_close = wrapped_cookie->real_close;
  int res = real_close(wrapped_cookie->real_cookie);
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn,
            funopen2_writefn writefn, funopen2_seekfn seekfn,
            funopen2_flushfn flushfn, funopen2_closefn closefn) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn,
                           flushfn, closefn);

  WrappedFunopen2Cookie *wrapped_cookie =
      (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_read = readfn;
  wrapped_cookie->real_write = writefn;
  wrapped_cookie->real_seek = seekfn;
  wrapped_cookie->real_flush = flushfn;
  wrapped_cookie->real_close = closefn;

  __sanitizer_FILE *res =
      REAL(funopen2)(wrapped_cookie,
                     readfn  ? wrapped_funopen2_read  : nullptr,
                     writefn ? wrapped_funopen2_write : nullptr,
                     seekfn  ? wrapped_funopen2_seek  : nullptr,
                     flushfn ? wrapped_funopen2_flush : nullptr,
                     closefn ? wrapped_funopen2_close : nullptr);
  if (res)
    unpoison_file(res);
  return res;
}
#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2)
#else
#define INIT_FUNOPEN2
#endif

#if SANITIZER_INTERCEPT_FDEVNAME
INTERCEPTOR(char *, fdevname,  int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  char *name = REAL(fdevname)(fd);
  if (name) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
    if (fd > 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return name;
}

INTERCEPTOR(char *, fdevname_r,  int fd, char *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  char *name = REAL(fdevname_r)(fd, buf, len);
  if (name && buf && len > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
    if (fd > 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return name;
}

#define INIT_FDEVNAME \
  COMMON_INTERCEPT_FUNCTION(fdevname); \
  COMMON_INTERCEPT_FUNCTION(fdevname_r);
#else
#define INIT_FDEVNAME
#endif

#if SANITIZER_INTERCEPT_GETUSERSHELL
INTERCEPTOR(char *, getusershell) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
  char *res = REAL(getusershell)();
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}

#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell);
#else
#define INIT_GETUSERSHELL
#endif

#if SANITIZER_INTERCEPT_SL_INIT
INTERCEPTOR(void *, sl_init) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_init);
  void *res = REAL(sl_init)();
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz);
  return res;
}

INTERCEPTOR(int, sl_add, void *sl, char *item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  if (item)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
  int res = REAL(sl_add)(sl, item);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  return res;
}

INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  if (item)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
  char *res = REAL(sl_find)(sl, item);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
  return res;
}

INTERCEPTOR(void, sl_free, void *sl, int freeall) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  REAL(sl_free)(sl, freeall);
}

#define INIT_SL_INIT                  \
  COMMON_INTERCEPT_FUNCTION(sl_init); \
  COMMON_INTERCEPT_FUNCTION(sl_add);  \
  COMMON_INTERCEPT_FUNCTION(sl_find); \
  COMMON_INTERCEPT_FUNCTION(sl_free);
#else
#define INIT_SL_INIT
#endif

#if SANITIZER_INTERCEPT_GETRANDOM
INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
  SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
  if (n > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
  }
  return n;
}
#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom)
#else
#define INIT_GETRANDOM
#endif

#if SANITIZER_INTERCEPT_GETENTROPY
INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
  int r = REAL(getentropy)(buf, buflen);
  if (r == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  return r;
}
#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
#else
#define INIT_GETENTROPY
#endif

#if SANITIZER_INTERCEPT_QSORT_R
typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
struct qsort_r_compar_params {
  SIZE_T size;
  qsort_r_compar_f compar;
  void *arg;
};
static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
  qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size);
  return params->compar(a, b, params->arg);
}

INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_r_compar_f compar, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
  // Run the comparator over all array elements to detect any memory issues.
  if (nmemb > 1) {
    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
      void *p = (void *)((char *)base + i * size);
      void *q = (void *)((char *)base + (i + 1) * size);
      COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
      compar(p, q, arg);
    }
  }
  qsort_r_compar_params params = {size, compar, arg};
  REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, &params);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
}
#  define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
#else
#  define INIT_QSORT_R
#endif

#if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_r_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
  WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
}
#  define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
#elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
// Poisoned memory from there may get copied into the comparator arguments,
// where it needs to be dealt with. But even that is not enough - the results of
// the sort may be copied into the input/output array based on the results of
// the comparator calls, but directly from the temp memory, bypassing the
// unpoisoning done in wrapped_qsort_compar. We deal with this by, again,
// unpoisoning the entire array after the sort is done.
//
// We can not check that the entire array is initialized at the beginning. IMHO,
// it's fine for parts of the sorted objects to contain uninitialized memory,
// ex. as padding in structs.
typedef int (*qsort_compar_f)(const void *, const void *);
static THREADLOCAL qsort_compar_f qsort_compar;
static THREADLOCAL SIZE_T qsort_size;
static int wrapped_qsort_compar(const void *a, const void *b) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
  return qsort_compar(a, b);
}

INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
  // Run the comparator over all array elements to detect any memory issues.
  if (nmemb > 1) {
    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
      void *p = (void *)((char *)base + i * size);
      void *q = (void *)((char *)base + (i + 1) * size);
      COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
      compar(p, q);
    }
  }
  qsort_compar_f old_compar = qsort_compar;
  SIZE_T old_size = qsort_size;
  // Handle qsort() implementations that recurse using an
  // interposable function call:
  bool already_wrapped = compar == wrapped_qsort_compar;
  if (already_wrapped) {
    // This case should only happen if the qsort() implementation calls itself
    // using a preemptible function call (e.g. the FreeBSD libc version).
    // Check that the size and comparator arguments are as expected.
    CHECK_NE(compar, qsort_compar);
    CHECK_EQ(qsort_size, size);
  } else {
    qsort_compar = compar;
    qsort_size = size;
  }
  REAL(qsort)(base, nmemb, size, wrapped_qsort_compar);
  if (!already_wrapped) {
    qsort_compar = old_compar;
    qsort_size = old_size;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
}
#  define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
#else
#  define INIT_QSORT
#endif

#if SANITIZER_INTERCEPT_BSEARCH
typedef int (*bsearch_compar_f)(const void *, const void *);
struct bsearch_compar_params {
  const void *key;
  bsearch_compar_f compar;
};

static int wrapped_bsearch_compar(const void *key, const void *b) {
  const bsearch_compar_params *params = (const bsearch_compar_params *)key;
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  return params->compar(params->key, b);
}

INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
            SIZE_T size, bsearch_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
  bsearch_compar_params params = {key, compar};
  return REAL(bsearch)(&params, base, nmemb, size, wrapped_bsearch_compar);
}
#  define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
#else
#  define INIT_BSEARCH
#endif

#if SANITIZER_INTERCEPT_SIGALTSTACK
INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss);
  int r = REAL(sigaltstack)(ss, oss);
  if (r == 0 && oss != nullptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz);
  }
  return r;
}
#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack)
#else
#define INIT_SIGALTSTACK
#endif

#if SANITIZER_INTERCEPT_PROCCTL
INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data);
   static const int PROC_REAP_ACQUIRE = 2;
   static const int PROC_REAP_RELEASE = 3;
   static const int PROC_REAP_STATUS = 4;
   static const int PROC_REAP_GETPIDS = 5;
   static const int PROC_REAP_KILL = 6;
   if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) {
     COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int));
   } else {
     // reap_acquire/reap_release bears no arguments.
     if (cmd > PROC_REAP_RELEASE) {
       unsigned int reapsz;
       switch (cmd) {
       case PROC_REAP_STATUS:
         reapsz = struct_procctl_reaper_status_sz;
         break;
       case PROC_REAP_GETPIDS:
         reapsz = struct_procctl_reaper_pids_sz;
         break;
       case PROC_REAP_KILL:
         reapsz = struct_procctl_reaper_kill_sz;
         break;
       }
       COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz);
     }
   }
   return REAL(procctl)(idtype, id, cmd, data);
}
#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl)
#else
#define INIT_PROCCTL
#endif

#if SANITIZER_INTERCEPT_UNAME
INTERCEPTOR(int, uname, struct utsname *utsname) {
#if SANITIZER_LINUX
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_uname(utsname);
#endif
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, uname, utsname);
  int res = REAL(uname)(utsname);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
                                   __sanitizer::struct_utsname_sz);
  return res;
}
#define INIT_UNAME COMMON_INTERCEPT_FUNCTION(uname)
#else
#define INIT_UNAME
#endif

#if SANITIZER_INTERCEPT___XUNAME
// FreeBSD's <sys/utsname.h> define uname() as
// static __inline int uname(struct utsname *name) {
//   return __xuname(SYS_NMLN, (void*)name);
// }
INTERCEPTOR(int, __xuname, int size, void *utsname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xuname, size, utsname);
  int res = REAL(__xuname)(size, utsname);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
                                   __sanitizer::struct_utsname_sz);
  return res;
}
#define INIT___XUNAME COMMON_INTERCEPT_FUNCTION(__xuname)
#else
#define INIT___XUNAME
#endif

#if SANITIZER_INTERCEPT_HEXDUMP
INTERCEPTOR(void, hexdump, const void *ptr, int length, const char *header, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, hexdump, ptr, length, header, flags);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, length);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, header, internal_strlen(header) + 1);
  REAL(hexdump)(ptr, length, header, flags);
}

#define INIT_HEXDUMP COMMON_INTERCEPT_FUNCTION(hexdump);
#else
#define INIT_HEXDUMP
#endif

#if SANITIZER_INTERCEPT_ARGP_PARSE
INTERCEPTOR(int, argp_parse, const struct argp *argp, int argc, char **argv,
            unsigned flags, int *arg_index, void *input) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, argp_parse, argp, argc, argv, flags, arg_index,
                           input);
  for (int i = 0; i < argc; i++)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, argv[i], internal_strlen(argv[i]) + 1);
  int res = REAL(argp_parse)(argp, argc, argv, flags, arg_index, input);
  if (!res && arg_index)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg_index, sizeof(int));
  return res;
}

#define INIT_ARGP_PARSE COMMON_INTERCEPT_FUNCTION(argp_parse);
#else
#define INIT_ARGP_PARSE
#endif

#if SANITIZER_INTERCEPT_CPUSET_GETAFFINITY
INTERCEPTOR(int, cpuset_getaffinity, int level, int which, __int64_t id, SIZE_T cpusetsize, __sanitizer_cpuset_t *mask) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cpuset_getaffinity, level, which, id, cpusetsize, mask);
  int res = REAL(cpuset_getaffinity)(level, which, id, cpusetsize, mask);
  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
  return res;
}
#define INIT_CPUSET_GETAFFINITY COMMON_INTERCEPT_FUNCTION(cpuset_getaffinity);
#else
#define INIT_CPUSET_GETAFFINITY
#endif

#include "sanitizer_common_interceptors_netbsd_compat.inc"

namespace __sanitizer {
void InitializeMemintrinsicInterceptors();
}  // namespace __sanitizer

static void InitializeCommonInterceptors() {
#if SI_POSIX
  static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
  interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
#endif

  __sanitizer::InitializeMemintrinsicInterceptors();

  INIT_MMAP;
  INIT_MMAP64;
  INIT_TEXTDOMAIN;
  INIT_STRLEN;
  INIT_STRNLEN;
  INIT_STRNDUP;
  INIT___STRNDUP;
  INIT_STRCMP;
  INIT_STRNCMP;
  INIT_STRCASECMP;
  INIT_STRNCASECMP;
  INIT_STRSTR;
  INIT_STRCASESTR;
  INIT_STRCHR;
  INIT_STRCHRNUL;
  INIT_STRRCHR;
  INIT_STRSPN;
  INIT_STRTOK;
  INIT_STRPBRK;
  INIT_STRXFRM;
  INIT___STRXFRM_L;
  INIT_MEMCHR;
  INIT_MEMCMP;
  INIT_BCMP;
  INIT_MEMRCHR;
  INIT_MEMMEM;
  INIT_READ;
  INIT_FREAD;
  INIT_PREAD;
  INIT_PREAD64;
  INIT_READV;
  INIT_PREADV;
  INIT_PREADV64;
  INIT_WRITE;
  INIT_FWRITE;
  INIT_PWRITE;
  INIT_PWRITE64;
  INIT_WRITEV;
  INIT_PWRITEV;
  INIT_PWRITEV64;
  INIT_FGETS;
  INIT_FPUTS;
  INIT_PUTS;
  INIT_PRCTL;
  INIT_LOCALTIME_AND_FRIENDS;
  INIT_STRPTIME;
  INIT_SCANF;
  INIT_ISOC99_SCANF;
  INIT_PRINTF;
  INIT_PRINTF_L;
  INIT_ISOC99_PRINTF;
  INIT_FREXP;
  INIT_FREXPF_FREXPL;
  INIT_GETPWNAM_AND_FRIENDS;
  INIT_GETPWNAM_R_AND_FRIENDS;
  INIT_GETPWENT;
  INIT_FGETPWENT;
  INIT_GETPWENT_R;
  INIT_FGETPWENT_R;
  INIT_FGETGRENT_R;
  INIT_SETPWENT;
  INIT_CLOCK_GETTIME;
  INIT_CLOCK_GETCPUCLOCKID;
  INIT_GETITIMER;
  INIT_TIME;
  INIT_GLOB;
  INIT_GLOB64;
  INIT___B64_TO;
  INIT_DN_COMP_EXPAND;
  INIT_POSIX_SPAWN;
  INIT_WAIT;
  INIT_WAIT4;
  INIT_INET;
  INIT_PTHREAD_GETSCHEDPARAM;
  INIT_GETADDRINFO;
  INIT_GETNAMEINFO;
  INIT_GETSOCKNAME;
  INIT_GETHOSTBYNAME;
  INIT_GETHOSTBYNAME2;
  INIT_GETHOSTBYNAME_R;
  INIT_GETHOSTBYNAME2_R;
  INIT_GETHOSTBYADDR_R;
  INIT_GETHOSTENT_R;
  INIT_GETSOCKOPT;
  INIT_ACCEPT;
  INIT_ACCEPT4;
  INIT_PACCEPT;
  INIT_MODF;
  INIT_RECVMSG;
  INIT_SENDMSG;
  INIT_RECVMMSG;
  INIT_SENDMMSG;
  INIT_SYSMSG;
  INIT_GETPEERNAME;
  INIT_IOCTL;
  INIT_INET_ATON;
  INIT_SYSINFO;
  INIT_READDIR;
  INIT_READDIR64;
  INIT_PTRACE;
  INIT_SETLOCALE;
  INIT_GETCWD;
  INIT_GET_CURRENT_DIR_NAME;
  INIT_STRTOIMAX;
  INIT_STRTOIMAX_C23;
  INIT_MBSTOWCS;
  INIT_MBSNRTOWCS;
  INIT_WCSTOMBS;
  INIT_WCSNRTOMBS;
  INIT_WCRTOMB;
  INIT_WCTOMB;
  INIT_TCGETATTR;
  INIT_REALPATH;
  INIT_CANONICALIZE_FILE_NAME;
  INIT_CONFSTR;
  INIT_SCHED_GETAFFINITY;
  INIT_SCHED_GETPARAM;
  INIT_STRERROR;
  INIT_STRERROR_R;
  INIT_XPG_STRERROR_R;
  INIT_SCANDIR;
  INIT_SCANDIR64;
  INIT_GETGROUPS;
  INIT_POLL;
  INIT_PPOLL;
  INIT_WORDEXP;
  INIT_SIGWAIT;
  INIT_SIGWAITINFO;
  INIT_SIGTIMEDWAIT;
  INIT_SIGSETOPS;
  INIT_SIGSET_LOGICOPS;
  INIT_SIGPENDING;
  INIT_SIGPROCMASK;
  INIT_PTHREAD_SIGMASK;
  INIT_BACKTRACE;
  INIT__EXIT;
  INIT___LIBC_THR_SETCANCELSTATE;
  INIT_GETMNTENT;
  INIT_GETMNTENT_R;
  INIT_STATFS;
  INIT_STATFS64;
  INIT_STATVFS;
  INIT_STATVFS64;
  INIT_INITGROUPS;
  INIT_ETHER_NTOA_ATON;
  INIT_ETHER_HOST;
  INIT_ETHER_R;
  INIT_SHMCTL;
  INIT_RANDOM_R;
  INIT_PTHREAD_ATTR_GET;
  INIT_PTHREAD_ATTR_GET_SCHED;
  INIT_PTHREAD_ATTR_GETINHERITSCHED;
  INIT_PTHREAD_ATTR_GETAFFINITY_NP;
  INIT_PTHREAD_GETAFFINITY_NP;
  INIT_PTHREAD_MUTEXATTR_GETPSHARED;
  INIT_PTHREAD_MUTEXATTR_GETTYPE;
  INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
  INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
  INIT_PTHREAD_MUTEXATTR_GETROBUST;
  INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
  INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
  INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
  INIT_PTHREAD_CONDATTR_GETPSHARED;
  INIT_PTHREAD_CONDATTR_GETCLOCK;
  INIT_PTHREAD_BARRIERATTR_GETPSHARED;
  INIT_TMPNAM;
  INIT_TMPNAM_R;
  INIT_PTSNAME;
  INIT_PTSNAME_R;
  INIT_TTYNAME;
  INIT_TTYNAME_R;
  INIT_TEMPNAM;
  INIT_PTHREAD_SETNAME_NP;
  INIT_PTHREAD_GETNAME_NP;
  INIT_SINCOS;
  INIT_REMQUO;
  INIT_REMQUOL;
  INIT_LGAMMA;
  INIT_LGAMMAL;
  INIT_LGAMMA_R;
  INIT_LGAMMAL_R;
  INIT_DRAND48_R;
  INIT_RAND_R;
  INIT_GETLINE;
  INIT_ICONV;
  INIT_TIMES;
  INIT_TLS_GET_ADDR;
  INIT_LISTXATTR;
  INIT_GETXATTR;
  INIT_GETRESID;
  INIT_GETIFADDRS;
  INIT_IF_INDEXTONAME;
  INIT_CAPGET;
  INIT_FTIME;
  INIT_XDR;
  INIT_XDRREC_LINUX;
  INIT_TSEARCH;
  INIT_LIBIO_INTERNALS;
  INIT_FOPEN;
  INIT_FOPEN64;
  INIT_FLOPEN;
  INIT_OPEN_MEMSTREAM;
  INIT_OBSTACK;
  INIT_FFLUSH;
  INIT_FCLOSE;
  INIT_DLOPEN_DLCLOSE;
  INIT_GETPASS;
  INIT_TIMERFD;
  INIT_MLOCKX;
  INIT_FOPENCOOKIE;
  INIT_SEM;
  INIT_PTHREAD_SETCANCEL;
  INIT_MINCORE;
  INIT_PROCESS_VM_READV;
  INIT_CTERMID;
  INIT_CTERMID_R;
  INIT_RECV_RECVFROM;
  INIT_SEND_SENDTO;
  INIT_STAT;
  INIT_STAT64;
  INIT_EVENTFD_READ_WRITE;
  INIT_LSTAT;
  INIT_LSTAT64;
  INIT___XSTAT;
  INIT___XSTAT64;
  INIT___LXSTAT;
  INIT___LXSTAT64;
  // FIXME: add other *stat interceptors.
  INIT_UTMP;
  INIT_UTMPX;
  INIT_GETLOADAVG;
  INIT_WCSLEN;
  INIT_WCSCAT;
  INIT_WCSDUP;
  INIT_WCSXFRM;
  INIT___WCSXFRM_L;
  INIT_ACCT;
  INIT_USER_FROM_UID;
  INIT_UID_FROM_USER;
  INIT_GROUP_FROM_GID;
  INIT_GID_FROM_GROUP;
  INIT_ACCESS;
  INIT_FACCESSAT;
  INIT_GETGROUPLIST;
  INIT_GETGROUPMEMBERSHIP;
  INIT_READLINK;
  INIT_READLINKAT;
  INIT_NAME_TO_HANDLE_AT;
  INIT_OPEN_BY_HANDLE_AT;
  INIT_STRLCPY;
  INIT_DEVNAME;
  INIT_DEVNAME_R;
  INIT_FGETLN;
  INIT_STRMODE;
  INIT_TTYENT;
  INIT_PROTOENT;
  INIT_PROTOENT_R;
  INIT_NETENT;
  INIT_GETMNTINFO;
  INIT_MI_VECTOR_HASH;
  INIT_SETVBUF;
  INIT_GETVFSSTAT;
  INIT_REGEX;
  INIT_REGEXSUB;
  INIT_FTS;
  INIT_SYSCTL;
  INIT_ASYSCTL;
  INIT_SYSCTLGETMIBINFO;
  INIT_NL_LANGINFO;
  INIT_MODCTL;
  INIT_STRTONUM;
  INIT_FPARSELN;
  INIT_STATVFS1;
  INIT_STRTOI;
  INIT_CAPSICUM;
  INIT_SHA1;
  INIT_MD4;
  INIT_RMD160;
  INIT_MD5;
  INIT_FSEEK;
  INIT_MD2;
  INIT_SHA2;
  INIT_VIS;
  INIT_CDB;
  INIT_GETFSENT;
  INIT_ARC4RANDOM;
  INIT_POPEN;
  INIT_POPENVE;
  INIT_PCLOSE;
  INIT_FUNOPEN;
  INIT_FUNOPEN2;
  INIT_FDEVNAME;
  INIT_GETUSERSHELL;
  INIT_SL_INIT;
  INIT_GETRANDOM;
  INIT_GETENTROPY;
  INIT_QSORT;
  INIT_QSORT_R;
  INIT_BSEARCH;
  INIT_SIGALTSTACK;
  INIT_PROCCTL
  INIT_UNAME;
  INIT___XUNAME;
  INIT_HEXDUMP;
  INIT_ARGP_PARSE;
  INIT_CPUSET_GETAFFINITY;

  INIT___PRINTF_CHK;
}
@


1.14
log
@initial merge of GCC 12.3.0.

this doesn't include any of the changes to the .c -> .cc files renamed,
and reverts our local changes to the vax port and libsanitizer subdir.
vax GCC was rewritten and our local fixes no longer are relevant, and
the new libsanitizer is more updated than our old one, and merging via
gcc10->gcc12 is not really possible.

unfortunately, our local changes to libsanitizer that aren't related
to the general update of those sources (ie, the netbsd code) will need
to be re-checked and perhaps re-ported.
@
text
@d24 1
a24 1
//   COMMON_INTERCEPTOR_ON_DLOPEN
a25 4
//   COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
//   COMMON_INTERCEPTOR_MUTEX_POST_LOCK
//   COMMON_INTERCEPTOR_MUTEX_UNLOCK
//   COMMON_INTERCEPTOR_MUTEX_REPAIR
a28 3
//   COMMON_INTERCEPTOR_MEMSET_IMPL
//   COMMON_INTERCEPTOR_MEMMOVE_IMPL
//   COMMON_INTERCEPTOR_MEMCPY_IMPL
d30 1
d36 2
d40 1
a46 2
#include <stdarg.h>

d130 69
a198 8
// Platform-specific options.
#if SANITIZER_MAC
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
#elif SANITIZER_WINDOWS64
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
#else
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
#endif  // SANITIZER_MAC
a211 20
#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
#endif

d245 3
a247 3
#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
  CheckNoDeepBind(filename, flag);
a294 41
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
  {                                                       \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)        \
      return internal_memset(dst, v, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);  \
    if (common_flags()->intercept_intrin)                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);     \
    return REAL(memset)(dst, v, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
  {                                                          \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)           \
      return internal_memmove(dst, src, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                  \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);        \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);         \
    }                                                        \
    return REAL(memmove)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
  {                                                         \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {        \
      return internal_memmove(dst, src, size);              \
    }                                                       \
    COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);       \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);        \
    }                                                       \
    return REAL(memcpy)(dst, src, size);                    \
  }
#endif

d301 5
d318 5
a322 3
  COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);               \
  internal_memcpy(new_mem, s, copy_length);                                   \
  new_mem[copy_length] = '\0';                                                \
d449 1
a449 1
#if SANITIZER_INTERCEPT_STRCMP
d453 1
d455 1
a799 51
#if SANITIZER_INTERCEPT_MEMSET
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
}

#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
#else
#define INIT_MEMSET
#endif

#if SANITIZER_INTERCEPT_MEMMOVE
INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
}

#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
#else
#define INIT_MEMMOVE
#endif

#if SANITIZER_INTERCEPT_MEMCPY
INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
  // On OS X, calling internal_memcpy here will cause memory corruptions,
  // because memcpy and memmove are actually aliases of the same
  // implementation.  We need to use internal_memmove here.
  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
  // due to memcpy being an alias of memmove on OS X.
  void *ctx;
#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
    COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
#else
    COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
#endif
}

#define INIT_MEMCPY                                  \
  do {                                               \
    if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
      COMMON_INTERCEPT_FUNCTION(memcpy);             \
    } else {                                         \
      ASSIGN_REAL(memcpy, memmove);                  \
    }                                                \
    CHECK(REAL(memcpy));                             \
  } while (false)

#else
#define INIT_MEMCPY
#endif

d1220 1
a1220 1
  if (!SANITIZER_MAC || s) {  // `fputs(NULL, file)` is supported on Darwin.
d1235 1
a1235 1
  if (!SANITIZER_MAC || s) {  // `puts(NULL)` is supported on Darwin.
d1251 8
a1258 1
  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
d1264 2
d1497 10
d1527 9
d1559 7
a1565 1
  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
d1868 1
a1868 1
#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD
d2412 76
d3349 2
a3350 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
d3365 1
a3365 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
d3386 2
a3387 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
d3402 1
a3402 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
a3569 1

d3571 4
a3574 6
INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
d3576 1
a3576 1
  INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
d3581 5
d3589 1
a3589 7
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *real_endptr;
  UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  return res;
d3599 19
d3922 1
a3922 1
    SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD ||                 \
d3955 1
a3955 1
       //SANITIZER_MAC
d3989 1
a3989 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
d3997 1
a3997 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
d3999 1
a3999 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
d4023 1
a4023 1
                                     (*namelist)[i]->d_reclen);
d4042 1
a4042 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
d4050 1
a4050 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
d4052 1
a4052 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
d4077 1
a4077 1
                                     (*namelist)[i]->d_reclen);
d4354 6
a4359 5
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(backtrace)(buffer, size);
  if (res && buffer)
d4361 3
d4372 2
a4373 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
a4403 67
#if SANITIZER_INTERCEPT_PTHREAD_MUTEX
INTERCEPTOR(int, pthread_mutex_lock, void *m) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
  int res = REAL(pthread_mutex_lock)(m);
  if (res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
  if (res == 0 || res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
}

INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
  int res = REAL(pthread_mutex_unlock)(m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
}

#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
#define INIT_PTHREAD_MUTEX_UNLOCK \
  COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
#else
#define INIT_PTHREAD_MUTEX_LOCK
#define INIT_PTHREAD_MUTEX_UNLOCK
#endif

#if SANITIZER_INTERCEPT___PTHREAD_MUTEX
INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m);
  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
  int res = REAL(__pthread_mutex_lock)(m);
  if (res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
  if (res == 0 || res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
}

INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m);
  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
  int res = REAL(__pthread_mutex_unlock)(m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
}

#define INIT___PTHREAD_MUTEX_LOCK \
  COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock)
#define INIT___PTHREAD_MUTEX_UNLOCK \
  COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock)
#else
#define INIT___PTHREAD_MUTEX_LOCK
#define INIT___PTHREAD_MUTEX_UNLOCK
#endif

a4404 6
INTERCEPTOR(int, __libc_mutex_lock, void *m)
ALIAS(WRAPPER_NAME(pthread_mutex_lock));

INTERCEPTOR(int, __libc_mutex_unlock, void *m)
ALIAS(WRAPPER_NAME(pthread_mutex_unlock));

d4406 1
a4406 1
ALIAS(WRAPPER_NAME(pthread_setcancelstate));
a4407 2
#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock)
#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock)
a4410 2
#define INIT___LIBC_MUTEX_LOCK
#define INIT___LIBC_MUTEX_UNLOCK
d4850 21
d5437 1
a5437 3
extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
                          visibility("default")))
void *__tls_get_addr_opt(void *arg);
a5470 2
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
d5473 5
a5477 3
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
                          visibility("hidden")))
uptr __tls_get_addr_hidden(void *arg);
d5484 1
a5484 2
  ".type __tls_get_offset, @@function\n"
  "__tls_get_offset:\n"
d5713 4
a5716 2
  if (res == 0 && datap)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
d5727 4
a5730 2
  if (datap)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
a5739 99
#if SANITIZER_INTERCEPT_AEABI_MEM
INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
}

INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
}

INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
}

INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
}

INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
}

INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
}

// Note the argument order.
INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
}

INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
}

INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
}

INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
}

INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
}

INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
}

#define INIT_AEABI_MEM                         \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy);   \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memset);   \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memset4);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memset8);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr);   \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
#else
#define INIT_AEABI_MEM
#endif  // SANITIZER_INTERCEPT_AEABI_MEM

#if SANITIZER_INTERCEPT___BZERO
INTERCEPTOR(void *, __bzero, void *block, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
}
#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
#else
#define INIT___BZERO
#endif  // SANITIZER_INTERCEPT___BZERO

#if SANITIZER_INTERCEPT_BZERO
INTERCEPTOR(void *, bzero, void *block, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
}
#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
#else
#define INIT_BZERO
#endif  // SANITIZER_INTERCEPT_BZERO

d6311 31
a6341 3
  if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
  COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
  void *res = REAL(dlopen)(filename, flag);
d6510 1
a6510 1
  // interceptors bind to the lowest symbols version by default, hitting the
d6832 17
d6865 16
d7053 1
d7072 3
d7483 8
d7503 1
d7641 1
a7641 2
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                  pp_size * sizeof(char **));
d7747 1
a7747 2
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
                                   nn_size * sizeof(char **));
d7768 1
a7768 2
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
                                   nn_size * sizeof(char **));
d7787 1
a7787 2
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
                                   nn_size * sizeof(char **));
d7860 1
a7860 1
INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, int mode) {
d7862 2
a7863 2
  COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, mode);
  REAL(setbuffer)(stream, buf, mode);
d7865 1
a7865 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
d7907 1
a7907 1
  if (!res)
a9978 35
#if SANITIZER_INTERCEPT_CRYPT
INTERCEPTOR(char *, crypt, char *key, char *salt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
  char *res = REAL(crypt)(key, salt);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
#else
#define INIT_CRYPT
#endif

#if SANITIZER_INTERCEPT_CRYPT_R
INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
  char *res = REAL(crypt_r)(key, salt, data);
  if (res != nullptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
                                   __sanitizer::struct_crypt_data_sz);
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  }
  return res;
}
#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
#else
#define INIT_CRYPT_R
#endif

d10141 36
d10215 46
d10263 4
d10273 2
a10295 3
  INIT_MEMSET;
  INIT_MEMMOVE;
  INIT_MEMCPY;
d10342 2
d10379 1
a10410 6
  INIT_PTHREAD_MUTEX_LOCK;
  INIT_PTHREAD_MUTEX_UNLOCK;
  INIT___PTHREAD_MUTEX_LOCK;
  INIT___PTHREAD_MUTEX_UNLOCK;
  INIT___LIBC_MUTEX_LOCK;
  INIT___LIBC_MUTEX_UNLOCK;
d10428 1
a10467 3
  INIT_AEABI_MEM;
  INIT___BZERO;
  INIT_BZERO;
d10494 1
d10497 1
a10569 2
  INIT_CRYPT;
  INIT_CRYPT_R;
d10575 1
d10578 3
@


1.13
log
@revert sanitizer back to the version we were using with GCC 9, since
that one was already newer than the GCC 10 version.
@
text
@d137 1
a137 1
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
d139 1
a139 1
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
d141 1
a141 1
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
d207 1
a207 1
      common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
d242 17
d438 1
a438 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
d465 4
a468 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
d578 2
a579 2
    uptr len1 = REAL(strlen)(s1);
    uptr len2 = REAL(strlen)(s2);
d643 1
a643 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
d646 1
a646 1
                                  REAL(strlen)(delimiters) + 1);
d660 1
a660 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
d664 1
a664 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
d709 1
a709 1
      (result ? result - s : REAL(strlen)(s)) + 1);
d740 1
a740 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d754 1
a754 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
d765 1
a765 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
d784 1
a784 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
d786 1
a786 1
        r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
d826 1
a826 1
  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
d828 1
a828 1
  } else {
d830 1
a830 1
  }
d960 1
d973 1
a973 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
d975 1
a975 1
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
d982 1
a982 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
d984 1
a984 1
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
d1254 1
a1254 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
d1268 1
a1268 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d1283 1
a1283 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d1337 1
a1337 1
                                        REAL(strlen(tm->tm_zone)) + 1);
d1390 1
a1390 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d1403 1
a1403 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d1416 1
a1416 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d1429 1
a1429 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d1466 1
a1466 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
d1846 1
a1846 1
    VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
d1848 1
a1848 1
      Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
d1872 1
a1872 1
                                     REAL(strlen)(pwd->pw_name) + 1);
d1875 1
a1875 1
                                     REAL(strlen)(pwd->pw_passwd) + 1);
d1879 1
a1879 1
                                     REAL(strlen)(pwd->pw_gecos) + 1);
d1881 1
a1881 1
#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
d1884 1
a1884 1
                                     REAL(strlen)(pwd->pw_class) + 1);
d1888 1
a1888 1
                                     REAL(strlen)(pwd->pw_dir) + 1);
d1891 1
a1891 1
                                     REAL(strlen)(pwd->pw_shell) + 1);
d1900 1
a1900 1
                                     REAL(strlen)(grp->gr_name) + 1);
d1903 1
a1903 1
                                     REAL(strlen)(grp->gr_passwd) + 1);
d1906 1
a1906 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
d1919 1
a1919 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d1934 1
a1934 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d1960 1
a1960 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d1987 1
a1987 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d2195 1
d2205 1
d2232 14
a2245 2
#define INIT_CLOCK_GETCPUCLOCKID                  \
  COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);
d2304 1
a2304 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
d2334 1
a2334 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
d2340 1
a2340 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
d2346 1
a2346 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
d2425 54
d2588 1
a2588 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d2617 1
a2617 1
  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
d2659 1
a2659 1
  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
d2661 1
a2661 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
d2677 1
a2677 1
                                       REAL(strlen)(p->ai_canonname) + 1);
d2703 1
a2703 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
d2705 1
a2705 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
d2715 1
a2715 1
INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
d2718 5
a2722 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
  int addrlen_in = *addrlen;
d2727 2
a2728 2
  if (res == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
d2741 1
a2741 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
d2744 1
a2744 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
d3233 4
a3236 1
  if (addrlen) addr_sz = *addrlen;
d3241 1
a3241 1
  if (!res && addr && addrlen)
d3243 1
d3272 1
a3272 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d3427 1
a3427 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
d3430 1
a3430 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3449 1
a3449 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3465 1
a3465 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3739 1
a3739 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d3750 3
a3752 2
  if (allocated_path && !res) WRAP(free)(allocated_path);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3755 1
a3755 1
#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
d3764 1
a3764 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d3766 1
a3766 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3827 1
a3827 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d3843 1
a3843 1
    SANITIZER_FREEBSD || SANITIZER_OPENBSD
d3869 1
a3869 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3871 1
a3871 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d3891 1
a3891 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
d3927 1
a3927 1
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
d3980 1
a3980 1
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
d4076 1
a4076 1
  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d4083 5
a4087 4
    if (p->we_wordc)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
                                     sizeof(*p->we_wordv) * p->we_wordc);
    for (uptr i = 0; i < p->we_wordc; ++i) {
d4089 1
a4089 1
      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
d4107 1
a4107 1
  int res = REAL(sigwait)(set, sig);
d4124 1
a4124 1
  int res = REAL(sigwaitinfo)(set, info);
d4143 1
a4143 1
  int res = REAL(sigtimedwait)(set, info, timeout);
d4182 2
a4183 1
INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst, __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
d4186 4
a4189 2
  if (src1) COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
  if (src2) COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
d4191 2
a4192 1
  if (!res && dst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
d4196 2
a4197 1
INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst, __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
d4200 4
a4203 2
  if (src1) COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
  if (src2) COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
d4205 2
a4206 1
  if (!res && dst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
d4295 1
a4295 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
d4413 1
a4413 1
                                   REAL(strlen)(mnt->mnt_fsname) + 1);
d4416 1
a4416 1
                                   REAL(strlen)(mnt->mnt_dir) + 1);
d4419 1
a4419 1
                                   REAL(strlen)(mnt->mnt_type) + 1);
d4422 1
a4422 1
                                   REAL(strlen)(mnt->mnt_opts) + 1);
d4457 1
a4457 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4486 1
a4486 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4515 1
a4515 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4549 1
a4549 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4578 1
a4578 1
  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
d4593 1
a4593 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d4599 1
a4599 1
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
d4621 1
a4621 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
d4628 1
a4628 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
d4640 1
a4640 1
  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
d4648 1
a4648 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
d4669 1
a4669 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d4676 1
a4676 1
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
d4942 1
a4942 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
d4944 1
a4944 1
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d4961 1
a4961 1
  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
d4969 28
d5003 1
a5003 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d5017 1
a5017 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
d5029 2
a5030 2
  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
d5032 1
a5032 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d5378 6
a5422 1
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
a5423 3
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
d5439 9
a5485 3
#endif // SANITIZER_S390
#else
#define INIT_TLS_GET_ADDR
d5492 1
a5492 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d5505 1
a5505 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d5536 2
a5537 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d5549 2
a5550 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d5562 1
a5562 1
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d5632 1
a5632 1
                                       REAL(strlen)(p->ifa_name) + 1);
d5662 1
a5662 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
d5669 1
a5669 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
d5927 1
a5927 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
d5936 1
a5936 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
d6007 1
a6007 1
  
d6080 3
d6147 2
a6148 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
d6157 1
a6157 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
d6166 2
a6167 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
d6182 34
d6220 2
a6221 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
d6231 2
a6232 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
d6343 2
d6364 2
d6410 1
a6410 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
d6412 1
a6412 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
d6580 1
a6580 1
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
d6616 33
a6648 8
#define INIT_SEM                                                               \
  COMMON_INTERCEPT_FUNCTION(sem_init);                                         \
  COMMON_INTERCEPT_FUNCTION(sem_destroy);                                      \
  COMMON_INTERCEPT_FUNCTION(sem_wait);                                         \
  COMMON_INTERCEPT_FUNCTION(sem_trywait);                                      \
  COMMON_INTERCEPT_FUNCTION(sem_timedwait);                                    \
  COMMON_INTERCEPT_FUNCTION(sem_post);                                         \
  COMMON_INTERCEPT_FUNCTION(sem_getvalue);
d6650 2
a6651 2
#define INIT_SEM
#endif // SANITIZER_INTERCEPT_SEM
d6734 1
a6734 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d6749 1
a6749 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
d7086 2
a7087 2
  SIZE_T src_size = REAL(wcslen)(src);
  SIZE_T dst_size = REAL(wcslen)(dst);
d7098 2
a7099 2
  SIZE_T src_size = REAL(wcsnlen)(src, n);
  SIZE_T dst_size = REAL(wcslen)(dst);
d7118 1
a7118 1
  SIZE_T len = REAL(wcslen)(s);
d7132 1
a7132 1
static SIZE_T RealStrLen(const char *str) { return REAL(strlen)(str); }
d7134 1
a7134 1
static SIZE_T RealStrLen(const wchar_t *str) { return REAL(wcslen)(str); }
d7208 1
a7208 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
d7223 1
a7223 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1);
d7237 1
a7237 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7255 1
a7255 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1);
d7269 1
a7269 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1);
d7285 1
a7285 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d7298 1
a7298 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d7313 1
a7313 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7337 1
a7337 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7355 1
a7355 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d7372 1
a7372 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d7390 1
a7390 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1);
d7454 1
a7454 1
  COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1);
d7482 1
a7482 1
    ReportMmapWriteExec(prot);
d7492 1
a7492 1
    ReportMmapWriteExec(prot);
d7511 1
a7511 1
    ReportMmapWriteExec(prot);
d7529 1
a7529 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7551 1
a7551 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1);
d7581 1
a7581 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, REAL(strlen)(bp) + 1);
d7601 1
a7601 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7607 8
d7619 1
a7619 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d7622 1
a7622 4
#define INIT_TTYENT \
  COMMON_INTERCEPT_FUNCTION(getttyent); \
  COMMON_INTERCEPT_FUNCTION(getttynam); \
  COMMON_INTERCEPT_FUNCTION(setttyentpath)
d7624 1
a7624 1
#define INIT_TTYENT
d7631 1
a7631 1
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);
d7636 1
a7636 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);
d7655 1
a7655 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7699 1
a7699 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7738 1
a7738 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
d7743 1
a7743 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
d7755 1
a7755 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d7760 1
a7760 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
d7765 1
a7765 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
d7780 1
a7780 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
d7785 1
a7785 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
d7906 1
a7906 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1);
d7919 1
a7919 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1);
d7933 1
a7933 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1);
d7945 1
a7945 1
  COMMON_INTERCEPT_FUNCTION(regexec);                                          \
d7958 1
a7958 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
d7963 1
a7963 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
d7966 1
a7966 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
d7974 1
a7974 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
d7979 1
a7979 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1);
d7983 1
a7983 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1);
d8005 1
a8005 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
d8097 1
a8097 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
d8118 1
a8118 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
d8158 1
a8158 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
d8181 1
a8181 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
d8215 1
a8215 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
d8235 1
a8235 1
                                      REAL(strlen)(ml->ml_filename) + 1);
d8243 1
a8243 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d8285 1
a8285 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
d8305 1
a8305 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
d8322 1
a8322 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d8603 1
a8603 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d8614 1
a8614 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d8690 1
a8690 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d8773 1
a8773 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d8784 1
a8784 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d8860 1
a8860 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d8990 1
a8990 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
d9068 1
a9068 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
d9080 1
a9080 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
d9097 4
a9100 4
SHA2_INTERCEPTORS(224, u32);
SHA2_INTERCEPTORS(256, u32);
SHA2_INTERCEPTORS(384, u64);
SHA2_INTERCEPTORS(512, u64);
d9144 1
a9144 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9154 1
a9154 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9167 1
a9167 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9217 1
a9217 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9228 1
a9228 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9240 1
a9240 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9242 1
a9242 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9253 1
a9253 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9255 1
a9255 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9269 1
a9269 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9282 1
a9282 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9296 1
a9296 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
d9323 1
a9323 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9333 1
a9333 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9343 1
a9343 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9354 1
a9354 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
d9390 1
a9390 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d9582 1
a9582 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1);
d9593 1
a9593 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
d9637 1
a9637 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
d9639 1
a9639 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
d9656 1
a9656 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d9662 1
a9662 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
d9670 1
a9670 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
d9674 1
a9674 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
d9870 1
a9870 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
d9883 1
a9883 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
d9903 1
a9903 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d9928 1
a9928 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
d9941 1
a9941 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
d9944 1
a9944 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d10030 46
a10075 1
#if SANITIZER_INTERCEPT_QSORT
d10090 1
a10090 1
int wrapped_qsort_compar(const void *a, const void *b) {
d10132 1
a10132 1
#define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
d10134 1
a10134 1
#define INIT_QSORT
d10137 11
a10147 9
#if SANITIZER_INTERCEPT_QSORT_R
typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
static THREADLOCAL qsort_r_compar_f qsort_r_compar;
static THREADLOCAL SIZE_T qsort_r_size;
int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size);
  return qsort_r_compar(a, b, arg);
d10150 2
a10151 2
INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_r_compar_f compar, void *arg) {
d10153 3
a10155 31
  COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
  // Run the comparator over all array elements to detect any memory issues.
  if (nmemb > 1) {
    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
      void *p = (void *)((char *)base + i * size);
      void *q = (void *)((char *)base + (i + 1) * size);
      COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
      compar(p, q, arg);
    }
  }
  qsort_r_compar_f old_compar = qsort_r_compar;
  SIZE_T old_size = qsort_r_size;
  // Handle qsort_r() implementations that recurse using an
  // interposable function call:
  bool already_wrapped = compar == wrapped_qsort_r_compar;
  if (already_wrapped) {
    // This case should only happen if the qsort() implementation calls itself
    // using a preemptible function call (e.g. the FreeBSD libc version).
    // Check that the size and comparator arguments are as expected.
    CHECK_NE(compar, qsort_r_compar);
    CHECK_EQ(qsort_r_size, size);
  } else {
    qsort_r_compar = compar;
    qsort_r_size = size;
  }
  REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg);
  if (!already_wrapped) {
    qsort_r_compar = old_compar;
    qsort_r_size = old_size;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
d10157 1
a10157 1
#define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
d10159 1
a10159 1
#define INIT_QSORT_R
d10293 1
d10395 2
d10431 1
d10529 1
@


1.12
log
@initial merge of GCC 10.3.0.

these three files are not yet finished merging:

gcc/config/rs6000/rs6000.c
libsanitizer/lsan/lsan_allocator.h
libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h

our current GCC 9 sanitizers are newer than GCC 10's still, so that
may take a little to untease, so it's probable that more than
these 2 will need more changes.

rs6000.c has some changes related to ABI and supported functionality
that need to be merged forward.
@
text
@a9989 2230
#if SANITIZER_INTERCEPT_GETMNTINFO
INTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags);
  int cnt = REAL(getmntinfo)(mntbufp, flags);
  if (cnt > 0 && mntbufp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
    if (*mntbufp)
#if SANITIZER_NETBSD
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz);
#else
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz);
#endif
  }
  return cnt;
}
#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo)
#else
#define INIT_GETMNTINFO
#endif

#if SANITIZER_INTERCEPT_MI_VECTOR_HASH
INTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed,
            u32 hashes[3]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes);
  if (key)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len);
  REAL(mi_vector_hash)(key, len, seed, hashes);
  if (hashes)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3);
}
#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash)
#else
#define INIT_MI_VECTOR_HASH
#endif

#if SANITIZER_INTERCEPT_SETVBUF
INTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode,
  SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size);
  int ret = REAL(setvbuf)(stream, buf, mode, size);
  if (buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
  if (stream)
      unpoison_file(stream);
  return ret;
}

INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf);
  REAL(setbuf)(stream, buf);
  if (buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
  }
  if (stream)
      unpoison_file(stream);
}

INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, int mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, mode);
  REAL(setbuffer)(stream, buf, mode);
  if (buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
  }
  if (stream)
    unpoison_file(stream);
}

INTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream);
  REAL(setlinebuf)(stream);
  if (stream)
    unpoison_file(stream);
}
#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \
    COMMON_INTERCEPT_FUNCTION(setbuf); \
    COMMON_INTERCEPT_FUNCTION(setbuffer); \
    COMMON_INTERCEPT_FUNCTION(setlinebuf)
#else
#define INIT_SETVBUF
#endif

#if SANITIZER_INTERCEPT_GETVFSSTAT
INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
  int ret = REAL(getvfsstat)(buf, bufsize, flags);
  if (buf && ret > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz);
  return ret;
}
#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat)
#else
#define INIT_GETVFSSTAT
#endif

#if SANITIZER_INTERCEPT_REGEX
INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
  if (pattern)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1);
  int res = REAL(regcomp)(preg, pattern, cflags);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
  return res;
}
INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
            struct __sanitizer_regmatch *pmatch[], int eflags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  if (string)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1);
  int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
  if (!res && pmatch)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
  return res;
}
INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
            SIZE_T errbuf_size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
  if (errbuf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1);
  return res;
}
INTERCEPTOR(void, regfree, const void *preg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  REAL(regfree)(preg);
}
#define INIT_REGEX                                                             \
  COMMON_INTERCEPT_FUNCTION(regcomp);                                          \
  COMMON_INTERCEPT_FUNCTION(regexec);                                          \
  COMMON_INTERCEPT_FUNCTION(regerror);                                         \
  COMMON_INTERCEPT_FUNCTION(regfree);
#else
#define INIT_REGEX
#endif

#if SANITIZER_INTERCEPT_REGEXSUB
INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
            const struct __sanitizer_regmatch *rm, const char *str) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
  if (sub)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
  // The implementation demands and hardcodes 10 elements
  if (rm)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
  if (str)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
  SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
  if (res > 0 && buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
  return res;
}
INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
            const struct __sanitizer_regmatch *rm, const char *sstr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
  if (sub)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
  // Hardcode 10 elements as this is hardcoded size
  if (rm)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
  if (sstr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1);
  SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
  if (res > 0 && buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1);
  }
  return res;
}

#define INIT_REGEXSUB                                                          \
  COMMON_INTERCEPT_FUNCTION(regnsub);                                          \
  COMMON_INTERCEPT_FUNCTION(regasub);
#else
#define INIT_REGEXSUB
#endif

#if SANITIZER_INTERCEPT_FTS
INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
            int (*compar)(void **, void **)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar);
  if (path_argv) {
    for (char *const *pa = path_argv; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
    }
  }
  // TODO(kamil): handle compar callback
  void *fts = REAL(fts_open)(path_argv, options, compar);
  if (fts)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz);
  return fts;
}

INTERCEPTOR(void *, fts_read, void *ftsp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  void *ftsent = REAL(fts_read)(ftsp);
  if (ftsent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
  return ftsent;
}

INTERCEPTOR(void *, fts_children, void *ftsp, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  void *ftsent = REAL(fts_children)(ftsp, options);
  if (ftsent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
  return ftsent;
}

INTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  if (f)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz);
  return REAL(fts_set)(ftsp, f, options);
}

INTERCEPTOR(int, fts_close, void *ftsp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  return REAL(fts_close)(ftsp);
}
#define INIT_FTS                                                               \
  COMMON_INTERCEPT_FUNCTION(fts_open);                                         \
  COMMON_INTERCEPT_FUNCTION(fts_read);                                         \
  COMMON_INTERCEPT_FUNCTION(fts_children);                                     \
  COMMON_INTERCEPT_FUNCTION(fts_set);                                          \
  COMMON_INTERCEPT_FUNCTION(fts_close);
#else
#define INIT_FTS
#endif

#if SANITIZER_INTERCEPT_SYSCTL
INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
            SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
  COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
                           newlen);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
  if (oldlenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
  if (newp && newlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
  int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
  if (!res) {
    if (oldlenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
      if (oldp)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
    }
  }
  return res;
}

INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
            void *newp, SIZE_T newlen) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen);
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
                           newlen);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  if (oldlenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
  if (newp && newlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
  int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
  if (!res) {
    if (oldlenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
      if (oldp)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
    }
  }
  return res;
}

INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
            SIZE_T *namelenp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  if (namelenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
  int res = REAL(sysctlnametomib)(sname, name, namelenp);
  if (!res) {
    if (namelenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
      if (name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
    }
  }
  return res;
}

#define INIT_SYSCTL                        \
  COMMON_INTERCEPT_FUNCTION(sysctl);       \
  COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
  COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
#else
#define INIT_SYSCTL
#endif

#if SANITIZER_INTERCEPT_ASYSCTL
INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
  void *res = REAL(asysctl)(name, namelen, len);
  if (res && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
  }
  return res;
}

INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  void *res = REAL(asysctlbyname)(sname, len);
  if (res && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
  }
  return res;
}
#define INIT_ASYSCTL                           \
  COMMON_INTERCEPT_FUNCTION(asysctl);          \
  COMMON_INTERCEPT_FUNCTION(asysctlbyname);
#else
#define INIT_ASYSCTL
#endif

#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
            unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
            int v) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
                           csz, rnode, v);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  if (namelenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
  if (csz)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
  // Skip rnode, it's rarely used and not trivial to sanitize
  // It's also used mostly internally
  int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
  if (!res) {
    if (namelenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
      if (name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
    }
    if (csz) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
      if (cname)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
    }
  }
  return res;
}
#define INIT_SYSCTLGETMIBINFO                  \
  COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
#else
#define INIT_SYSCTLGETMIBINFO
#endif

#if SANITIZER_INTERCEPT_NL_LANGINFO
INTERCEPTOR(char *, nl_langinfo, long item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
  char *ret = REAL(nl_langinfo)(item);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
  return ret;
}
#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
#else
#define INIT_NL_LANGINFO
#endif

#if SANITIZER_INTERCEPT_MODCTL
INTERCEPTOR(int, modctl, int operation, void *argp) {
  void *ctx;
  int ret;
  COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp);

  if (operation == modctl_load) {
    if (argp) {
      __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
      if (ml->ml_filename)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
                                      REAL(strlen)(ml->ml_filename) + 1);
      if (ml->ml_props)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
    }
    ret = REAL(modctl)(operation, argp);
  } else if (operation == modctl_unload) {
    if (argp) {
      const char *name = (const char *)argp;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
    }
    ret = REAL(modctl)(operation, argp);
  } else if (operation == modctl_stat) {
    uptr iov_len;
    struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp;
    if (iov) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov));
      iov_len = iov->iov_len;
    }
    ret = REAL(modctl)(operation, argp);
    if (iov)
      COMMON_INTERCEPTOR_WRITE_RANGE(
          ctx, iov->iov_base, Min(iov_len,  iov->iov_len));
  } else if (operation == modctl_exists) {
    ret = REAL(modctl)(operation, argp);
  } else {
    ret = REAL(modctl)(operation, argp);
  }

  return ret;
}
#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl)
#else
#define INIT_MODCTL
#endif

#if SANITIZER_INTERCEPT_STRTONUM
INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
            long long maxval, const char **errstr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);

  // TODO(kamil): Implement strtoll as a common inteceptor
  char *real_endptr;
  long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
  StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);

  ret = REAL(strtonum)(nptr, minval, maxval, errstr);
  if (errstr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
     if (*errstr)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
  }
  return ret;
}
#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
#else
#define INIT_STRTONUM
#endif

#if SANITIZER_INTERCEPT_FPARSELN
INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
            SIZE_T *lineno, const char delim[3], int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags);
  if (lineno)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno));
  if (delim)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
  char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
  if (ret) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
    if (len)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    if (lineno)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno));
  }
  return ret;
}
#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln)
#else
#define INIT_FPARSELN
#endif

#if SANITIZER_INTERCEPT_STATVFS1
INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  int res = REAL(statvfs1)(path, buf, flags);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(fstatvfs1)(fd, buf, flags);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
    if (fd >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
#define INIT_STATVFS1                  \
  COMMON_INTERCEPT_FUNCTION(statvfs1);  \
  COMMON_INTERCEPT_FUNCTION(fstatvfs1);
#else
#define INIT_STATVFS1
#endif

#if SANITIZER_INTERCEPT_STRTOI
INTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base,
            INTMAX_T low, INTMAX_T high, int *rstatus) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus);
  char *real_endptr;
  INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  if (rstatus)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
  return ret;
}

INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base,
            UINTMAX_T low, UINTMAX_T high, int *rstatus) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus);
  char *real_endptr;
  UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  if (rstatus)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
  return ret;
}
#define INIT_STRTOI                                                            \
  COMMON_INTERCEPT_FUNCTION(strtoi);                                           \
  COMMON_INTERCEPT_FUNCTION(strtou)
#else
#define INIT_STRTOI
#endif

#if SANITIZER_INTERCEPT_CAPSICUM
#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...)          \
  {                                                                        \
    void *ctx;                                                             \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \
    if (rights)                                                            \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));         \
    __sanitizer_cap_rights_t *ret =                                        \
        REAL(cap_rights_init)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                               \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));              \
    return ret;                                                            \
  }

#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...)           \
  {                                                                       \
    void *ctx;                                                            \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \
    if (rights)                                                           \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));        \
    __sanitizer_cap_rights_t *ret =                                       \
        REAL(cap_rights_set)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                              \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));             \
    return ret;                                                           \
  }

#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...)         \
  {                                                                         \
    void *ctx;                                                              \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \
    if (rights)                                                             \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));          \
    __sanitizer_cap_rights_t *ret =                                         \
        REAL(cap_rights_clear)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                                \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));               \
    return ret;                                                             \
  }

#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...)        \
  {                                                                          \
    void *ctx;                                                               \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \
    if (rights)                                                              \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));           \
    return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__);                   \
  }

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights);
}

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights);
}

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights);
}

INTERCEPTOR(bool, cap_rights_is_set,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights);
}

INTERCEPTOR(int, cap_rights_limit, int fd,
            const __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights);
  if (rights)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));

  return REAL(cap_rights_limit)(fd, rights);
}

INTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights);
  int ret = REAL(cap_rights_get)(fd, rights);
  if (!ret && rights)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights));

  return ret;
}

INTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights);
  if (rights)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));

  return REAL(cap_rights_is_valid(rights));
}

INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge,
  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));

  __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));

  return ret;
}

INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove,
  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));

  __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));

  return ret;
}

INTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big,
  const __sanitizer_cap_rights *little) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little);
  if (little)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little));
  if (big)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big));

  return REAL(cap_rights_contains)(big, little);
}

INTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds);
  if (cmds)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds);

  return REAL(cap_ioctls_limit)(fd, cmds, ncmds);
}

INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds);
  int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds);
  if (!ret && cmds)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds);

  return ret;
}
#define INIT_CAPSICUM                          \
  COMMON_INTERCEPT_FUNCTION(cap_rights_init); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_set); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_get);   \
  COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \
  COMMON_INTERCEPT_FUNCTION(cap_ioctls_get);   \
  COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit)
#else
#define INIT_CAPSICUM
#endif

#if SANITIZER_INTERCEPT_SHA1
INTERCEPTOR(void, SHA1Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context);
  REAL(SHA1Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
}
INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  REAL(SHA1Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
}
INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  REAL(SHA1Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
}
INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer);
  if (state)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
  if (buffer)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64);
  REAL(SHA1Transform)(state, buffer);
  if (state)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
}
INTERCEPTOR(char *, SHA1End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  char *ret = REAL(SHA1End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(SHA1File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
  OFF_T length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf);
  if (data)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(SHA1Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
#define INIT_SHA1                                                              \
  COMMON_INTERCEPT_FUNCTION(SHA1Init);                                         \
  COMMON_INTERCEPT_FUNCTION(SHA1Update);                                       \
  COMMON_INTERCEPT_FUNCTION(SHA1Final);                                        \
  COMMON_INTERCEPT_FUNCTION(SHA1Transform);                                    \
  COMMON_INTERCEPT_FUNCTION(SHA1End);                                          \
  COMMON_INTERCEPT_FUNCTION(SHA1File);                                         \
  COMMON_INTERCEPT_FUNCTION(SHA1FileChunk);                                    \
  COMMON_INTERCEPT_FUNCTION(SHA1Data)
#else
#define INIT_SHA1
#endif

#if SANITIZER_INTERCEPT_MD4
INTERCEPTOR(void, MD4Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context);
  REAL(MD4Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
}

INTERCEPTOR(void, MD4Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  REAL(MD4Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
}

INTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  REAL(MD4Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD4End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  char *ret = REAL(MD4End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(MD4File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

INTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD4Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

#define INIT_MD4                                                               \
  COMMON_INTERCEPT_FUNCTION(MD4Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD4Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD4Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD4End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD4File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD4Data)
#else
#define INIT_MD4
#endif

#if SANITIZER_INTERCEPT_RMD160
INTERCEPTOR(void, RMD160Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context);
  REAL(RMD160Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
}
INTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  REAL(RMD160Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
}
INTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  REAL(RMD160Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
}
INTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer);
  if (state)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
  if (buffer)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16);
  REAL(RMD160Transform)(state, buffer);
  if (state)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
}
INTERCEPTOR(char *, RMD160End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  char *ret = REAL(RMD160End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(RMD160File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
  OFF_T length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(RMD160Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
#define INIT_RMD160                                                            \
  COMMON_INTERCEPT_FUNCTION(RMD160Init);                                       \
  COMMON_INTERCEPT_FUNCTION(RMD160Update);                                     \
  COMMON_INTERCEPT_FUNCTION(RMD160Final);                                      \
  COMMON_INTERCEPT_FUNCTION(RMD160Transform);                                  \
  COMMON_INTERCEPT_FUNCTION(RMD160End);                                        \
  COMMON_INTERCEPT_FUNCTION(RMD160File);                                       \
  COMMON_INTERCEPT_FUNCTION(RMD160FileChunk);                                  \
  COMMON_INTERCEPT_FUNCTION(RMD160Data)
#else
#define INIT_RMD160
#endif

#if SANITIZER_INTERCEPT_MD5
INTERCEPTOR(void, MD5Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
  REAL(MD5Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
}

INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  REAL(MD5Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
}

INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  REAL(MD5Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD5End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  char *ret = REAL(MD5End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(MD5File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD5Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

#define INIT_MD5                                                               \
  COMMON_INTERCEPT_FUNCTION(MD5Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD5Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD5Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD5End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD5File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD5Data)
#else
#define INIT_MD5
#endif

#if SANITIZER_INTERCEPT_FSEEK
INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence);
  return REAL(fseek)(stream, offset, whence);
}
INTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence);
  return REAL(fseeko)(stream, offset, whence);
}
INTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream);
  return REAL(ftell)(stream);
}
INTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream);
  return REAL(ftello)(stream);
}
INTERCEPTOR(void, rewind, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream);
  return REAL(rewind)(stream);
}
INTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos);
  int ret = REAL(fgetpos)(stream, pos);
  if (pos && !ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz);
  return ret;
}
INTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos);
  if (pos)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz);
  return REAL(fsetpos)(stream, pos);
}
#define INIT_FSEEK \
  COMMON_INTERCEPT_FUNCTION(fseek); \
  COMMON_INTERCEPT_FUNCTION(fseeko); \
  COMMON_INTERCEPT_FUNCTION(ftell); \
  COMMON_INTERCEPT_FUNCTION(ftello); \
  COMMON_INTERCEPT_FUNCTION(rewind); \
  COMMON_INTERCEPT_FUNCTION(fgetpos); \
  COMMON_INTERCEPT_FUNCTION(fsetpos)
#else
#define INIT_FSEEK
#endif

#if SANITIZER_INTERCEPT_MD2
INTERCEPTOR(void, MD2Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context);
  REAL(MD2Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
}

INTERCEPTOR(void, MD2Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  REAL(MD2Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
}

INTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  REAL(MD2Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD2End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  char *ret = REAL(MD2End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(MD2File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD2Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

#define INIT_MD2                                                               \
  COMMON_INTERCEPT_FUNCTION(MD2Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD2Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD2Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD2End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD2File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD2Data)
#else
#define INIT_MD2
#endif

#if SANITIZER_INTERCEPT_SHA2
#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
  INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
    REAL(SHA##LEN##_Init)(context); \
    if (context) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
  } \
  INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
              const u8 *data, SIZE_T len) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
    if (data && len > 0) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    REAL(SHA##LEN##_Update)(context, data, len); \
    if (context) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
  } \
  INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
  void *context) { \
    void *ctx; \
    CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    REAL(SHA##LEN##_Final)(digest, context); \
    if (digest) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
                                     sizeof(digest[0]) * \
  SHA##LEN##_digest_length); \
  } \
  INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    char *ret = REAL(SHA##LEN##_End)(context, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
    if (filename) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
    char *ret = REAL(SHA##LEN##_File)(filename, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
              OFF_T offset, OFF_T length) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
  length); \
    if (filename) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
    char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
    if (data && len > 0) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
    char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  }

SHA2_INTERCEPTORS(224, u32);
SHA2_INTERCEPTORS(256, u32);
SHA2_INTERCEPTORS(384, u64);
SHA2_INTERCEPTORS(512, u64);

#define INIT_SHA2_INTECEPTORS(LEN) \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)

#define INIT_SHA2 \
  INIT_SHA2_INTECEPTORS(224); \
  INIT_SHA2_INTECEPTORS(256); \
  INIT_SHA2_INTECEPTORS(384); \
  INIT_SHA2_INTECEPTORS(512)
#undef SHA2_INTERCEPTORS
#else
#define INIT_SHA2
#endif

#if SANITIZER_INTERCEPT_VIS
INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
  char *end = REAL(vis)(dst, c, flag, nextc);
  // dst is NULL terminated and end points to the NULL char
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
  char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
  // nvis cannot make sure the dst is NULL terminated
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int len = REAL(strvis)(dst, src, flag);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int len = REAL(stravis)(dst, src, flag);
  if (dst) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
    if (*dst)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
  }
  return len;
}
INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int len = REAL(strnvis)(dst, dlen, src, flag);
  // The interface will be valid even if there is no space for NULL char
  if (dst && len > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  int ret = REAL(strvisx)(dst, src, len, flag);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag, int *cerr_ptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
  // according to the implementation
  if (cerr_ptr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
  int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  if (cerr_ptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
  return ret;
}
INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  char *end = REAL(svis)(dst, c, flag, nextc, extra);
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
                                   Min((SIZE_T)(end - dst + 1), dlen));
  return end;
}
INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int len = REAL(strsvis)(dst, src, flag, extra);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
  // The interface will be valid even if there is no space for NULL char
  if (dst && len >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int ret = REAL(strsvisx)(dst, src, len, flag, extra);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag, const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
            SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
                           cerr_ptr);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
  // according to the implementation
  if (cerr_ptr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
  int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  if (cerr_ptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
  return ret;
}
INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
  if (astate)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
  int ret = REAL(unvis)(cp, c, astate, flag);
  if (ret == unvis_valid || ret == unvis_validpush) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
  }
  return ret;
}
INTERCEPTOR(int, strunvis, char *dst, const char *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strunvis)(dst, src);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strnunvis)(dst, dlen, src);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strunvisx)(dst, src, flag);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
            int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strnunvisx)(dst, dlen, src, flag);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
#define INIT_VIS                                                               \
  COMMON_INTERCEPT_FUNCTION(vis);                                              \
  COMMON_INTERCEPT_FUNCTION(nvis);                                             \
  COMMON_INTERCEPT_FUNCTION(strvis);                                           \
  COMMON_INTERCEPT_FUNCTION(stravis);                                          \
  COMMON_INTERCEPT_FUNCTION(strnvis);                                          \
  COMMON_INTERCEPT_FUNCTION(strvisx);                                          \
  COMMON_INTERCEPT_FUNCTION(strnvisx);                                         \
  COMMON_INTERCEPT_FUNCTION(strenvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(svis);                                             \
  COMMON_INTERCEPT_FUNCTION(snvis);                                            \
  COMMON_INTERCEPT_FUNCTION(strsvis);                                          \
  COMMON_INTERCEPT_FUNCTION(strsnvis);                                         \
  COMMON_INTERCEPT_FUNCTION(strsvisx);                                         \
  COMMON_INTERCEPT_FUNCTION(strsnvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(strsenvisx);                                       \
  COMMON_INTERCEPT_FUNCTION(unvis);                                            \
  COMMON_INTERCEPT_FUNCTION(strunvis);                                         \
  COMMON_INTERCEPT_FUNCTION(strnunvis);                                        \
  COMMON_INTERCEPT_FUNCTION(strunvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(strnunvisx)
#else
#define INIT_VIS
#endif

#if SANITIZER_INTERCEPT_CDB
INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
  if (cdbr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
  return cdbr;
}

INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
  int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
    cookie);
  if (base && size)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
  struct __sanitizer_cdbr *cdbr =
    REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
  if (cdbr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
  return cdbr;
}

INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  return REAL(cdbr_entries)(cdbr);
}

INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
            const void **data, SIZE_T *datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
  if (!ret) {
    if (data)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
    if (datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
    if (data && datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
  }
  return ret;
}

INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
            SIZE_T keylen, const void **data, SIZE_T *datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  if (key)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
  if (!ret) {
    if (data)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
    if (datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
    if (data && datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
  }
  return ret;
}

INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  REAL(cdbr_close)(cdbr);
}

INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
  struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
  return ret;
}

INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
  SIZE_T keylen, const void *data, SIZE_T datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (data && datalen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
  if (key && keylen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
  if (!ret && cdbw)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  return ret;
}

INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
  SIZE_T datalen, u32 *index) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (data && datalen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
  int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
  if (!ret) {
    if (index)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
    if (cdbw)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  }
  return ret;
}

INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
  SIZE_T keylen, u32 index) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (key && keylen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
  if (!ret && cdbw)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  return ret;
}

INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
  const char descr[16], u32 (*seedgen)(void)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (descr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
  if (seedgen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
  int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
  if (!ret) {
    if (cdbw)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
    if (output >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
  }
  return ret;
}

INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  REAL(cdbw_close)(cdbw);
}

#define INIT_CDB \
  COMMON_INTERCEPT_FUNCTION(cdbr_open); \
  COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
  COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
  COMMON_INTERCEPT_FUNCTION(cdbr_get); \
  COMMON_INTERCEPT_FUNCTION(cdbr_find); \
  COMMON_INTERCEPT_FUNCTION(cdbr_close); \
  COMMON_INTERCEPT_FUNCTION(cdbw_open); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
  COMMON_INTERCEPT_FUNCTION(cdbw_output); \
  COMMON_INTERCEPT_FUNCTION(cdbw_close)
#else
#define INIT_CDB
#endif

#if SANITIZER_INTERCEPT_GETFSENT
INTERCEPTOR(void *, getfsent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsent);
  void *ret = REAL(getfsent)();
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

INTERCEPTOR(void *, getfsspec, const char *spec) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
  if (spec)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1);
  void *ret = REAL(getfsspec)(spec);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

INTERCEPTOR(void *, getfsfile, const char *file) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
  if (file)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
  void *ret = REAL(getfsfile)(file);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

#define INIT_GETFSENT \
  COMMON_INTERCEPT_FUNCTION(getfsent); \
  COMMON_INTERCEPT_FUNCTION(getfsspec); \
  COMMON_INTERCEPT_FUNCTION(getfsfile);
#else
#define INIT_GETFSENT
#endif

#if SANITIZER_INTERCEPT_ARC4RANDOM
INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len);
  REAL(arc4random_buf)(buf, len);
  if (buf && len)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len);
}

INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen);
  if (dat && datlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen);
  REAL(arc4random_addrandom)(dat, datlen);
}

#define INIT_ARC4RANDOM \
  COMMON_INTERCEPT_FUNCTION(arc4random_buf); \
  COMMON_INTERCEPT_FUNCTION(arc4random_addrandom);
#else
#define INIT_ARC4RANDOM
#endif

#if SANITIZER_INTERCEPT_POPEN
INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
  if (command)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
  if (type)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
  __sanitizer_FILE *res = REAL(popen)(command, type);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
#else
#define INIT_POPEN
#endif

#if SANITIZER_INTERCEPT_POPENVE
INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
            char *const *argv, char *const *envp, const char *type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  if (argv) {
    for (char *const *pa = argv; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
    }
  }
  if (envp) {
    for (char *const *pa = envp; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
    }
  }
  if (type)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
  __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
#else
#define INIT_POPENVE
#endif

#if SANITIZER_INTERCEPT_PCLOSE
INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  const FileMetadata *m = GetInterceptorMetadata(fp);
  int res = REAL(pclose)(fp);
  if (m) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
    DeleteInterceptorMetadata(fp);
  }
  return res;
}
#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
#else
#define INIT_PCLOSE
#endif

#if SANITIZER_INTERCEPT_FUNOPEN
typedef int (*funopen_readfn)(void *cookie, char *buf, int len);
typedef int (*funopen_writefn)(void *cookie, const char *buf, int len);
typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence);
typedef int (*funopen_closefn)(void *cookie);

struct WrappedFunopenCookie {
  void *real_cookie;
  funopen_readfn real_read;
  funopen_writefn real_write;
  funopen_seekfn real_seek;
  funopen_closefn real_close;
};

static int wrapped_funopen_read(void *cookie, char *buf, int len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_readfn real_read = wrapped_cookie->real_read;
  return real_read(wrapped_cookie->real_cookie, buf, len);
}

static int wrapped_funopen_write(void *cookie, const char *buf, int len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_writefn real_write = wrapped_cookie->real_write;
  return real_write(wrapped_cookie->real_cookie, buf, len);
}

static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_seekfn real_seek = wrapped_cookie->real_seek;
  return real_seek(wrapped_cookie->real_cookie, offset, whence);
}

static int wrapped_funopen_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_closefn real_close = wrapped_cookie->real_close;
  int res = real_close(wrapped_cookie->real_cookie);
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn,
            funopen_writefn writefn, funopen_seekfn seekfn,
            funopen_closefn closefn) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn,
                           closefn);

  WrappedFunopenCookie *wrapped_cookie =
      (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_read = readfn;
  wrapped_cookie->real_write = writefn;
  wrapped_cookie->real_seek = seekfn;
  wrapped_cookie->real_close = closefn;

  __sanitizer_FILE *res =
      REAL(funopen)(wrapped_cookie,
                    readfn  ? wrapped_funopen_read  : nullptr,
                    writefn ? wrapped_funopen_write : nullptr,
                    seekfn  ? wrapped_funopen_seek  : nullptr,
                    closefn ? wrapped_funopen_close : nullptr);
  if (res)
    unpoison_file(res);
  return res;
}
#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen)
#else
#define INIT_FUNOPEN
#endif

#if SANITIZER_INTERCEPT_FUNOPEN2
typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len);
typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len);
typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence);
typedef int (*funopen2_flushfn)(void *cookie);
typedef int (*funopen2_closefn)(void *cookie);

struct WrappedFunopen2Cookie {
  void *real_cookie;
  funopen2_readfn real_read;
  funopen2_writefn real_write;
  funopen2_seekfn real_seek;
  funopen2_flushfn real_flush;
  funopen2_closefn real_close;
};

static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_readfn real_read = wrapped_cookie->real_read;
  return real_read(wrapped_cookie->real_cookie, buf, len);
}

static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf,
                                      SIZE_T len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_writefn real_write = wrapped_cookie->real_write;
  return real_write(wrapped_cookie->real_cookie, buf, len);
}

static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_seekfn real_seek = wrapped_cookie->real_seek;
  return real_seek(wrapped_cookie->real_cookie, offset, whence);
}

static int wrapped_funopen2_flush(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_flushfn real_flush = wrapped_cookie->real_flush;
  return real_flush(wrapped_cookie->real_cookie);
}

static int wrapped_funopen2_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_closefn real_close = wrapped_cookie->real_close;
  int res = real_close(wrapped_cookie->real_cookie);
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn,
            funopen2_writefn writefn, funopen2_seekfn seekfn,
            funopen2_flushfn flushfn, funopen2_closefn closefn) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn,
                           flushfn, closefn);

  WrappedFunopen2Cookie *wrapped_cookie =
      (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_read = readfn;
  wrapped_cookie->real_write = writefn;
  wrapped_cookie->real_seek = seekfn;
  wrapped_cookie->real_flush = flushfn;
  wrapped_cookie->real_close = closefn;

  __sanitizer_FILE *res =
      REAL(funopen2)(wrapped_cookie,
                     readfn  ? wrapped_funopen2_read  : nullptr,
                     writefn ? wrapped_funopen2_write : nullptr,
                     seekfn  ? wrapped_funopen2_seek  : nullptr,
                     flushfn ? wrapped_funopen2_flush : nullptr,
                     closefn ? wrapped_funopen2_close : nullptr);
  if (res)
    unpoison_file(res);
  return res;
}
#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2)
#else
#define INIT_FUNOPEN2
#endif

#if SANITIZER_INTERCEPT_FDEVNAME
INTERCEPTOR(char *, fdevname,  int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  char *name = REAL(fdevname)(fd);
  if (name) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
    if (fd > 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return name;
}

INTERCEPTOR(char *, fdevname_r,  int fd, char *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  char *name = REAL(fdevname_r)(fd, buf, len);
  if (name && buf && len > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
    if (fd > 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return name;
}

#define INIT_FDEVNAME \
  COMMON_INTERCEPT_FUNCTION(fdevname); \
  COMMON_INTERCEPT_FUNCTION(fdevname_r);
#else
#define INIT_FDEVNAME
#endif

#if SANITIZER_INTERCEPT_GETUSERSHELL
INTERCEPTOR(char *, getusershell) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
  char *res = REAL(getusershell)();
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}

#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell);
#else
#define INIT_GETUSERSHELL
#endif

#if SANITIZER_INTERCEPT_SL_INIT
INTERCEPTOR(void *, sl_init) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_init);
  void *res = REAL(sl_init)();
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz);
  return res;
}

INTERCEPTOR(int, sl_add, void *sl, char *item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  if (item)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
  int res = REAL(sl_add)(sl, item);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  return res;
}

INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  if (item)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
  char *res = REAL(sl_find)(sl, item);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}

INTERCEPTOR(void, sl_free, void *sl, int freeall) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  REAL(sl_free)(sl, freeall);
}

#define INIT_SL_INIT                  \
  COMMON_INTERCEPT_FUNCTION(sl_init); \
  COMMON_INTERCEPT_FUNCTION(sl_add);  \
  COMMON_INTERCEPT_FUNCTION(sl_find); \
  COMMON_INTERCEPT_FUNCTION(sl_free);
#else
#define INIT_SL_INIT
#endif

#if SANITIZER_INTERCEPT_GETRANDOM
INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
  SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
  if (n > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
  }
  return n;
}
#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom)
#else
#define INIT_GETRANDOM
#endif

#if SANITIZER_INTERCEPT_CRYPT
INTERCEPTOR(char *, crypt, char *key, char *salt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
  char *res = REAL(crypt)(key, salt);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
#else
#define INIT_CRYPT
#endif

#if SANITIZER_INTERCEPT_CRYPT_R
INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
  char *res = REAL(crypt_r)(key, salt, data);
  if (res != nullptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
                                   __sanitizer::struct_crypt_data_sz);
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  }
  return res;
}
#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
#else
#define INIT_CRYPT_R
#endif

#if SANITIZER_INTERCEPT_GETENTROPY
INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
  int r = REAL(getentropy)(buf, buflen);
  if (r == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  return r;
}
#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
#else
#define INIT_GETENTROPY
#endif

@


1.11
log
@Sync interceptors of sanitizers with LLVM rev. 00460ae520

Use the 2020-09-10 snapshot to replace two-years-old GCC9 copy of
interceptors.

With this change, ASan works with the locally patched GCC tree (as there
were IOCTL operations not properly defined).
@
text
@d9990 2230
@


1.10
log
@Add __lsan::ScopedInterceptorDisabler for strerror(3)

Cherry-pick and adapt:

commit 1b58389428ed07a7322ba9c2bcaeec99807f9457
Author: Kamil Rytarowski <n54@@gmx.com>
Date:   Sat Sep 21 07:45:02 2019 +0000

    Add __lsan::ScopedInterceptorDisabler for strerror(3)

    Summary:
    strerror(3) on NetBSD uses internally TSD with a destructor that is never
    fired for exit(3). It's correctly called for pthread_exit(3) scenarios.

    This is a case when a leak on exit(3) is expected, unavoidable and harmless.

    Reviewers: joerg, vitalybuka, dvyukov, mgorny

    Reviewed By: vitalybuka

    Subscribers: dmgreen, kristof.beyls, jfb, llvm-commits, #sanitizers

    Tags: #sanitizers, #llvm

    Differential Revision: https://reviews.llvm.org/D67337

    llvm-svn: 372461
@
text
@d3 3
a5 2
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
d66 1
a66 1
#if SANITIZER_BSD
d80 9
d90 1
d100 2
d116 1
d123 2
d127 1
d137 1
a137 5
namespace __sanitizer {
bool PlatformHasDifferentMemcpyAndMemmove();
}
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
  (__sanitizer::PlatformHasDifferentMemcpyAndMemmove())
d327 1
a331 1
#if SI_POSIX
a828 1

d833 4
a836 5
INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
d862 1
a862 1
  int result = REAL(memcmp(a1, a2, size));
d868 8
d881 14
d1251 3
a1253 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d1266 3
a1268 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d1277 2
a1278 3
INTERCEPTOR(int, prctl, int option, unsigned long arg2,
            unsigned long arg3,                        // NOLINT
            unsigned long arg4, unsigned long arg5) {  // NOLINT
a1529 8
#define INIT_SCANF_NORMAL                                                      \
  INTERCEPT_FUNCTION(scanf);                                                   \
  INTERCEPT_FUNCTION(sscanf);                                                  \
  INTERCEPT_FUNCTION(fscanf);                                                  \
  INTERCEPT_FUNCTION(vscanf);                                                  \
  INTERCEPT_FUNCTION(vsscanf);                                                 \
  INTERCEPT_FUNCTION(vfscanf);                                                 \

d1710 2
a1711 2
INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
d1715 2
a1716 2
            const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT
d1724 2
a1725 2
            SIZE_T size_to, const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT
d1850 2
a1851 4
#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS || \
    SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT || \
    SANITIZER_INTERCEPT_GETPWENT_R || SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
d1855 2
a1856 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_name,
                                          REAL(strlen)(pwd->pw_name) + 1);
d1858 2
a1859 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_passwd,
                                          REAL(strlen)(pwd->pw_passwd) + 1);
d1862 2
a1863 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_gecos,
                                          REAL(strlen)(pwd->pw_gecos) + 1);
d1865 1
a1865 1
#if SANITIZER_MAC
d1867 2
a1868 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_class,
                                          REAL(strlen)(pwd->pw_class) + 1);
d1871 2
a1872 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_dir,
                                          REAL(strlen)(pwd->pw_dir) + 1);
d1874 2
a1875 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_shell,
                                          REAL(strlen)(pwd->pw_shell) + 1);
d1879 1
a1879 1
static void unpoison_group(void *ctx, __sanitizer_group *grp) {
d1883 2
a1884 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_name,
                                          REAL(strlen)(grp->gr_name) + 1);
d1886 2
a1887 2
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_passwd,
                                          REAL(strlen)(grp->gr_passwd) + 1);
d1890 1
a1890 1
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(*p, REAL(strlen)(*p) + 1);
d1892 2
a1893 2
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_mem,
                                        (p - grp->gr_mem + 1) * sizeof(*p));
d1896 1
a1896 4
#endif  // SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS ||
        // SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT ||
        // SANITIZER_INTERCEPT_GETPWENT_R ||
        // SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
d1905 1
a1905 1
  if (res) unpoison_passwd(ctx, res);
d1912 1
a1912 1
  if (res) unpoison_passwd(ctx, res);
d1920 1
a1920 1
  if (res) unpoison_group(ctx, res);
d1927 1
a1927 1
  if (res) unpoison_group(ctx, res);
d1949 2
a1950 4
  if (!res) {
    if (result && *result) unpoison_passwd(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d1962 2
a1963 4
  if (!res) {
    if (result && *result) unpoison_passwd(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d1976 2
a1977 4
  if (!res) {
    if (result && *result) unpoison_group(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d1989 2
a1990 4
  if (!res) {
    if (result && *result) unpoison_group(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d2008 1
a2008 1
  if (res) unpoison_passwd(ctx, res);
d2015 1
a2015 1
  if (res) unpoison_group(ctx, res);;
d2030 1
a2030 1
  if (res) unpoison_passwd(ctx, res);
d2037 1
a2037 1
  if (res) unpoison_group(ctx, res);
d2056 2
a2057 4
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d2061 2
a2062 2
INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
d2064 1
a2064 1
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
d2068 3
a2070 5
  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d2074 10
a2083 2
INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
            __sanitizer_group **pwbufp) {
d2085 1
a2085 1
  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
d2089 3
a2091 5
  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d2095 7
d2110 2
a2111 4
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
d2115 1
a2115 4
#define INIT_GETPWENT_R                   \
  COMMON_INTERCEPT_FUNCTION(getpwent_r);  \
  COMMON_INTERCEPT_FUNCTION(fgetpwent_r); \
  COMMON_INTERCEPT_FUNCTION(getgrent_r);  \
d2118 1
a2118 1
#define INIT_GETPWENT_R
d2182 2
d2202 18
d3098 1
a3098 1
  if (res >= 0 && msgvec)
d3105 1
d3113 28
d3264 1
a3264 1
    if (request == ptrace_setregs)
d3266 1
a3266 1
    else if (request == ptrace_setfpregs)
d3268 1
a3268 1
    else if (request == ptrace_setfpxregs)
d3270 1
a3270 1
    else if (request == ptrace_setvfpregs)
d3272 1
a3272 1
    else if (request == ptrace_setsiginfo)
d3274 1
d3278 1
a3278 1
    else if (request == ptrace_setregset || request == ptrace_getregset) {
d3295 1
a3295 1
    if (request == ptrace_getregs)
d3297 1
a3297 1
    else if (request == ptrace_getfpregs)
d3299 1
a3299 1
    else if (request == ptrace_getfpxregs)
d3301 1
a3301 1
    else if (request == ptrace_getvfpregs)
d3303 1
a3303 1
    else if (request == ptrace_getsiginfo)
d3305 1
a3305 1
    else if (request == ptrace_geteventmsg)
d3307 1
a3307 1
    else if (request == ptrace_getregset) {
d3585 10
a3594 7
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(wcrtomb)(dest, src, ps);
  if (res != ((SIZE_T)-1) && dest) {
    SIZE_T write_cnt = res;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
d3604 22
d4088 27
d4150 19
d4255 11
a4265 1
  return WRAP(pthread_mutex_lock)(m);
d4269 7
a4275 1
  return WRAP(pthread_mutex_unlock)(m);
d4425 1
d4430 5
a4434 1
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
d4868 14
d5009 8
d5027 1
a5027 3
#define INIT_REMQUO                   \
  COMMON_INTERCEPT_FUNCTION(remquo);  \
  COMMON_INTERCEPT_FUNCTION(remquof); \
d5030 1
a5030 1
#define INIT_REMQUO
d5049 8
d5064 1
a5064 3
#define INIT_LGAMMA                   \
  COMMON_INTERCEPT_FUNCTION(lgamma);  \
  COMMON_INTERCEPT_FUNCTION(lgammaf); \
d5067 1
a5067 1
#define INIT_LGAMMA
a5658 1

d5664 10
d5839 73
d5935 5
d5943 1
d6578 1
a6578 1
  if (res > 0) {
d6580 3
a6582 4
    if (srcaddr)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
                                          Min((SIZE_T)*addrlen, srcaddr_sz));
  }
d6812 10
d6825 2
a6826 1
  COMMON_INTERCEPT_FUNCTION(getutxline);
d6889 1
a6889 1
  return REAL(wcscat)(dst, src);  // NOLINT
d6902 1
a6902 1
  return REAL(wcsncat)(dst, src, n);  // NOLINT
d6911 17
d7335 9
a7343 1
INTERCEPTOR(int, devname_r, u64 dev, u32 type, char *path, uptr len) {
a7344 1
  int res;
d7346 2
a7347 2
  res = REAL(devname_r)(dev, type, path, len);
  if (!res)
d7420 14
d7438 2
a7439 13
  if (p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);

    SIZE_T pp_size = 1; // One handles the trailing \0

    for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                   pp_size * sizeof(char **));
  }
d7449 2
a7450 13
  if (p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);

    SIZE_T pp_size = 1; // One handles the trailing \0

    for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                   pp_size * sizeof(char **));
  }
d7458 2
a7459 13
  if (p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);

    SIZE_T pp_size = 1; // One handles the trailing \0

    for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                   pp_size * sizeof(char **));
  }
d7470 52
d7592 2398
d9991 1
d9993 2
a9994 1
  interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
d10022 1
d10057 2
d10061 1
d10088 1
d10105 1
d10125 1
d10128 1
d10167 1
d10174 1
d10176 1
d10193 1
d10196 1
d10231 1
d10254 1
d10256 45
@


1.9
log
@merge GCC 9.3.0.
@
text
@d38 1
d294 4
d3639 1
@


1.8
log
@merge GCC 8.3.0 pass 1.  will not compile yet.  thare are still
about 25 files with merge issues.
@
text
@d35 1
d71 46
d269 6
d327 1
a327 1
  if (h.exists()) {
d1190 44
d1275 1
d1282 1
d1618 6
d1637 6
d1671 6
d1680 6
d1689 6
d1734 11
d1769 1
d1874 2
a1875 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
d2155 7
d2192 13
a2204 2
  if (new_value)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
d2234 12
d2309 6
d2316 1
d2345 1
a2345 2
#define INIT_GLOB                  \
  COMMON_INTERCEPT_FUNCTION(glob); \
d2347 3
a2349 3
#else  // SANITIZER_INTERCEPT_GLOB
#define INIT_GLOB
#endif  // SANITIZER_INTERCEPT_GLOB
d2654 7
d2662 1
d2670 1
a2670 5
#define INIT_GETHOSTBYNAME                  \
  COMMON_INTERCEPT_FUNCTION(gethostent);    \
  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
  COMMON_INTERCEPT_FUNCTION(gethostbyname); \
  COMMON_INTERCEPT_FUNCTION(gethostbyname2);
d2672 2
a2673 2
#define INIT_GETHOSTBYNAME
#endif
d2843 24
d2912 1
a2912 1
#if SANITIZER_INTERCEPT_RECVMSG
d2925 1
d2927 1
d2950 24
a2973 1
#if SANITIZER_INTERCEPT_SENDMSG
d3023 1
d3025 1
d3044 24
d3249 9
d3264 4
a3267 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
d3354 1
a3354 1
INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
d3361 1
a3361 1
  INTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
d3650 2
a3651 1
    SANITIZER_MAC || SANITIZER_ANDROID
d4074 1
a4074 1
#if SANITIZER_INTERCEPT_PHTREAD_MUTEX
d4107 38
d4469 1
a4497 2
INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
a4527 2
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam);  \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy); \
d4535 11
d4730 1
a4730 1
#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP
d4739 11
d4754 14
d6174 1
a6174 1
  if (res == 0)
d6183 1
a6183 1
  if (res == 0)
d6392 16
d6620 624
d7248 2
d7267 2
d7290 3
d7313 1
d7322 1
d7330 1
d7334 2
d7377 5
d7395 1
d7414 1
d7459 1
d7470 25
@


1.7
log
@first pass at merging GCC 7.4.0.  unlikely to compile..
@
text
@d25 2
a26 1
//   COMMON_INTERCEPTOR_MUTEX_LOCK
d32 5
d41 1
d44 1
d50 3
a52 9
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)                                     \
  do {                                                                         \
    if (f)                                                                     \
      f(__VA_ARGS__);                                                          \
  } while (false);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)                                  \
  extern "C" {                                                                 \
  SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);  \
  } // extern "C"
d70 13
d95 6
a100 2
#ifndef COMMON_INTERCEPTOR_MUTEX_LOCK
#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) {}
d144 1
a144 1
#define COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n)       \
d146 1
a146 4
      common_flags()->strict_string_checks ? (len) + 1 : (n) )

#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n)                   \
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
d149 2
a150 1
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) {}
d181 59
d260 1
a260 1
#if SI_NOT_WINDOWS
d287 1
a287 1
#endif  // SI_NOT_WINDOWS
d323 20
d347 1
a347 1
  COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
d401 8
a408 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, Min(i + 1, size));
d451 1
a451 1
                              const char *s1, const char *s2, uptr n,
d454 1
a454 1
INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
d456 1
a456 1
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
d459 1
a459 1
  for (i = 0; i < n; i++) {
d464 8
a471 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
d474 1
a474 1
                             s1, s2, n, result);
d490 1
a490 2
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s1, len1,
                                          r ? r - s1 + len2 : len1 + 1);
d539 46
d616 5
a620 4
  uptr len = internal_strlen(s);
  uptr n = result ? result - s + 1 : len + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n);
a648 1
  uptr len = internal_strlen(s);
d650 1
a650 1
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, len + 1);
d707 1
a707 3
INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memset(dst, v, size);
d709 1
a709 4
  COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);
  if (common_flags()->intercept_intrin)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
  return REAL(memset)(dst, v, size);
d718 1
a718 3
INTERCEPTOR(void*, memmove, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memmove(dst, src, size);
d720 1
a720 6
  COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  return REAL(memmove)(dst, src, size);
d729 6
a734 7
INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {
    // On OS X, calling internal_memcpy here will cause memory corruptions,
    // because memcpy and memmove are actually aliases of the same
    // implementation.  We need to use internal_memmove here.
    return internal_memmove(dst, src, size);
  }
d736 4
a739 4
  COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
a740 3
  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
  // due to memcpy being an alias of memmove on OS X.
  return REAL(memcpy)(dst, src, size);
d743 10
a752 1
#define INIT_MEMCPY COMMON_INTERCEPT_FUNCTION(memcpy)
d888 1
a888 1
#if SI_NOT_WINDOWS
d927 17
d1044 14
d1413 6
a1418 6
  COMMON_INTERCEPT_FUNCTION(scanf);   \
  COMMON_INTERCEPT_FUNCTION(sscanf);  \
  COMMON_INTERCEPT_FUNCTION(fscanf);  \
  COMMON_INTERCEPT_FUNCTION(vscanf);  \
  COMMON_INTERCEPT_FUNCTION(vsscanf); \
  COMMON_INTERCEPT_FUNCTION(vfscanf);
d1591 10
a1600 10
  COMMON_INTERCEPT_FUNCTION(printf);    \
  COMMON_INTERCEPT_FUNCTION(sprintf);   \
  COMMON_INTERCEPT_FUNCTION(snprintf);  \
  COMMON_INTERCEPT_FUNCTION(asprintf);  \
  COMMON_INTERCEPT_FUNCTION(fprintf);   \
  COMMON_INTERCEPT_FUNCTION(vprintf);   \
  COMMON_INTERCEPT_FUNCTION(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION(vasprintf); \
  COMMON_INTERCEPT_FUNCTION(vfprintf);
d3375 24
d3406 1
a3406 14
  // There are 2 versions of strerror_r:
  //  * POSIX version returns 0 on success, negative error code on failure,
  //    writes message to buf.
  //  * GNU version returns message pointer, which points to either buf or some
  //    static storage.
  SIZE_T posix_res = (SIZE_T)res;
  if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
    // POSIX version. Spec is not clear on whether buf is NULL-terminated.
    // At least on OSX, buf contents are valid even when the call fails.
    SIZE_T sz = internal_strnlen(buf, buflen);
    if (sz < buflen) ++sz;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  } else {
    // GNU version.
d3408 2
a3409 1
  }
d3412 2
d3599 1
a3599 1
  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
d3640 1
a3640 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3657 1
a3657 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3676 1
a3676 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3739 1
a3739 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3808 1
d3813 1
a3813 1
    COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
d4687 1
a4687 1
  if (res != (SIZE_T) - 1 && outbuf && *outbuf > outbuf_orig) {
a5041 4
DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr)

d5043 2
a5044 1
  return WRAP(memmove)(to, from, size);
d5046 1
d5048 2
a5049 1
  return WRAP(memmove)(to, from, size);
d5051 1
d5053 2
a5054 1
  return WRAP(memmove)(to, from, size);
d5056 1
d5058 2
a5059 1
  return WRAP(memcpy)(to, from, size);
d5061 1
d5063 2
a5064 1
  return WRAP(memcpy)(to, from, size);
d5066 1
d5068 2
a5069 1
  return WRAP(memcpy)(to, from, size);
d5071 1
d5074 2
a5075 1
  return WRAP(memset)(block, c, size);
d5077 1
d5079 2
a5080 1
  return WRAP(memset)(block, c, size);
d5082 1
d5084 2
a5085 1
  return WRAP(memset)(block, c, size);
d5087 1
d5089 2
a5090 1
  return WRAP(memset)(block, 0, size);
d5092 1
d5094 2
a5095 1
  return WRAP(memset)(block, 0, size);
d5097 1
d5099 2
a5100 1
  return WRAP(memset)(block, 0, size);
d5102 1
a5120 2
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);

d5122 2
a5123 1
  return WRAP(memset)(block, 0, size);
d5125 1
d5585 1
d5594 1
d6117 146
d6270 2
d6282 1
d6292 1
d6299 1
d6464 5
@


1.6
log
@merge GCC 6.4.0.  sanitizer stuff is probably busted, but most
other changes merged easily.

docs need to be regenerated with modern versions still.
@
text
@d12 1
a12 1
// which has to define it's own macros:
d92 4
d148 16
d213 34
d269 1
a269 1
                              const char *s1, const char *s2)
a273 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
                             s2);
d283 4
a286 1
  return CharCmpX(c1, c2);
d290 2
a291 1
                              const char *s1, const char *s2, uptr n)
a297 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
                             s2, size);
d305 6
a310 3
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
  return CharCmpX(c1, c2);
d327 3
d342 4
a345 1
  return CharCaseCmp(c1, c2);
d348 4
d364 4
a367 1
  return CharCaseCmp(c1, c2);
d389 4
d401 2
d412 4
d422 2
d432 73
d553 58
d614 2
a615 1
                              const void *s1, const void *s2, uptr n)
d618 2
a621 4
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
                             a2, size);
d641 4
a644 1
      return CharCmpX(c1, c2);
d647 4
a650 1
  return REAL(memcmp(a1, a2, size));
d664 8
d673 1
d718 1
a718 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d729 1
a729 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d737 1
a737 1
  COMMON_INTERCEPT_FUNCTION(frexpl)
d770 1
a770 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d788 1
a788 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d806 1
a806 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1053 1
a1053 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1066 1
a1066 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1079 1
a1079 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1092 1
a1092 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1136 1
a1136 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1281 1
a1281 1
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1298 1
a1298 1
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1315 1
a1315 1
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1600 1
a1600 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1615 1
a1615 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1631 1
a1631 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1646 1
a1646 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1715 1
a1715 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1730 1
a1730 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1745 1
a1745 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1760 1
a1760 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1817 1
a1817 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1829 1
a1829 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1856 1
a1856 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1870 1
a1870 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d1927 5
d1938 2
a1939 4
  __sanitizer_glob_t glob_copy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
d1967 2
a1968 4
  __sanitizer_glob_t glob_copy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
d2005 1
a2005 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2023 1
a2023 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2034 1
a2034 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2045 1
a2045 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2059 1
a2059 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2074 1
a2074 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2103 1
a2103 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2115 1
a2115 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2137 1
a2137 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2156 1
a2156 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2183 1
a2183 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2215 1
a2215 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2239 1
a2239 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2325 1
a2325 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2348 1
a2348 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2374 1
a2374 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2400 1
a2400 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2426 1
a2426 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2470 1
a2470 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2490 1
a2490 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2502 1
a2502 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2514 1
a2514 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2524 1
a2524 1
  COMMON_INTERCEPT_FUNCTION(modfl);
d2549 1
a2549 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2565 69
d2642 1
a2642 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2658 1
a2658 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2686 1
a2686 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2698 1
a2698 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2722 1
a2722 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2734 1
a2734 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2781 1
a2781 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2836 1
a2836 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2852 1
a2852 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2901 1
a2901 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2913 1
a2913 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2933 1
a2933 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2950 1
a2950 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d2980 1
a2980 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3000 1
a3000 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3017 1
a3017 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3045 1
a3045 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3067 1
a3067 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3087 1
a3087 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3144 1
a3144 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3161 1
a3161 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3203 1
a3203 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3234 1
a3234 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3279 1
a3279 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3332 1
a3332 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3359 1
a3359 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3426 1
a3426 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3452 1
a3452 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3469 1
a3469 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3488 1
a3488 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3504 1
a3504 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3515 1
a3515 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3533 1
a3533 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3551 1
a3551 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3568 1
a3568 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3582 1
a3582 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3602 1
d3604 1
d3622 2
d3631 4
a3634 1
  return REAL(pthread_mutex_unlock)(m);
d3697 1
a3697 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3707 1
a3707 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3726 1
a3726 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3736 1
a3736 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3755 1
a3755 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3765 1
a3765 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3784 1
a3784 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3794 1
a3794 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3850 1
a3850 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3863 1
a3863 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3875 1
a3875 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3899 1
a3899 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3911 1
a3911 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3929 1
a3929 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3954 1
a3954 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d3967 1
a3967 1
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4006 1
a4006 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4055 1
a4055 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4165 1
a4165 1
      // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4183 1
a4183 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4193 14
d4241 1
a4241 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4251 1
a4251 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4261 1
a4261 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4269 1
a4269 1
  COMMON_INTERCEPT_FUNCTION(sincosl);
d4280 1
a4280 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4290 1
a4290 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4300 1
a4300 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4308 1
a4308 1
  COMMON_INTERCEPT_FUNCTION(remquol);
d4339 1
a4339 1
  COMMON_INTERCEPT_FUNCTION(lgammal);
d4350 1
a4350 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4360 1
a4360 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4378 1
a4378 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4383 1
a4383 1
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION(lgammal_r);
d4394 1
a4394 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4404 1
a4404 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4434 1
a4434 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4446 1
a4446 1
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4493 1
a4493 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4512 1
a4512 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4524 1
d4545 76
d4632 1
a4632 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4645 1
a4645 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4655 1
a4655 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4677 1
a4677 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4690 1
a4690 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4702 1
a4702 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4721 1
a4721 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4735 1
a4735 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4760 1
a4760 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4796 1
a4796 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4824 1
a4824 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4925 1
a4925 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4943 1
a4943 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4958 1
a4958 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d4965 1
a4965 1
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d5019 1
a5019 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d5039 1
a5039 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d5091 1
a5091 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d5173 1
a5173 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d5244 1
a5244 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d5275 1
a5275 1
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d5689 214
d5908 2
d5916 3
d5921 3
d5927 1
d5977 1
d6047 1
d6088 11
@


1.6.4.1
log
@Sync with HEAD
@
text
@d12 1
a12 1
// which has to define its own macros:
a91 4
#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
#endif

a143 16
#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
#endif

#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
#endif

#ifdef SANITIZER_NLDBL_VERSION
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
#else
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION(fn)
#endif

a192 34
#if SANITIZER_INTERCEPT_STRLEN
INTERCEPTOR(SIZE_T, strlen, const char *s) {
  // Sometimes strlen is called prior to InitializeCommonInterceptors,
  // in which case the REAL(strlen) typically used in
  // COMMON_INTERCEPTOR_ENTER will fail.  We use internal_strlen here
  // to handle that.
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strlen(s);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
  SIZE_T result = REAL(strlen)(s);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
  return result;
}
#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
#else
#define INIT_STRLEN
#endif

#if SANITIZER_INTERCEPT_STRNLEN
INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
  SIZE_T length = REAL(strnlen)(s, maxlen);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
  return length;
}
#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
#else
#define INIT_STRNLEN
#endif

d215 1
a215 1
                              const char *s1, const char *s2, int result)
d220 2
d231 1
a231 4
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
                             s2, result);
  return result;
d235 1
a235 2
                              const char *s1, const char *s2, uptr n,
                              int result)
d242 2
d251 3
a253 6
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, Min(i + 1, size));
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
                             s2, size, result);
  return result;
a269 3
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
                              const char *s1, const char *s2, int result)

d282 1
a282 4
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
                             s1, s2, result);
  return result;
a284 4
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
                              const char *s1, const char *s2, uptr n,
                              int result)

d297 1
a297 4
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
                             s1, s2, n, result);
  return result;
a318 4

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

a326 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
                             s2, r);
a335 4

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

a341 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
                             s1, s2, r);
a349 73
#if SANITIZER_INTERCEPT_MEMMEM
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
                              const void *s1, SIZE_T len1, const void *s2,
                              SIZE_T len2, void *result)

INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
            SIZE_T len2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
  void *r = REAL(memmem)(s1, len1, s2, len2);
  if (common_flags()->intercept_memmem) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
  }
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
                             s1, len1, s2, len2, r);
  return r;
}

#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
#else
#define INIT_MEMMEM
#endif  // SANITIZER_INTERCEPT_MEMMEM

#if SANITIZER_INTERCEPT_STRCHR
INTERCEPTOR(char*, strchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
  char *result = REAL(strchr)(s, c);
  uptr len = internal_strlen(s);
  uptr n = result ? result - s + 1 : len + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n);
  return result;
}
#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
#else
#define INIT_STRCHR
#endif

#if SANITIZER_INTERCEPT_STRCHRNUL
INTERCEPTOR(char*, strchrnul, const char *s, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
  char *result = REAL(strchrnul)(s, c);
  uptr len = result - s + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
  return result;
}
#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
#else
#define INIT_STRCHRNUL
#endif

#if SANITIZER_INTERCEPT_STRRCHR
INTERCEPTOR(char*, strrchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strrchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
  uptr len = internal_strlen(s);
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, len + 1);
  return REAL(strrchr)(s, c);
}
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
#else
#define INIT_STRRCHR
#endif

a397 58
#if SANITIZER_INTERCEPT_MEMSET
INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memset(dst, v, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);
  if (common_flags()->intercept_intrin)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
  return REAL(memset)(dst, v, size);
}

#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
#else
#define INIT_MEMSET
#endif

#if SANITIZER_INTERCEPT_MEMMOVE
INTERCEPTOR(void*, memmove, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memmove(dst, src, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  return REAL(memmove)(dst, src, size);
}

#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
#else
#define INIT_MEMMOVE
#endif

#if SANITIZER_INTERCEPT_MEMCPY
INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {
    // On OS X, calling internal_memcpy here will cause memory corruptions,
    // because memcpy and memmove are actually aliases of the same
    // implementation.  We need to use internal_memmove here.
    return internal_memmove(dst, src, size);
  }
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
  // due to memcpy being an alias of memmove on OS X.
  return REAL(memcpy)(dst, src, size);
}

#define INIT_MEMCPY COMMON_INTERCEPT_FUNCTION(memcpy)
#else
#define INIT_MEMCPY
#endif

d401 1
a401 2
                              const void *s1, const void *s2, uptr n,
                              int result)
d404 2
d408 2
a409 2
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
d429 1
a429 4
      int r = CharCmpX(c1, c2);
      CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
                                 a1, a2, size, r);
      return r;
d432 1
a432 4
  int result = REAL(memcmp(a1, a2, size));
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
                             a2, size, result);
  return result;
a445 8
#if SANITIZER_WINDOWS
  void *res;
  if (REAL(memchr)) {
    res = REAL(memchr)(s, c, n);
  } else {
    res = internal_memchr(s, c, n);
  }
#else
a446 1
#endif
d491 1
a491 1
  // https://github.com/google/sanitizers/issues/321.
d502 1
a502 1
  // https://github.com/google/sanitizers/issues/321.
d510 1
a510 1
  COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
d543 1
a543 1
  // https://github.com/google/sanitizers/issues/321.
d561 1
a561 1
  // https://github.com/google/sanitizers/issues/321.
d579 1
a579 1
  // https://github.com/google/sanitizers/issues/321.
d826 1
a826 1
  // https://github.com/google/sanitizers/issues/321.
d839 1
a839 1
  // https://github.com/google/sanitizers/issues/321.
d852 1
a852 1
  // https://github.com/google/sanitizers/issues/321.
d865 1
a865 1
  // https://github.com/google/sanitizers/issues/321.
d909 1
a909 1
  // https://github.com/google/sanitizers/issues/321.
d1054 1
a1054 1
// https://github.com/google/sanitizers/issues/321.
d1071 1
a1071 1
// https://github.com/google/sanitizers/issues/321.
d1088 1
a1088 1
// https://github.com/google/sanitizers/issues/321.
d1373 1
a1373 1
  // https://github.com/google/sanitizers/issues/321.
d1388 1
a1388 1
  // https://github.com/google/sanitizers/issues/321.
d1404 1
a1404 1
  // https://github.com/google/sanitizers/issues/321.
d1419 1
a1419 1
  // https://github.com/google/sanitizers/issues/321.
d1488 1
a1488 1
  // https://github.com/google/sanitizers/issues/321.
d1503 1
a1503 1
  // https://github.com/google/sanitizers/issues/321.
d1518 1
a1518 1
  // https://github.com/google/sanitizers/issues/321.
d1533 1
a1533 1
  // https://github.com/google/sanitizers/issues/321.
d1590 1
a1590 1
  // https://github.com/google/sanitizers/issues/321.
d1602 1
a1602 1
  // https://github.com/google/sanitizers/issues/321.
d1629 1
a1629 1
  // https://github.com/google/sanitizers/issues/321.
d1643 1
a1643 1
  // https://github.com/google/sanitizers/issues/321.
a1699 5
static const __sanitizer_glob_t kGlobCopy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};

d1706 4
a1709 2
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
d1737 4
a1740 2
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
d1777 1
a1777 1
  // https://github.com/google/sanitizers/issues/321.
d1795 1
a1795 1
  // https://github.com/google/sanitizers/issues/321.
d1806 1
a1806 1
  // https://github.com/google/sanitizers/issues/321.
d1817 1
a1817 1
  // https://github.com/google/sanitizers/issues/321.
d1831 1
a1831 1
  // https://github.com/google/sanitizers/issues/321.
d1846 1
a1846 1
  // https://github.com/google/sanitizers/issues/321.
d1875 1
a1875 1
  // https://github.com/google/sanitizers/issues/321.
d1887 1
a1887 1
  // https://github.com/google/sanitizers/issues/321.
d1909 1
a1909 1
  // https://github.com/google/sanitizers/issues/321.
d1928 1
a1928 1
  // https://github.com/google/sanitizers/issues/321.
d1955 1
a1955 1
  // https://github.com/google/sanitizers/issues/321.
d1987 1
a1987 1
  // https://github.com/google/sanitizers/issues/321.
d2011 1
a2011 1
  // https://github.com/google/sanitizers/issues/321.
d2097 1
a2097 1
  // https://github.com/google/sanitizers/issues/321.
d2120 1
a2120 1
  // https://github.com/google/sanitizers/issues/321.
d2146 1
a2146 1
  // https://github.com/google/sanitizers/issues/321.
d2172 1
a2172 1
  // https://github.com/google/sanitizers/issues/321.
d2198 1
a2198 1
  // https://github.com/google/sanitizers/issues/321.
d2242 1
a2242 1
  // https://github.com/google/sanitizers/issues/321.
d2262 1
a2262 1
  // https://github.com/google/sanitizers/issues/321.
d2274 1
a2274 1
  // https://github.com/google/sanitizers/issues/321.
d2286 1
a2286 1
  // https://github.com/google/sanitizers/issues/321.
d2296 1
a2296 1
  COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
d2321 1
a2321 1
  // https://github.com/google/sanitizers/issues/321.
a2336 69
#if SANITIZER_INTERCEPT_SENDMSG
static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
  const unsigned kCmsgDataOffset =
      RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));

  char *p = (char *)control;
  char *const control_end = p + controllen;
  while (true) {
    if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
    __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));

    if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;

    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
                                  sizeof(cmsg->cmsg_level));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
                                  sizeof(cmsg->cmsg_type));

    if (cmsg->cmsg_len > kCmsgDataOffset) {
      char *data = p + kCmsgDataOffset;
      unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
      if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
    }

    p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
  }
}

static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                        SSIZE_T maxlen) {
#define R(f) \
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
  R(name);
  R(namelen);
  R(iov);
  R(iovlen);
  R(control);
  R(controllen);
  R(flags);
#undef R
  if (msg->msg_name && msg->msg_namelen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
  if (msg->msg_iov && msg->msg_iovlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
                                  sizeof(*msg->msg_iov) * msg->msg_iovlen);
  read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
  if (msg->msg_control && msg->msg_controllen)
    read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
}

INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
            int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
  if (common_flags()->intercept_send && res >= 0 && msg)
    read_msghdr(ctx, msg, res);
  return res;
}
#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
#else
#define INIT_SENDMSG
#endif

d2345 1
a2345 1
  // https://github.com/google/sanitizers/issues/321.
d2361 1
a2361 1
  // https://github.com/google/sanitizers/issues/321.
d2389 1
a2389 1
  // https://github.com/google/sanitizers/issues/321.
d2401 1
a2401 1
  // https://github.com/google/sanitizers/issues/321.
d2425 1
a2425 1
  // https://github.com/google/sanitizers/issues/321.
d2437 1
a2437 1
  // https://github.com/google/sanitizers/issues/321.
d2484 1
a2484 1
  // https://github.com/google/sanitizers/issues/321.
d2539 1
a2539 1
  // https://github.com/google/sanitizers/issues/321.
d2555 1
a2555 1
  // https://github.com/google/sanitizers/issues/321.
d2604 1
a2604 1
  // https://github.com/google/sanitizers/issues/321.
d2616 1
a2616 1
  // https://github.com/google/sanitizers/issues/321.
d2636 1
a2636 1
  // https://github.com/google/sanitizers/issues/321.
d2653 1
a2653 1
  // https://github.com/google/sanitizers/issues/321.
d2683 1
a2683 1
  // https://github.com/google/sanitizers/issues/321.
d2703 1
a2703 1
  // https://github.com/google/sanitizers/issues/321.
d2720 1
a2720 1
  // https://github.com/google/sanitizers/issues/321.
d2748 1
a2748 1
  // https://github.com/google/sanitizers/issues/321.
d2770 1
a2770 1
  // https://github.com/google/sanitizers/issues/321.
d2790 1
a2790 1
  // https://github.com/google/sanitizers/issues/321.
d2847 1
a2847 1
  // https://github.com/google/sanitizers/issues/321.
d2864 1
a2864 1
  // https://github.com/google/sanitizers/issues/321.
d2906 1
a2906 1
  // https://github.com/google/sanitizers/issues/321.
d2937 1
a2937 1
  // https://github.com/google/sanitizers/issues/321.
d2982 1
a2982 1
  // https://github.com/google/sanitizers/issues/321.
d3035 1
a3035 1
  // https://github.com/google/sanitizers/issues/321.
d3062 1
a3062 1
  // https://github.com/google/sanitizers/issues/321.
d3129 1
a3129 1
  // https://github.com/google/sanitizers/issues/321.
d3155 1
a3155 1
  // https://github.com/google/sanitizers/issues/321.
d3172 1
a3172 1
  // https://github.com/google/sanitizers/issues/321.
d3191 1
a3191 1
  // https://github.com/google/sanitizers/issues/321.
d3207 1
a3207 1
  // https://github.com/google/sanitizers/issues/321.
d3218 1
a3218 1
  // https://github.com/google/sanitizers/issues/321.
d3236 1
a3236 1
  // https://github.com/google/sanitizers/issues/321.
d3254 1
a3254 1
  // https://github.com/google/sanitizers/issues/321.
d3271 1
a3271 1
  // https://github.com/google/sanitizers/issues/321.
d3285 1
a3285 1
  // https://github.com/google/sanitizers/issues/321.
a3304 1
  COMMON_INTERCEPTOR_USER_CALLBACK_START();
a3305 1
  COMMON_INTERCEPTOR_USER_CALLBACK_END();
a3322 2
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
d3330 1
a3330 4
  int res = REAL(pthread_mutex_unlock)(m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
d3393 1
a3393 1
  // https://github.com/google/sanitizers/issues/321.
d3403 1
a3403 1
  // https://github.com/google/sanitizers/issues/321.
d3422 1
a3422 1
  // https://github.com/google/sanitizers/issues/321.
d3432 1
a3432 1
  // https://github.com/google/sanitizers/issues/321.
d3451 1
a3451 1
  // https://github.com/google/sanitizers/issues/321.
d3461 1
a3461 1
  // https://github.com/google/sanitizers/issues/321.
d3480 1
a3480 1
  // https://github.com/google/sanitizers/issues/321.
d3490 1
a3490 1
  // https://github.com/google/sanitizers/issues/321.
d3546 1
a3546 1
  // https://github.com/google/sanitizers/issues/321.
d3559 1
a3559 1
  // https://github.com/google/sanitizers/issues/321.
d3571 1
a3571 1
  // https://github.com/google/sanitizers/issues/321.
d3595 1
a3595 1
  // https://github.com/google/sanitizers/issues/321.
d3607 1
a3607 1
  // https://github.com/google/sanitizers/issues/321.
d3625 1
a3625 1
  // https://github.com/google/sanitizers/issues/321.
d3650 1
a3650 1
  // https://github.com/google/sanitizers/issues/321.
d3663 1
a3663 1
// https://github.com/google/sanitizers/issues/321.
d3702 1
a3702 1
  // https://github.com/google/sanitizers/issues/321.
d3751 1
a3751 1
  // https://github.com/google/sanitizers/issues/321.
d3861 1
a3861 1
      // https://github.com/google/sanitizers/issues/321.
d3879 1
a3879 1
  // https://github.com/google/sanitizers/issues/321.
a3888 14
#if SANITIZER_INTERCEPT_TTYNAME_R
INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
  int res = REAL(ttyname_r)(fd, name, namesize);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
  return res;
}
#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
#else
#define INIT_TTYNAME_R
#endif

d3923 1
a3923 1
  // https://github.com/google/sanitizers/issues/321.
d3933 1
a3933 1
  // https://github.com/google/sanitizers/issues/321.
d3943 1
a3943 1
  // https://github.com/google/sanitizers/issues/321.
d3951 1
a3951 1
  COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
d3962 1
a3962 1
  // https://github.com/google/sanitizers/issues/321.
d3972 1
a3972 1
  // https://github.com/google/sanitizers/issues/321.
d3982 1
a3982 1
  // https://github.com/google/sanitizers/issues/321.
d3990 1
a3990 1
  COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
d4021 1
a4021 1
  COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
d4032 1
a4032 1
  // https://github.com/google/sanitizers/issues/321.
d4042 1
a4042 1
  // https://github.com/google/sanitizers/issues/321.
d4060 1
a4060 1
  // https://github.com/google/sanitizers/issues/321.
d4065 1
a4065 1
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
d4076 1
a4076 1
  // https://github.com/google/sanitizers/issues/321.
d4086 1
a4086 1
  // https://github.com/google/sanitizers/issues/321.
d4116 1
a4116 1
  // https://github.com/google/sanitizers/issues/321.
d4128 1
a4128 1
// https://github.com/google/sanitizers/issues/321.
d4175 1
a4175 1
  // https://github.com/google/sanitizers/issues/321.
d4194 1
a4194 1
  // https://github.com/google/sanitizers/issues/321.
a4205 1
#if !SANITIZER_S390
a4225 76
#if SANITIZER_PPC
// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
// mostly the same semantics as __tls_get_addr, but its presence enables
// some optimizations in linker (which are safe to ignore here).
extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
                          visibility("default")))
void *__tls_get_addr_opt(void *arg);
#endif
#else // SANITIZER_S390
// On s390, we have to intercept two functions here:
// - __tls_get_addr_internal, which is a glibc-internal function that is like
//   the usual __tls_get_addr, but returns a TP-relative offset instead of
//   a proper pointer.  It is used by dlsym for TLS symbols.
// - __tls_get_offset, which is like the above, but also takes a GOT-relative
//   descriptor offset as an argument instead of a pointer.  GOT address
//   is passed in r12, so it's necessary to write it in assembly.  This is
//   the function used by the compiler.
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
  uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
  uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
  void *ptr = reinterpret_cast<void *>(res + tp);
  uptr tls_begin, tls_end;
  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
  if (dtv) {
    // New DTLS block has been allocated.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
  }
  return res;
}
// We need a hidden symbol aliasing the above, so that we can jump
// directly to it from the assembly below.
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
                          visibility("hidden")))
uptr __tls_get_addr_hidden(void *arg);
// Now carefully intercept __tls_get_offset.
asm(
  ".text\n"
// The __intercept_ version has to exist, so that gen_dynamic_list.py
// exports our symbol.
  ".weak __tls_get_offset\n"
  ".type __tls_get_offset, @@function\n"
  "__tls_get_offset:\n"
  ".global __interceptor___tls_get_offset\n"
  ".type __interceptor___tls_get_offset, @@function\n"
  "__interceptor___tls_get_offset:\n"
#ifdef __s390x__
  "la %r2, 0(%r2,%r12)\n"
  "jg __tls_get_addr_hidden\n"
#else
  "basr %r3,0\n"
  "0: la %r2,0(%r2,%r12)\n"
  "l %r4,1f-0b(%r3)\n"
  "b 0(%r4,%r3)\n"
  "1: .long __tls_get_addr_hidden - 0b\n"
#endif
  ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
// Assembly wrapper to call REAL(__tls_get_offset)(arg)
  ".type __tls_get_offset_wrapper, @@function\n"
  "__tls_get_offset_wrapper:\n"
#ifdef __s390x__
  "sgr %r2,%r12\n"
#else
  "sr %r2,%r12\n"
#endif
  "br %r3\n"
  ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
);
#endif // SANITIZER_S390
d4237 1
a4237 1
  // https://github.com/google/sanitizers/issues/321.
d4250 1
a4250 1
  // https://github.com/google/sanitizers/issues/321.
d4260 1
a4260 1
  // https://github.com/google/sanitizers/issues/321.
d4282 1
a4282 1
  // https://github.com/google/sanitizers/issues/321.
d4295 1
a4295 1
  // https://github.com/google/sanitizers/issues/321.
d4307 1
a4307 1
  // https://github.com/google/sanitizers/issues/321.
d4326 1
a4326 1
  // https://github.com/google/sanitizers/issues/321.
d4340 1
a4340 1
  // https://github.com/google/sanitizers/issues/321.
d4365 1
a4365 1
  // https://github.com/google/sanitizers/issues/321.
d4401 1
a4401 1
  // https://github.com/google/sanitizers/issues/321.
d4429 1
a4429 1
  // https://github.com/google/sanitizers/issues/321.
d4530 1
a4530 1
  // https://github.com/google/sanitizers/issues/321.
d4548 1
a4548 1
  // https://github.com/google/sanitizers/issues/321.
d4563 1
a4563 1
  // https://github.com/google/sanitizers/issues/321.
d4570 1
a4570 1
// https://github.com/google/sanitizers/issues/321.
d4624 1
a4624 1
  // https://github.com/google/sanitizers/issues/321.
d4644 1
a4644 1
  // https://github.com/google/sanitizers/issues/321.
d4696 1
a4696 1
  // https://github.com/google/sanitizers/issues/321.
d4778 1
a4778 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4849 1
a4849 1
  // https://github.com/google/sanitizers/issues/321.
d4880 1
a4880 1
  // https://github.com/google/sanitizers/issues/321.
a5293 214
#if SANITIZER_INTERCEPT_CTERMID
INTERCEPTOR(char *, ctermid, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
  char *res = REAL(ctermid)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
#else
#define INIT_CTERMID
#endif

#if SANITIZER_INTERCEPT_CTERMID_R
INTERCEPTOR(char *, ctermid_r, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
  char *res = REAL(ctermid_r)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
#else
#define INIT_CTERMID_R
#endif

#if SANITIZER_INTERCEPT_RECV_RECVFROM
INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
  }
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}

INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
            void *srcaddr, int *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
                           addrlen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SIZE_T srcaddr_sz;
  if (srcaddr) srcaddr_sz = *addrlen;
  (void)srcaddr_sz;  // prevent "set but not used" warning
  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
    if (srcaddr)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
                                          Min((SIZE_T)*addrlen, srcaddr_sz));
  }
  return res;
}
#define INIT_RECV_RECVFROM          \
  COMMON_INTERCEPT_FUNCTION(recv);  \
  COMMON_INTERCEPT_FUNCTION(recvfrom);
#else
#define INIT_RECV_RECVFROM
#endif

#if SANITIZER_INTERCEPT_SEND_SENDTO
INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(send)(fd, buf, len, flags);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}

INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
            void *dstaddr, int addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  // Can't check dstaddr as it may have uninitialized padding at the end.
  SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}
#define INIT_SEND_SENDTO           \
  COMMON_INTERCEPT_FUNCTION(send); \
  COMMON_INTERCEPT_FUNCTION(sendto);
#else
#define INIT_SEND_SENDTO
#endif

#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(eventfd_read)(fd, value);
  if (res == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  int res = REAL(eventfd_write)(fd, value);
  return res;
}
#define INIT_EVENTFD_READ_WRITE            \
  COMMON_INTERCEPT_FUNCTION(eventfd_read); \
  COMMON_INTERCEPT_FUNCTION(eventfd_write)
#else
#define INIT_EVENTFD_READ_WRITE
#endif

#if SANITIZER_INTERCEPT_STAT
INTERCEPTOR(int, stat, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(stat)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
#else
#define INIT_STAT
#endif

#if SANITIZER_INTERCEPT___XSTAT
INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
#else
#define INIT___XSTAT
#endif

#if SANITIZER_INTERCEPT___XSTAT64
INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
#else
#define INIT___XSTAT64
#endif

#if SANITIZER_INTERCEPT___LXSTAT
INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
#else
#define INIT___LXSTAT
#endif

#if SANITIZER_INTERCEPT___LXSTAT64
INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
#else
#define INIT___LXSTAT64
#endif

// FIXME: add other *stat interceptor

a5298 2
  INIT_STRLEN;
  INIT_STRNLEN;
a5304 3
  INIT_STRCHR;
  INIT_STRCHRNUL;
  INIT_STRRCHR;
a5306 3
  INIT_MEMSET;
  INIT_MEMMOVE;
  INIT_MEMCPY;
a5309 1
  INIT_MEMMEM;
a5358 1
  INIT_SENDMSG;
a5427 1
  INIT_TTYNAME_R;
a5467 11
  INIT_CTERMID;
  INIT_CTERMID_R;
  INIT_RECV_RECVFROM;
  INIT_SEND_SENDTO;
  INIT_STAT;
  INIT_EVENTFD_READ_WRITE;
  INIT___XSTAT;
  INIT___XSTAT64;
  INIT___LXSTAT;
  INIT___LXSTAT64;
  // FIXME: add other *stat interceptors.
@


1.6.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@d25 1
a25 2
//   COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
//   COMMON_INTERCEPTOR_MUTEX_POST_LOCK
a30 5
//   COMMON_INTERCEPTOR_MEMSET_IMPL
//   COMMON_INTERCEPTOR_MEMMOVE_IMPL
//   COMMON_INTERCEPTOR_MEMCPY_IMPL
//   COMMON_INTERCEPTOR_COPY_STRING
//   COMMON_INTERCEPTOR_STRNDUP_IMPL
a34 1
#include "sanitizer_errno.h"
a36 1
#include "sanitizer_symbolizer.h"
d42 9
a50 3
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
  SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
a67 13
// Platform-specific options.
#if SANITIZER_MAC
namespace __sanitizer {
bool PlatformHasDifferentMemcpyAndMemmove();
}
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
  (__sanitizer::PlatformHasDifferentMemcpyAndMemmove())
#elif SANITIZER_WINDOWS64
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
#else
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
#endif  // SANITIZER_MAC

d80 2
a81 6
#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
d125 4
d130 1
a130 2
    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
      common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
d133 1
a133 2
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
  CheckNoDeepBind(filename, flag);
a163 59
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
  {                                                       \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)        \
      return internal_memset(dst, v, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);  \
    if (common_flags()->intercept_intrin)                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);     \
    return REAL(memset)(dst, v, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
  {                                                          \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)           \
      return internal_memmove(dst, src, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                  \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);        \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);         \
    }                                                        \
    return REAL(memmove)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
  {                                                         \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {        \
      return internal_memmove(dst, src, size);              \
    }                                                       \
    COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);       \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);        \
    }                                                       \
    return REAL(memcpy)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_COPY_STRING
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
#endif

#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size)                         \
  COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size);                            \
  uptr copy_length = internal_strnlen(s, size);                               \
  char *new_mem = (char *)WRAP(malloc)(copy_length + 1);                      \
  if (common_flags()->intercept_strndup) {                                    \
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1));       \
  }                                                                           \
  COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);               \
  internal_memcpy(new_mem, s, copy_length);                                   \
  new_mem[copy_length] = '\0';                                                \
  return new_mem;
#endif

d184 1
a184 1
#if SI_POSIX
d211 1
a211 1
#endif  // SI_POSIX
a246 20
#if SANITIZER_INTERCEPT_STRNDUP
INTERCEPTOR(char*, strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
#else
#define INIT_STRNDUP
#endif // SANITIZER_INTERCEPT_STRNDUP

#if SANITIZER_INTERCEPT___STRNDUP
INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
#else
#define INIT___STRNDUP
#endif // SANITIZER_INTERCEPT___STRNDUP

d251 1
a251 1
  if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
d305 2
a306 8
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
d349 1
a349 1
                              const char *s1, const char *s2, uptr size,
d352 1
a352 1
INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
d354 1
a354 1
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
d357 1
a357 1
  for (i = 0; i < size; i++) {
d362 2
a363 8
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
d366 1
a366 1
                             s1, s2, size, result);
d382 2
a383 1
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
a431 46
#if SANITIZER_INTERCEPT_STRTOK

INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
  if (!common_flags()->intercept_strtok) {
    return REAL(strtok)(str, delimiters);
  }
  if (common_flags()->strict_string_checks) {
    // If strict_string_checks is enabled, we check the whole first argument
    // string on the first call (strtok saves this string in a static buffer
    // for subsequent calls). We do not need to check strtok's result.
    // As the delimiters can change, we check them every call.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
                                  REAL(strlen)(delimiters) + 1);
    return REAL(strtok)(str, delimiters);
  } else {
    // However, when strict_string_checks is disabled we cannot check the
    // whole string on the first call. Instead, we check the result string
    // which is guaranteed to be a NULL-terminated substring of the first
    // argument. We also conservatively check one character of str and the
    // delimiters.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
    char *result = REAL(strtok)(str, delimiters);
    if (result != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
    } else if (str != nullptr) {
      // No delimiter were found, it's safe to assume that the entire str was
      // scanned.
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
    }
    return result;
  }
}

#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
#else
#define INIT_STRTOK
#endif

d463 4
a466 5
  if (common_flags()->intercept_strchr) {
    // Keep strlen as macro argument, as macro may ignore it.
    COMMON_INTERCEPTOR_READ_STRING(ctx, s,
      (result ? result - s : REAL(strlen)(s)) + 1);
  }
d495 1
d497 1
a497 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d554 3
a556 1
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
d558 4
a561 1
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
d570 3
a572 1
INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
d574 6
a579 1
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
d588 13
a600 4
INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
  // On OS X, calling internal_memcpy here will cause memory corruptions,
  // because memcpy and memmove are actually aliases of the same
  // implementation.  We need to use internal_memmove here.
d603 1
a603 6
  void *ctx;
  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
    COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
  } else {
    COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
  }
d606 1
a606 10
#define INIT_MEMCPY                                  \
  do {                                               \
    if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
      COMMON_INTERCEPT_FUNCTION(memcpy);             \
    } else {                                         \
      ASSIGN_REAL(memcpy, memmove);                  \
    }                                                \
    CHECK(REAL(memcpy));                             \
  } while (false)

d742 1
a742 1
#if SI_POSIX
a780 17
#if SANITIZER_INTERCEPT_FREAD
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
  return res;
}
#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
#else
#define INIT_FREAD
#endif

a880 14
#if SANITIZER_INTERCEPT_FWRITE
INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
  SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
  return res;
}
#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
#else
#define INIT_FWRITE
#endif

d1236 6
a1241 6
  COMMON_INTERCEPT_FUNCTION_LDBL(scanf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(sscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
d1414 10
a1423 10
  COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
a3197 24
// There are 2 versions of strerror_r:
//  * POSIX version returns 0 on success, negative error code on failure,
//    writes message to buf.
//  * GNU version returns message pointer, which points to either buf or some
//    static storage.
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
    SANITIZER_MAC || SANITIZER_ANDROID
// POSIX version. Spec is not clear on whether buf is NULL-terminated.
// At least on OSX, buf contents are valid even when the call fails.
INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(strerror_r)(errnum, buf, buflen);

  SIZE_T sz = internal_strnlen(buf, buflen);
  if (sz < buflen) ++sz;
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  return res;
}
#else
// GNU version.
d3205 14
a3218 1
  if (res == buf)
d3220 1
a3220 2
  else
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
a3222 2
#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
       //SANITIZER_MAC
d3408 1
a3408 1
  if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
d3449 1
a3449 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3466 1
a3466 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3485 1
a3485 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3548 1
a3548 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
a3616 1
  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
d3621 1
a3621 1
    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
d4495 1
a4495 1
  if (outbuf && *outbuf > outbuf_orig) {
d4850 4
d4855 1
a4855 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4856 1

d4858 1
a4858 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4859 1

d4861 1
a4861 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4862 1

d4864 1
a4864 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4865 1

d4867 1
a4867 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4868 1

d4870 1
a4870 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4871 1

d4874 1
a4874 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4875 1

d4877 1
a4877 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4878 1

d4880 1
a4880 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4881 1

d4883 1
a4883 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4884 1

d4886 1
a4886 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4887 1

d4889 1
a4889 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4890 1

d4909 2
d4912 1
a4912 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4913 1

a5372 1
  Symbolizer::GetOrInit()->InvalidateModuleList();
a5380 1
  Symbolizer::GetOrInit()->InvalidateModuleList();
a5902 146
#if SANITIZER_INTERCEPT_UTMP
INTERCEPTOR(void *, getutent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
  void *res = REAL(getutent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
  void *res = REAL(getutid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
  void *res = REAL(getutline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
#define INIT_UTMP                      \
  COMMON_INTERCEPT_FUNCTION(getutent); \
  COMMON_INTERCEPT_FUNCTION(getutid);  \
  COMMON_INTERCEPT_FUNCTION(getutline);
#else
#define INIT_UTMP
#endif

#if SANITIZER_INTERCEPT_UTMPX
INTERCEPTOR(void *, getutxent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
  void *res = REAL(getutxent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
  void *res = REAL(getutxid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
  void *res = REAL(getutxline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
#define INIT_UTMPX                      \
  COMMON_INTERCEPT_FUNCTION(getutxent); \
  COMMON_INTERCEPT_FUNCTION(getutxid);  \
  COMMON_INTERCEPT_FUNCTION(getutxline);
#else
#define INIT_UTMPX
#endif

#if SANITIZER_INTERCEPT_GETLOADAVG
INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
  int res = REAL(getloadavg)(loadavg, nelem);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
  return res;
}
#define INIT_GETLOADAVG                      \
  COMMON_INTERCEPT_FUNCTION(getloadavg);
#else
#define INIT_GETLOADAVG
#endif

#if SANITIZER_INTERCEPT_MCHECK_MPROBE
INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mprobe, void *ptr) {
  return 0;
}
#endif

INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
  SIZE_T res = REAL(wcslen)(s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
  return res;
}

INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
  SIZE_T res = REAL(wcsnlen)(s, n);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
  return res;
}
#define INIT_WCSLEN                  \
  COMMON_INTERCEPT_FUNCTION(wcslen); \
  COMMON_INTERCEPT_FUNCTION(wcsnlen);

#if SANITIZER_INTERCEPT_WCSCAT
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
  SIZE_T src_size = REAL(wcslen)(src);
  SIZE_T dst_size = REAL(wcslen)(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcscat)(dst, src);  // NOLINT
}

INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
  SIZE_T src_size = REAL(wcsnlen)(src, n);
  SIZE_T dst_size = REAL(wcslen)(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
                                Min(src_size + 1, n) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcsncat)(dst, src, n);  // NOLINT
}
#define INIT_WCSCAT                  \
  COMMON_INTERCEPT_FUNCTION(wcscat); \
  COMMON_INTERCEPT_FUNCTION(wcsncat);
#else
#define INIT_WCSCAT
#endif

a5909 2
  INIT_STRNDUP;
  INIT___STRNDUP;
a5919 1
  INIT_STRTOK;
a5928 1
  INIT_FREAD;
a5934 1
  INIT_FWRITE;
a6098 5
  INIT_UTMP;
  INIT_UTMPX;
  INIT_GETLOADAVG;
  INIT_WCSLEN;
  INIT_WCSCAT;
@


1.6.2.1
log
@Sync with HEAD
@
text
@d12 1
a12 1
// which has to define its own macros:
a91 4
#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
#endif

a143 16
#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
#endif

#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
#endif

#ifdef SANITIZER_NLDBL_VERSION
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
#else
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION(fn)
#endif

a192 34
#if SANITIZER_INTERCEPT_STRLEN
INTERCEPTOR(SIZE_T, strlen, const char *s) {
  // Sometimes strlen is called prior to InitializeCommonInterceptors,
  // in which case the REAL(strlen) typically used in
  // COMMON_INTERCEPTOR_ENTER will fail.  We use internal_strlen here
  // to handle that.
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strlen(s);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
  SIZE_T result = REAL(strlen)(s);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
  return result;
}
#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
#else
#define INIT_STRLEN
#endif

#if SANITIZER_INTERCEPT_STRNLEN
INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
  SIZE_T length = REAL(strnlen)(s, maxlen);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
  return length;
}
#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
#else
#define INIT_STRNLEN
#endif

d215 1
a215 1
                              const char *s1, const char *s2, int result)
d220 2
d231 1
a231 4
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
                             s2, result);
  return result;
d235 1
a235 2
                              const char *s1, const char *s2, uptr n,
                              int result)
d242 2
d251 3
a253 6
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, Min(i + 1, size));
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
                             s2, size, result);
  return result;
a269 3
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
                              const char *s1, const char *s2, int result)

d282 1
a282 4
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
                             s1, s2, result);
  return result;
a284 4
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
                              const char *s1, const char *s2, uptr n,
                              int result)

d297 1
a297 4
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
                             s1, s2, n, result);
  return result;
a318 4

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

a326 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
                             s2, r);
a335 4

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

a341 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
                             s1, s2, r);
a349 73
#if SANITIZER_INTERCEPT_MEMMEM
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
                              const void *s1, SIZE_T len1, const void *s2,
                              SIZE_T len2, void *result)

INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
            SIZE_T len2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
  void *r = REAL(memmem)(s1, len1, s2, len2);
  if (common_flags()->intercept_memmem) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
  }
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
                             s1, len1, s2, len2, r);
  return r;
}

#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
#else
#define INIT_MEMMEM
#endif  // SANITIZER_INTERCEPT_MEMMEM

#if SANITIZER_INTERCEPT_STRCHR
INTERCEPTOR(char*, strchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
  char *result = REAL(strchr)(s, c);
  uptr len = internal_strlen(s);
  uptr n = result ? result - s + 1 : len + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n);
  return result;
}
#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
#else
#define INIT_STRCHR
#endif

#if SANITIZER_INTERCEPT_STRCHRNUL
INTERCEPTOR(char*, strchrnul, const char *s, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
  char *result = REAL(strchrnul)(s, c);
  uptr len = result - s + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
  return result;
}
#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
#else
#define INIT_STRCHRNUL
#endif

#if SANITIZER_INTERCEPT_STRRCHR
INTERCEPTOR(char*, strrchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strrchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
  uptr len = internal_strlen(s);
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, len + 1);
  return REAL(strrchr)(s, c);
}
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
#else
#define INIT_STRRCHR
#endif

a397 58
#if SANITIZER_INTERCEPT_MEMSET
INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memset(dst, v, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);
  if (common_flags()->intercept_intrin)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
  return REAL(memset)(dst, v, size);
}

#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
#else
#define INIT_MEMSET
#endif

#if SANITIZER_INTERCEPT_MEMMOVE
INTERCEPTOR(void*, memmove, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memmove(dst, src, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  return REAL(memmove)(dst, src, size);
}

#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
#else
#define INIT_MEMMOVE
#endif

#if SANITIZER_INTERCEPT_MEMCPY
INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {
    // On OS X, calling internal_memcpy here will cause memory corruptions,
    // because memcpy and memmove are actually aliases of the same
    // implementation.  We need to use internal_memmove here.
    return internal_memmove(dst, src, size);
  }
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
  // due to memcpy being an alias of memmove on OS X.
  return REAL(memcpy)(dst, src, size);
}

#define INIT_MEMCPY COMMON_INTERCEPT_FUNCTION(memcpy)
#else
#define INIT_MEMCPY
#endif

d401 1
a401 2
                              const void *s1, const void *s2, uptr n,
                              int result)
d404 2
d408 2
a409 2
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
d429 1
a429 4
      int r = CharCmpX(c1, c2);
      CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
                                 a1, a2, size, r);
      return r;
d432 1
a432 4
  int result = REAL(memcmp(a1, a2, size));
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
                             a2, size, result);
  return result;
a445 8
#if SANITIZER_WINDOWS
  void *res;
  if (REAL(memchr)) {
    res = REAL(memchr)(s, c, n);
  } else {
    res = internal_memchr(s, c, n);
  }
#else
a446 1
#endif
d491 1
a491 1
  // https://github.com/google/sanitizers/issues/321.
d502 1
a502 1
  // https://github.com/google/sanitizers/issues/321.
d510 1
a510 1
  COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
d543 1
a543 1
  // https://github.com/google/sanitizers/issues/321.
d561 1
a561 1
  // https://github.com/google/sanitizers/issues/321.
d579 1
a579 1
  // https://github.com/google/sanitizers/issues/321.
d826 1
a826 1
  // https://github.com/google/sanitizers/issues/321.
d839 1
a839 1
  // https://github.com/google/sanitizers/issues/321.
d852 1
a852 1
  // https://github.com/google/sanitizers/issues/321.
d865 1
a865 1
  // https://github.com/google/sanitizers/issues/321.
d909 1
a909 1
  // https://github.com/google/sanitizers/issues/321.
d1054 1
a1054 1
// https://github.com/google/sanitizers/issues/321.
d1071 1
a1071 1
// https://github.com/google/sanitizers/issues/321.
d1088 1
a1088 1
// https://github.com/google/sanitizers/issues/321.
d1373 1
a1373 1
  // https://github.com/google/sanitizers/issues/321.
d1388 1
a1388 1
  // https://github.com/google/sanitizers/issues/321.
d1404 1
a1404 1
  // https://github.com/google/sanitizers/issues/321.
d1419 1
a1419 1
  // https://github.com/google/sanitizers/issues/321.
d1488 1
a1488 1
  // https://github.com/google/sanitizers/issues/321.
d1503 1
a1503 1
  // https://github.com/google/sanitizers/issues/321.
d1518 1
a1518 1
  // https://github.com/google/sanitizers/issues/321.
d1533 1
a1533 1
  // https://github.com/google/sanitizers/issues/321.
d1590 1
a1590 1
  // https://github.com/google/sanitizers/issues/321.
d1602 1
a1602 1
  // https://github.com/google/sanitizers/issues/321.
d1629 1
a1629 1
  // https://github.com/google/sanitizers/issues/321.
d1643 1
a1643 1
  // https://github.com/google/sanitizers/issues/321.
a1699 5
static const __sanitizer_glob_t kGlobCopy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};

d1706 4
a1709 2
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
d1737 4
a1740 2
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
d1777 1
a1777 1
  // https://github.com/google/sanitizers/issues/321.
d1795 1
a1795 1
  // https://github.com/google/sanitizers/issues/321.
d1806 1
a1806 1
  // https://github.com/google/sanitizers/issues/321.
d1817 1
a1817 1
  // https://github.com/google/sanitizers/issues/321.
d1831 1
a1831 1
  // https://github.com/google/sanitizers/issues/321.
d1846 1
a1846 1
  // https://github.com/google/sanitizers/issues/321.
d1875 1
a1875 1
  // https://github.com/google/sanitizers/issues/321.
d1887 1
a1887 1
  // https://github.com/google/sanitizers/issues/321.
d1909 1
a1909 1
  // https://github.com/google/sanitizers/issues/321.
d1928 1
a1928 1
  // https://github.com/google/sanitizers/issues/321.
d1955 1
a1955 1
  // https://github.com/google/sanitizers/issues/321.
d1987 1
a1987 1
  // https://github.com/google/sanitizers/issues/321.
d2011 1
a2011 1
  // https://github.com/google/sanitizers/issues/321.
d2097 1
a2097 1
  // https://github.com/google/sanitizers/issues/321.
d2120 1
a2120 1
  // https://github.com/google/sanitizers/issues/321.
d2146 1
a2146 1
  // https://github.com/google/sanitizers/issues/321.
d2172 1
a2172 1
  // https://github.com/google/sanitizers/issues/321.
d2198 1
a2198 1
  // https://github.com/google/sanitizers/issues/321.
d2242 1
a2242 1
  // https://github.com/google/sanitizers/issues/321.
d2262 1
a2262 1
  // https://github.com/google/sanitizers/issues/321.
d2274 1
a2274 1
  // https://github.com/google/sanitizers/issues/321.
d2286 1
a2286 1
  // https://github.com/google/sanitizers/issues/321.
d2296 1
a2296 1
  COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
d2321 1
a2321 1
  // https://github.com/google/sanitizers/issues/321.
a2336 69
#if SANITIZER_INTERCEPT_SENDMSG
static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
  const unsigned kCmsgDataOffset =
      RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));

  char *p = (char *)control;
  char *const control_end = p + controllen;
  while (true) {
    if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
    __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));

    if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;

    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
                                  sizeof(cmsg->cmsg_level));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
                                  sizeof(cmsg->cmsg_type));

    if (cmsg->cmsg_len > kCmsgDataOffset) {
      char *data = p + kCmsgDataOffset;
      unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
      if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
    }

    p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
  }
}

static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                        SSIZE_T maxlen) {
#define R(f) \
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
  R(name);
  R(namelen);
  R(iov);
  R(iovlen);
  R(control);
  R(controllen);
  R(flags);
#undef R
  if (msg->msg_name && msg->msg_namelen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
  if (msg->msg_iov && msg->msg_iovlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
                                  sizeof(*msg->msg_iov) * msg->msg_iovlen);
  read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
  if (msg->msg_control && msg->msg_controllen)
    read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
}

INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
            int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
  if (common_flags()->intercept_send && res >= 0 && msg)
    read_msghdr(ctx, msg, res);
  return res;
}
#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
#else
#define INIT_SENDMSG
#endif

d2345 1
a2345 1
  // https://github.com/google/sanitizers/issues/321.
d2361 1
a2361 1
  // https://github.com/google/sanitizers/issues/321.
d2389 1
a2389 1
  // https://github.com/google/sanitizers/issues/321.
d2401 1
a2401 1
  // https://github.com/google/sanitizers/issues/321.
d2425 1
a2425 1
  // https://github.com/google/sanitizers/issues/321.
d2437 1
a2437 1
  // https://github.com/google/sanitizers/issues/321.
d2484 1
a2484 1
  // https://github.com/google/sanitizers/issues/321.
d2539 1
a2539 1
  // https://github.com/google/sanitizers/issues/321.
d2555 1
a2555 1
  // https://github.com/google/sanitizers/issues/321.
d2604 1
a2604 1
  // https://github.com/google/sanitizers/issues/321.
d2616 1
a2616 1
  // https://github.com/google/sanitizers/issues/321.
d2636 1
a2636 1
  // https://github.com/google/sanitizers/issues/321.
d2653 1
a2653 1
  // https://github.com/google/sanitizers/issues/321.
d2683 1
a2683 1
  // https://github.com/google/sanitizers/issues/321.
d2703 1
a2703 1
  // https://github.com/google/sanitizers/issues/321.
d2720 1
a2720 1
  // https://github.com/google/sanitizers/issues/321.
d2748 1
a2748 1
  // https://github.com/google/sanitizers/issues/321.
d2770 1
a2770 1
  // https://github.com/google/sanitizers/issues/321.
d2790 1
a2790 1
  // https://github.com/google/sanitizers/issues/321.
d2847 1
a2847 1
  // https://github.com/google/sanitizers/issues/321.
d2864 1
a2864 1
  // https://github.com/google/sanitizers/issues/321.
d2906 1
a2906 1
  // https://github.com/google/sanitizers/issues/321.
d2937 1
a2937 1
  // https://github.com/google/sanitizers/issues/321.
d2982 1
a2982 1
  // https://github.com/google/sanitizers/issues/321.
d3035 1
a3035 1
  // https://github.com/google/sanitizers/issues/321.
d3062 1
a3062 1
  // https://github.com/google/sanitizers/issues/321.
d3129 1
a3129 1
  // https://github.com/google/sanitizers/issues/321.
d3155 1
a3155 1
  // https://github.com/google/sanitizers/issues/321.
d3172 1
a3172 1
  // https://github.com/google/sanitizers/issues/321.
d3191 1
a3191 1
  // https://github.com/google/sanitizers/issues/321.
d3207 1
a3207 1
  // https://github.com/google/sanitizers/issues/321.
d3218 1
a3218 1
  // https://github.com/google/sanitizers/issues/321.
d3236 1
a3236 1
  // https://github.com/google/sanitizers/issues/321.
d3254 1
a3254 1
  // https://github.com/google/sanitizers/issues/321.
d3271 1
a3271 1
  // https://github.com/google/sanitizers/issues/321.
d3285 1
a3285 1
  // https://github.com/google/sanitizers/issues/321.
a3304 1
  COMMON_INTERCEPTOR_USER_CALLBACK_START();
a3305 1
  COMMON_INTERCEPTOR_USER_CALLBACK_END();
a3322 2
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
d3330 1
a3330 4
  int res = REAL(pthread_mutex_unlock)(m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
d3393 1
a3393 1
  // https://github.com/google/sanitizers/issues/321.
d3403 1
a3403 1
  // https://github.com/google/sanitizers/issues/321.
d3422 1
a3422 1
  // https://github.com/google/sanitizers/issues/321.
d3432 1
a3432 1
  // https://github.com/google/sanitizers/issues/321.
d3451 1
a3451 1
  // https://github.com/google/sanitizers/issues/321.
d3461 1
a3461 1
  // https://github.com/google/sanitizers/issues/321.
d3480 1
a3480 1
  // https://github.com/google/sanitizers/issues/321.
d3490 1
a3490 1
  // https://github.com/google/sanitizers/issues/321.
d3546 1
a3546 1
  // https://github.com/google/sanitizers/issues/321.
d3559 1
a3559 1
  // https://github.com/google/sanitizers/issues/321.
d3571 1
a3571 1
  // https://github.com/google/sanitizers/issues/321.
d3595 1
a3595 1
  // https://github.com/google/sanitizers/issues/321.
d3607 1
a3607 1
  // https://github.com/google/sanitizers/issues/321.
d3625 1
a3625 1
  // https://github.com/google/sanitizers/issues/321.
d3650 1
a3650 1
  // https://github.com/google/sanitizers/issues/321.
d3663 1
a3663 1
// https://github.com/google/sanitizers/issues/321.
d3702 1
a3702 1
  // https://github.com/google/sanitizers/issues/321.
d3751 1
a3751 1
  // https://github.com/google/sanitizers/issues/321.
d3861 1
a3861 1
      // https://github.com/google/sanitizers/issues/321.
d3879 1
a3879 1
  // https://github.com/google/sanitizers/issues/321.
a3888 14
#if SANITIZER_INTERCEPT_TTYNAME_R
INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
  int res = REAL(ttyname_r)(fd, name, namesize);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
  return res;
}
#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
#else
#define INIT_TTYNAME_R
#endif

d3923 1
a3923 1
  // https://github.com/google/sanitizers/issues/321.
d3933 1
a3933 1
  // https://github.com/google/sanitizers/issues/321.
d3943 1
a3943 1
  // https://github.com/google/sanitizers/issues/321.
d3951 1
a3951 1
  COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
d3962 1
a3962 1
  // https://github.com/google/sanitizers/issues/321.
d3972 1
a3972 1
  // https://github.com/google/sanitizers/issues/321.
d3982 1
a3982 1
  // https://github.com/google/sanitizers/issues/321.
d3990 1
a3990 1
  COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
d4021 1
a4021 1
  COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
d4032 1
a4032 1
  // https://github.com/google/sanitizers/issues/321.
d4042 1
a4042 1
  // https://github.com/google/sanitizers/issues/321.
d4060 1
a4060 1
  // https://github.com/google/sanitizers/issues/321.
d4065 1
a4065 1
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
d4076 1
a4076 1
  // https://github.com/google/sanitizers/issues/321.
d4086 1
a4086 1
  // https://github.com/google/sanitizers/issues/321.
d4116 1
a4116 1
  // https://github.com/google/sanitizers/issues/321.
d4128 1
a4128 1
// https://github.com/google/sanitizers/issues/321.
d4175 1
a4175 1
  // https://github.com/google/sanitizers/issues/321.
d4194 1
a4194 1
  // https://github.com/google/sanitizers/issues/321.
a4205 1
#if !SANITIZER_S390
a4225 76
#if SANITIZER_PPC
// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
// mostly the same semantics as __tls_get_addr, but its presence enables
// some optimizations in linker (which are safe to ignore here).
extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
                          visibility("default")))
void *__tls_get_addr_opt(void *arg);
#endif
#else // SANITIZER_S390
// On s390, we have to intercept two functions here:
// - __tls_get_addr_internal, which is a glibc-internal function that is like
//   the usual __tls_get_addr, but returns a TP-relative offset instead of
//   a proper pointer.  It is used by dlsym for TLS symbols.
// - __tls_get_offset, which is like the above, but also takes a GOT-relative
//   descriptor offset as an argument instead of a pointer.  GOT address
//   is passed in r12, so it's necessary to write it in assembly.  This is
//   the function used by the compiler.
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
  uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
  uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
  void *ptr = reinterpret_cast<void *>(res + tp);
  uptr tls_begin, tls_end;
  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
  if (dtv) {
    // New DTLS block has been allocated.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
  }
  return res;
}
// We need a hidden symbol aliasing the above, so that we can jump
// directly to it from the assembly below.
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
                          visibility("hidden")))
uptr __tls_get_addr_hidden(void *arg);
// Now carefully intercept __tls_get_offset.
asm(
  ".text\n"
// The __intercept_ version has to exist, so that gen_dynamic_list.py
// exports our symbol.
  ".weak __tls_get_offset\n"
  ".type __tls_get_offset, @@function\n"
  "__tls_get_offset:\n"
  ".global __interceptor___tls_get_offset\n"
  ".type __interceptor___tls_get_offset, @@function\n"
  "__interceptor___tls_get_offset:\n"
#ifdef __s390x__
  "la %r2, 0(%r2,%r12)\n"
  "jg __tls_get_addr_hidden\n"
#else
  "basr %r3,0\n"
  "0: la %r2,0(%r2,%r12)\n"
  "l %r4,1f-0b(%r3)\n"
  "b 0(%r4,%r3)\n"
  "1: .long __tls_get_addr_hidden - 0b\n"
#endif
  ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
// Assembly wrapper to call REAL(__tls_get_offset)(arg)
  ".type __tls_get_offset_wrapper, @@function\n"
  "__tls_get_offset_wrapper:\n"
#ifdef __s390x__
  "sgr %r2,%r12\n"
#else
  "sr %r2,%r12\n"
#endif
  "br %r3\n"
  ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
);
#endif // SANITIZER_S390
d4237 1
a4237 1
  // https://github.com/google/sanitizers/issues/321.
d4250 1
a4250 1
  // https://github.com/google/sanitizers/issues/321.
d4260 1
a4260 1
  // https://github.com/google/sanitizers/issues/321.
d4282 1
a4282 1
  // https://github.com/google/sanitizers/issues/321.
d4295 1
a4295 1
  // https://github.com/google/sanitizers/issues/321.
d4307 1
a4307 1
  // https://github.com/google/sanitizers/issues/321.
d4326 1
a4326 1
  // https://github.com/google/sanitizers/issues/321.
d4340 1
a4340 1
  // https://github.com/google/sanitizers/issues/321.
d4365 1
a4365 1
  // https://github.com/google/sanitizers/issues/321.
d4401 1
a4401 1
  // https://github.com/google/sanitizers/issues/321.
d4429 1
a4429 1
  // https://github.com/google/sanitizers/issues/321.
d4530 1
a4530 1
  // https://github.com/google/sanitizers/issues/321.
d4548 1
a4548 1
  // https://github.com/google/sanitizers/issues/321.
d4563 1
a4563 1
  // https://github.com/google/sanitizers/issues/321.
d4570 1
a4570 1
// https://github.com/google/sanitizers/issues/321.
d4624 1
a4624 1
  // https://github.com/google/sanitizers/issues/321.
d4644 1
a4644 1
  // https://github.com/google/sanitizers/issues/321.
d4696 1
a4696 1
  // https://github.com/google/sanitizers/issues/321.
d4778 1
a4778 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4849 1
a4849 1
  // https://github.com/google/sanitizers/issues/321.
d4880 1
a4880 1
  // https://github.com/google/sanitizers/issues/321.
a5293 214
#if SANITIZER_INTERCEPT_CTERMID
INTERCEPTOR(char *, ctermid, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
  char *res = REAL(ctermid)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
#else
#define INIT_CTERMID
#endif

#if SANITIZER_INTERCEPT_CTERMID_R
INTERCEPTOR(char *, ctermid_r, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
  char *res = REAL(ctermid_r)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
#else
#define INIT_CTERMID_R
#endif

#if SANITIZER_INTERCEPT_RECV_RECVFROM
INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
  }
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}

INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
            void *srcaddr, int *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
                           addrlen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SIZE_T srcaddr_sz;
  if (srcaddr) srcaddr_sz = *addrlen;
  (void)srcaddr_sz;  // prevent "set but not used" warning
  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
    if (srcaddr)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
                                          Min((SIZE_T)*addrlen, srcaddr_sz));
  }
  return res;
}
#define INIT_RECV_RECVFROM          \
  COMMON_INTERCEPT_FUNCTION(recv);  \
  COMMON_INTERCEPT_FUNCTION(recvfrom);
#else
#define INIT_RECV_RECVFROM
#endif

#if SANITIZER_INTERCEPT_SEND_SENDTO
INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(send)(fd, buf, len, flags);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}

INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
            void *dstaddr, int addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  // Can't check dstaddr as it may have uninitialized padding at the end.
  SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}
#define INIT_SEND_SENDTO           \
  COMMON_INTERCEPT_FUNCTION(send); \
  COMMON_INTERCEPT_FUNCTION(sendto);
#else
#define INIT_SEND_SENDTO
#endif

#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(eventfd_read)(fd, value);
  if (res == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  int res = REAL(eventfd_write)(fd, value);
  return res;
}
#define INIT_EVENTFD_READ_WRITE            \
  COMMON_INTERCEPT_FUNCTION(eventfd_read); \
  COMMON_INTERCEPT_FUNCTION(eventfd_write)
#else
#define INIT_EVENTFD_READ_WRITE
#endif

#if SANITIZER_INTERCEPT_STAT
INTERCEPTOR(int, stat, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(stat)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
#else
#define INIT_STAT
#endif

#if SANITIZER_INTERCEPT___XSTAT
INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
#else
#define INIT___XSTAT
#endif

#if SANITIZER_INTERCEPT___XSTAT64
INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
#else
#define INIT___XSTAT64
#endif

#if SANITIZER_INTERCEPT___LXSTAT
INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
#else
#define INIT___LXSTAT
#endif

#if SANITIZER_INTERCEPT___LXSTAT64
INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
#else
#define INIT___LXSTAT64
#endif

// FIXME: add other *stat interceptor

a5298 2
  INIT_STRLEN;
  INIT_STRNLEN;
a5304 3
  INIT_STRCHR;
  INIT_STRCHRNUL;
  INIT_STRRCHR;
a5306 3
  INIT_MEMSET;
  INIT_MEMMOVE;
  INIT_MEMCPY;
a5309 1
  INIT_MEMMEM;
a5358 1
  INIT_SENDMSG;
a5427 1
  INIT_TTYNAME_R;
a5467 11
  INIT_CTERMID;
  INIT_CTERMID_R;
  INIT_RECV_RECVFROM;
  INIT_SEND_SENDTO;
  INIT_STAT;
  INIT_EVENTFD_READ_WRITE;
  INIT___XSTAT;
  INIT___XSTAT64;
  INIT___LXSTAT;
  INIT___LXSTAT64;
  // FIXME: add other *stat interceptors.
@


1.5
log
@merge GCC 5.5.0.  this does not include updated man/info pages (yet).
@
text
@d18 1
d23 1
d32 1
d41 16
d63 3
d105 1
a105 1
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) {}
d121 23
d197 2
a198 1
  char* domain = REAL(textdomain)(domainname);
d214 3
d220 2
d229 2
a230 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
d234 3
d242 2
d280 2
a281 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
d307 133
d442 2
d447 1
a447 1
  uptr len = res ? (char*)res - (char*)s + 1 : n;
d911 2
a912 2
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, res - s);
d916 1
a916 1
    if (tm) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
d1115 10
d1201 8
d1225 7
a1231 1
INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
d1233 4
d1245 4
d1331 1
a1331 1
  if (res != 0) unpoison_passwd(ctx, res);
d1338 1
a1338 1
  if (res != 0) unpoison_passwd(ctx, res);
d1346 1
a1346 1
  if (res != 0) unpoison_group(ctx, res);
d1353 1
a1353 1
  if (res != 0) unpoison_group(ctx, res);
d1442 1
a1442 1
  if (res != 0) unpoison_passwd(ctx, res);
d1449 1
a1449 1
  if (res != 0) unpoison_group(ctx, res);;
d1464 1
a1464 1
  if (res != 0) unpoison_passwd(ctx, res);
d1471 1
a1471 1
  if (res != 0) unpoison_group(ctx, res);
d1674 1
a1674 1
  IndirectExternCall(pglob_copy->gl_closedir)(dir);
d1679 1
a1679 1
  return IndirectExternCall(pglob_copy->gl_readdir)(dir);
d1685 1
a1685 1
  return IndirectExternCall(pglob_copy->gl_opendir)(s);
d1691 1
a1691 1
  return IndirectExternCall(pglob_copy->gl_lstat)(s, st);
d1697 1
a1697 1
  return IndirectExternCall(pglob_copy->gl_stat)(s, st);
d1705 1
d1736 1
d1883 1
d2374 10
d2412 1
d2457 1
d2466 2
d2470 9
a2478 3
    else if (request == ptrace_setregset) {
      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
d2496 2
d2503 4
a2506 2
      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
d2567 31
d2605 3
a2607 2
  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
d2617 3
a2619 2
  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
d2750 1
a2750 1
  if (res != (SIZE_T) - 1 && dest && src) {
d2762 22
d2812 1
a2812 1
  char *allocated_path = 0;
d2874 13
d2960 1
a2960 1
  return IndirectExternCall(scandir_filter)(dir);
d2970 1
a2970 1
  return IndirectExternCall(scandir_compar)(a, b);
d2983 5
a2987 4
  int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : 0,
                          compar ? wrapped_scandir_compar : 0);
  scandir_filter = 0;
  scandir_compar = 0;
d3013 1
a3013 1
  return IndirectExternCall(scandir64_filter)(dir);
d3023 1
a3023 1
  return IndirectExternCall(scandir64_compar)(a, b);
d3037 5
a3041 4
      REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : 0,
                      compar ? wrapped_scandir64_compar : 0);
  scandir64_filter = 0;
  scandir64_compar = 0;
d3908 1
d4125 17
d4143 5
a4147 14
            void *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __getdelim, lineptr, n, delim, stream);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(__getdelim)(lineptr, n, delim, stream);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
  }
  return res;
}
d4149 3
a4151 3
            void *stream) {
  return __getdelim(lineptr, n, delim, stream);
}
d4172 1
a4172 1
  void *outbuf_orig = outbuf ? *outbuf : 0;
d4207 6
d4217 3
a4219 1
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res);
d4455 3
a4457 3
DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr);
DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr);
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);
d4797 1
a4797 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4828 1
a4828 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4957 6
a4962 7
  if (fp) {
    COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
    const FileMetadata *m = GetInterceptorMetadata(fp);
    if (m) {
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
      DeleteInterceptorMetadata(fp);
    }
d4964 1
a4964 1
  return REAL(fclose)(fp);
d4975 2
d5047 1
a5047 1
  VPrintf(1, "INFO: %s ignores mlock/mlockall/munlock/munlockall\n",
d5081 213
d5303 4
d5308 1
d5328 1
d5374 1
d5380 1
d5463 5
@


1.4
log
@First steps to port this to NetBSD (compiles now but missing stuff)
@
text
@d2744 2
a2745 1
  if (res && lst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
@


1.4.8.1
log
@Pull up the gcc 5.5 import and assorted fixes, requested by mrg in ticket #381:

external/gpl3/gcc/dist/fixincludes/tests/base/iso/stdlib_c99.h up to 1.1.1.1
external/gpl3/gcc/dist/gcc/config/arm/t-phoenix up to 1.1.1.1
external/gpl3/gcc/dist/gcc/config/phoenix.h     up to 1.1.1.1
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64-freebsd.h up to 1.1.1.1
external/gpl3/gcc/dist/gcc/config/aarch64/t-aarch64-freebsd up to 1.1.1.1
external/gpl3/gcc/dist/gcc/doc/gcov-dump.1      up to 1.1.1.1
external/gpl3/gcc/dist/gcc/doc/gcov-dump.texi   up to 1.1.1.1
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/lfts_config.h up to 1.1.1.1
external/gpl3/gcc/dist/gcc/config/i386/pcommitintrin.h delete
external/gpl3/gcc/dist/gcc/config/i386/stringop.opt delete
external/gpl3/gcc/lib/libgcc/Makefile.wrapper   delete
external/gpl3/gcc/dist/ChangeLog                up to 1.1.1.10
external/gpl3/gcc/dist/LAST_UPDATED             up to 1.9
external/gpl3/gcc/dist/MD5SUMS                  up to 1.9
external/gpl3/gcc/dist/NEWS                     up to 1.7
external/gpl3/gcc/dist/config.sub               up to 1.11
external/gpl3/gcc/dist/configure                up to 1.11
external/gpl3/gcc/dist/configure.ac             up to 1.10
external/gpl3/gcc/dist/INSTALL/binaries.html    up to 1.5
external/gpl3/gcc/dist/INSTALL/build.html       up to 1.6
external/gpl3/gcc/dist/INSTALL/configure.html   up to 1.6
external/gpl3/gcc/dist/INSTALL/download.html    up to 1.5
external/gpl3/gcc/dist/INSTALL/finalinstall.html up to 1.5
external/gpl3/gcc/dist/INSTALL/gfdl.html        up to 1.5
external/gpl3/gcc/dist/INSTALL/index.html       up to 1.5
external/gpl3/gcc/dist/INSTALL/old.html         up to 1.5
external/gpl3/gcc/dist/INSTALL/prerequisites.html up to 1.6
external/gpl3/gcc/dist/INSTALL/specific.html    up to 1.6
external/gpl3/gcc/dist/INSTALL/test.html        up to 1.5
external/gpl3/gcc/dist/config/ChangeLog         up to 1.1.1.10
external/gpl3/gcc/dist/contrib/ChangeLog        up to 1.1.1.10
external/gpl3/gcc/dist/contrib/gcc_update       up to 1.1.1.4
external/gpl3/gcc/dist/contrib/reghunt/ChangeLog up to 1.1.1.9
external/gpl3/gcc/dist/contrib/regression/ChangeLog up to 1.1.1.9
external/gpl3/gcc/dist/fixincludes/ChangeLog    up to 1.1.1.9
external/gpl3/gcc/dist/fixincludes/fixincl.x    up to 1.1.1.6
external/gpl3/gcc/dist/fixincludes/inclhack.def up to 1.1.1.6
external/gpl3/gcc/dist/fixincludes/tests/base/math.h up to 1.1.1.3
external/gpl3/gcc/dist/fixincludes/tests/base/stdio.h up to 1.1.1.5
external/gpl3/gcc/dist/fixincludes/tests/base/stdlib.h up to 1.1.1.3
external/gpl3/gcc/dist/fixincludes/tests/base/iso/stdio_iso.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/BASE-VER             up to 1.1.1.8
external/gpl3/gcc/dist/gcc/ChangeLog            up to 1.15
external/gpl3/gcc/dist/gcc/DATESTAMP            up to 1.1.1.11
external/gpl3/gcc/dist/gcc/Makefile.in          up to 1.14
external/gpl3/gcc/dist/gcc/asan.c               up to 1.1.1.3
external/gpl3/gcc/dist/gcc/auto-profile.c       up to 1.3
external/gpl3/gcc/dist/gcc/bb-reorder.c         up to 1.1.1.6
external/gpl3/gcc/dist/gcc/builtins.c           up to 1.10
external/gpl3/gcc/dist/gcc/calls.c              up to 1.1.1.6
external/gpl3/gcc/dist/gcc/cgraph.c             up to 1.1.1.5
external/gpl3/gcc/dist/gcc/cgraph.h             up to 1.1.1.5
external/gpl3/gcc/dist/gcc/cgraphclones.c       up to 1.1.1.4
external/gpl3/gcc/dist/gcc/cgraphunit.c         up to 1.1.1.6
external/gpl3/gcc/dist/gcc/combine.c            up to 1.1.1.8
external/gpl3/gcc/dist/gcc/common.opt           up to 1.6
external/gpl3/gcc/dist/gcc/config.gcc           up to 1.37
external/gpl3/gcc/dist/gcc/coverage.c           up to 1.1.1.4
external/gpl3/gcc/dist/gcc/coverage.h           up to 1.1.1.4
external/gpl3/gcc/dist/gcc/cselib.c             up to 1.1.1.5
external/gpl3/gcc/dist/gcc/data-streamer-in.c   up to 1.1.1.3
external/gpl3/gcc/dist/gcc/data-streamer-out.c  up to 1.1.1.3
external/gpl3/gcc/dist/gcc/diagnostic.c         up to 1.4
external/gpl3/gcc/dist/gcc/dwarf2out.c          up to 1.8
external/gpl3/gcc/dist/gcc/explow.c             up to 1.1.1.4
external/gpl3/gcc/dist/gcc/expmed.c             up to 1.1.1.4
external/gpl3/gcc/dist/gcc/expr.c               up to 1.10
external/gpl3/gcc/dist/gcc/fold-const.c         up to 1.1.1.11
external/gpl3/gcc/dist/gcc/function.c           up to 1.1.1.7
external/gpl3/gcc/dist/gcc/function.h           up to 1.1.1.4
external/gpl3/gcc/dist/gcc/fwprop.c             up to 1.1.1.5
external/gpl3/gcc/dist/gcc/gcc.c                up to 1.15
external/gpl3/gcc/dist/gcc/gcov-dump.c          up to 1.1.1.5
external/gpl3/gcc/dist/gcc/gcov-io.c            up to 1.1.1.4
external/gpl3/gcc/dist/gcc/gcov-tool.c          up to 1.1.1.2
external/gpl3/gcc/dist/gcc/gcov.c               up to 1.1.1.5
external/gpl3/gcc/dist/gcc/gcse.c               up to 1.1.1.5
external/gpl3/gcc/dist/gcc/gengtype-lex.c       up to 1.7
external/gpl3/gcc/dist/gcc/genmatch.c           up to 1.1.1.2
external/gpl3/gcc/dist/gcc/gimple-fold.c        up to 1.1.1.5
external/gpl3/gcc/dist/gcc/gimple-ssa-strength-reduction.c up to 1.1.1.5
external/gpl3/gcc/dist/gcc/gimplify.c           up to 1.1.1.7
external/gpl3/gcc/dist/gcc/graphite-isl-ast-to-gimple.c up to 1.3
external/gpl3/gcc/dist/gcc/incpath.c            up to 1.1.1.4
external/gpl3/gcc/dist/gcc/internal-fn.c        up to 1.1.1.3
external/gpl3/gcc/dist/gcc/ipa-comdats.c        up to 1.1.1.2
external/gpl3/gcc/dist/gcc/ipa-cp.c             up to 1.1.1.8
external/gpl3/gcc/dist/gcc/ipa-devirt.c         up to 1.1.1.3
external/gpl3/gcc/dist/gcc/ipa-icf-gimple.c     up to 1.1.1.2
external/gpl3/gcc/dist/gcc/ipa-icf-gimple.h     up to 1.1.1.2
external/gpl3/gcc/dist/gcc/ipa-icf.c            up to 1.1.1.3
external/gpl3/gcc/dist/gcc/ipa-icf.h            up to 1.1.1.2
external/gpl3/gcc/dist/gcc/ipa-inline-transform.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/ipa-polymorphic-call.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/ipa-prop.c           up to 1.1.1.7
external/gpl3/gcc/dist/gcc/ipa-pure-const.c     up to 1.1.1.5
external/gpl3/gcc/dist/gcc/ipa-split.c          up to 1.1.1.4
external/gpl3/gcc/dist/gcc/ipa-visibility.c     up to 1.1.1.2
external/gpl3/gcc/dist/gcc/ira-build.c          up to 1.1.1.4
external/gpl3/gcc/dist/gcc/ira-costs.c          up to 1.1.1.4
external/gpl3/gcc/dist/gcc/ira-int.h            up to 1.1.1.4
external/gpl3/gcc/dist/gcc/ira-lives.c          up to 1.1.1.4
external/gpl3/gcc/dist/gcc/loop-doloop.c        up to 1.1.1.5
external/gpl3/gcc/dist/gcc/loop-invariant.c     up to 1.1.1.4
external/gpl3/gcc/dist/gcc/lra-constraints.c    up to 1.1.1.5
external/gpl3/gcc/dist/gcc/lra-remat.c          up to 1.1.1.3
external/gpl3/gcc/dist/gcc/lto-cgraph.c         up to 1.1.1.4
external/gpl3/gcc/dist/gcc/lto-streamer.h       up to 1.1.1.5
external/gpl3/gcc/dist/gcc/match.pd             up to 1.1.1.3
external/gpl3/gcc/dist/gcc/omp-low.c            up to 1.1.1.8
external/gpl3/gcc/dist/gcc/params.def           up to 1.1.1.5
external/gpl3/gcc/dist/gcc/postreload.c         up to 1.1.1.5
external/gpl3/gcc/dist/gcc/pretty-print.c       up to 1.1.1.4
external/gpl3/gcc/dist/gcc/real.c               up to 1.1.1.5
external/gpl3/gcc/dist/gcc/ree.c                up to 1.1.1.4
external/gpl3/gcc/dist/gcc/rtl.h                up to 1.1.1.6
external/gpl3/gcc/dist/gcc/sel-sched.c          up to 1.1.1.6
external/gpl3/gcc/dist/gcc/simplify-rtx.c       up to 1.1.1.4
external/gpl3/gcc/dist/gcc/system.h             up to 1.6
external/gpl3/gcc/dist/gcc/toplev.c             up to 1.2
external/gpl3/gcc/dist/gcc/tree-call-cdce.c     up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-cfg.c           up to 1.8
external/gpl3/gcc/dist/gcc/tree-chkp-opt.c      up to 1.1.1.2
external/gpl3/gcc/dist/gcc/tree-chkp.c          up to 1.1.1.2
external/gpl3/gcc/dist/gcc/tree-chrec.c         up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-data-ref.c      up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tree-eh.c            up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tree-inline.c        up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tree-inline.h        up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-loop-distribution.c up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-nested.c        up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-predcom.c       up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-profile.c       up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-ssa-ccp.c       up to 1.8
external/gpl3/gcc/dist/gcc/tree-ssa-loop-im.c   up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-ssa-loop-ivopts.c up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-ssa-loop-prefetch.c up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-ssa-math-opts.c up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tree-ssa-pre.c       up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-ssa-reassoc.c   up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tree-ssa-sccvn.c     up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tree-ssa-strlen.c    up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-ssa-structalias.c up to 1.1.1.6
external/gpl3/gcc/dist/gcc/tree-ssa-tail-merge.c up to 1.1.1.6
external/gpl3/gcc/dist/gcc/tree-ssa-threadedge.c up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-ssa-uninit.c    up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-ssa.c           up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-vect-data-refs.c up to 1.1.1.9
external/gpl3/gcc/dist/gcc/tree-vect-loop-manip.c up to 1.1.1.5
external/gpl3/gcc/dist/gcc/tree-vrp.c           up to 1.1.1.7
external/gpl3/gcc/dist/gcc/tsan.c               up to 1.1.1.4
external/gpl3/gcc/dist/gcc/ubsan.c              up to 1.1.1.3
external/gpl3/gcc/dist/gcc/value-prof.c         up to 1.1.1.4
external/gpl3/gcc/dist/gcc/c/ChangeLog          up to 1.1.1.8
external/gpl3/gcc/dist/gcc/c/c-decl.c           up to 1.1.1.5
external/gpl3/gcc/dist/gcc/c/c-objc-common.c    up to 1.1.1.3
external/gpl3/gcc/dist/gcc/c/c-parser.c         up to 1.1.1.5
external/gpl3/gcc/dist/gcc/c/c-typeck.c         up to 1.1.1.7
external/gpl3/gcc/dist/gcc/c-family/ChangeLog   up to 1.1.1.7
external/gpl3/gcc/dist/gcc/c-family/c-ada-spec.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/c-family/c-common.c  up to 1.1.1.6
external/gpl3/gcc/dist/gcc/c-family/c-cppbuiltin.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/c-family/c-gimplify.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/c-family/c-omp.c     up to 1.1.1.3
external/gpl3/gcc/dist/gcc/c-family/c-opts.c    up to 1.5
external/gpl3/gcc/dist/gcc/common/config/i386/i386-common.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64-simd.md up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64.c up to 1.1.1.8
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64.md up to 1.1.1.6
external/gpl3/gcc/dist/gcc/config/arm/arm-builtins.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/arm/arm-protos.h up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/arm/arm.c     up to 1.4
external/gpl3/gcc/dist/gcc/config/arm/arm.h     up to 1.15
external/gpl3/gcc/dist/gcc/config/arm/arm.md    up to 1.12
external/gpl3/gcc/dist/gcc/config/arm/freebsd.h up to 1.4
external/gpl3/gcc/dist/gcc/config/arm/neon.md   up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/avr/avr.c     up to 1.1.1.7
external/gpl3/gcc/dist/gcc/config/avr/avr.md    up to 1.1.1.7
external/gpl3/gcc/dist/gcc/config/avr/avr.opt   up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/avr/gen-avr-mmcu-specs.c up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/avr/gen-avr-mmcu-texi.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/i386/avx2intrin.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/avx512bwintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512dqintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512fintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512ifmaintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512ifmavlintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512pfintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512vbmiintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512vbmivlintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512vlbwintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512vldqintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/avx512vlintrin.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/i386/cpuid.h  up to 1.4
external/gpl3/gcc/dist/gcc/config/i386/driver-i386.c up to 1.7
external/gpl3/gcc/dist/gcc/config/i386/gmm_malloc.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/i386-builtin-types.def up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/i386-c.c up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/i386.c   up to 1.14
external/gpl3/gcc/dist/gcc/config/i386/i386.h   up to 1.6
external/gpl3/gcc/dist/gcc/config/i386/i386.md  up to 1.1.1.9
external/gpl3/gcc/dist/gcc/config/i386/i386.opt up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/ia32intrin.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/lwpintrin.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/mmx.md   up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/i386/pmm_malloc.h up to 1.4
external/gpl3/gcc/dist/gcc/config/i386/rdseedintrin.h up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/i386/rtmintrin.h up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/i386/sse.md   up to 1.1.1.8
external/gpl3/gcc/dist/gcc/config/i386/x86-64.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/i386/x86intrin.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/nds32/nds32.md up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/pa/pa-64.h    up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/pa/pa.h       up to 1.7
external/gpl3/gcc/dist/gcc/config/rl78/rl78-expand.md up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/rl78/rl78-real.md up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/rl78/rl78-virt.md up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/rs6000/altivec.md up to 1.1.1.9
external/gpl3/gcc/dist/gcc/config/rs6000/dfp.md up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/rs6000/predicates.md up to 1.1.1.7
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000-c.c up to 1.1.1.8
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000.c up to 1.17
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000.md up to 1.1.1.9
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000.opt up to 1.1.1.6
external/gpl3/gcc/dist/gcc/config/rs6000/vector.md up to 1.1.1.6
external/gpl3/gcc/dist/gcc/config/rs6000/vsx.md up to 1.1.1.10
external/gpl3/gcc/dist/gcc/config/s390/s390-modes.def up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/s390/s390.c   up to 1.1.1.8
external/gpl3/gcc/dist/gcc/config/s390/s390.md  up to 1.1.1.6
external/gpl3/gcc/dist/gcc/config/s390/vx-builtins.md up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/sh/sh-mem.cc  up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/sh/sh.c       up to 1.9
external/gpl3/gcc/dist/gcc/config/sh/sh_treg_combine.cc up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/sparc/sparc.c up to 1.1.1.8
external/gpl3/gcc/dist/gcc/config/sparc/sparc.md up to 1.7
external/gpl3/gcc/dist/gcc/config/xtensa/xtensa.c up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/xtensa/xtensa.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/xtensa/xtensa.md up to 1.1.1.4
external/gpl3/gcc/dist/gcc/cp/ChangeLog         up to 1.1.1.11
external/gpl3/gcc/dist/gcc/cp/call.c            up to 1.1.1.8
external/gpl3/gcc/dist/gcc/cp/class.c           up to 1.1.1.6
external/gpl3/gcc/dist/gcc/cp/constexpr.c       up to 1.1.1.3
external/gpl3/gcc/dist/gcc/cp/cp-gimplify.c     up to 1.1.1.4
external/gpl3/gcc/dist/gcc/cp/decl.c            up to 1.1.1.8
external/gpl3/gcc/dist/gcc/cp/error.c           up to 1.1.1.4
external/gpl3/gcc/dist/gcc/cp/init.c            up to 1.1.1.6
external/gpl3/gcc/dist/gcc/cp/mangle.c          up to 1.1.1.7
external/gpl3/gcc/dist/gcc/cp/name-lookup.c     up to 1.1.1.6
external/gpl3/gcc/dist/gcc/cp/parser.c          up to 1.1.1.10
external/gpl3/gcc/dist/gcc/cp/pt.c              up to 1.1.1.8
external/gpl3/gcc/dist/gcc/cp/semantics.c       up to 1.1.1.9
external/gpl3/gcc/dist/gcc/cp/tree.c            up to 1.1.1.7
external/gpl3/gcc/dist/gcc/cp/typeck.c          up to 1.1.1.9
external/gpl3/gcc/dist/gcc/doc/aot-compile.1    up to 1.7
external/gpl3/gcc/dist/gcc/doc/cppinternals.info up to 1.7
external/gpl3/gcc/dist/gcc/doc/extend.texi      up to 1.1.1.8
external/gpl3/gcc/dist/gcc/doc/fsf-funding.7    up to 1.7
external/gpl3/gcc/dist/gcc/doc/gc-analyze.1     up to 1.7
external/gpl3/gcc/dist/gcc/doc/gcc.texi         up to 1.1.1.5
external/gpl3/gcc/dist/gcc/doc/gccinstall.info  up to 1.7
external/gpl3/gcc/dist/gcc/doc/gccint.info      up to 1.7
external/gpl3/gcc/dist/gcc/doc/gcj-dbtool.1     up to 1.7
external/gpl3/gcc/dist/gcc/doc/gcj.1            up to 1.7
external/gpl3/gcc/dist/gcc/doc/gcj.info         up to 1.7
external/gpl3/gcc/dist/gcc/doc/gcov-tool.1      up to 1.1.1.3
external/gpl3/gcc/dist/gcc/doc/gcov-tool.texi   up to 1.1.1.2
external/gpl3/gcc/dist/gcc/doc/gcov.texi        up to 1.6
external/gpl3/gcc/dist/gcc/doc/generic.texi     up to 1.1.1.4
external/gpl3/gcc/dist/gcc/doc/gfdl.7           up to 1.7
external/gpl3/gcc/dist/gcc/doc/gfortran.1       up to 1.7
external/gpl3/gcc/dist/gcc/doc/gij.1            up to 1.7
external/gpl3/gcc/dist/gcc/doc/gpl.7            up to 1.7
external/gpl3/gcc/dist/gcc/doc/grmic.1          up to 1.7
external/gpl3/gcc/dist/gcc/doc/install.texi     up to 1.1.1.8
external/gpl3/gcc/dist/gcc/doc/invoke.texi      up to 1.12
external/gpl3/gcc/dist/gcc/doc/jcf-dump.1       up to 1.7
external/gpl3/gcc/dist/gcc/doc/jv-convert.1     up to 1.7
external/gpl3/gcc/dist/gcc/doc/lto.texi         up to 1.1.1.3
external/gpl3/gcc/dist/gcc/doc/passes.texi      up to 1.1.1.4
external/gpl3/gcc/dist/gcc/doc/rebuild-gcj-db.1 up to 1.7
external/gpl3/gcc/dist/gcc/doc/rtl.texi         up to 1.1.1.4
external/gpl3/gcc/dist/gcc/jit/ChangeLog        up to 1.1.1.3
external/gpl3/gcc/dist/gcc/lto/ChangeLog        up to 1.1.1.9
external/gpl3/gcc/dist/gcc/lto/lto-lang.c       up to 1.1.1.4
external/gpl3/gcc/dist/gcc/objc/ChangeLog       up to 1.1.1.9
external/gpl3/gcc/dist/gcc/objcp/ChangeLog      up to 1.1.1.9
external/gpl3/gcc/dist/gnattools/ChangeLog      up to 1.1.1.7
external/gpl3/gcc/dist/gotools/ChangeLog        up to 1.1.1.3
external/gpl3/gcc/dist/include/ChangeLog        up to 1.1.1.9
external/gpl3/gcc/dist/intl/ChangeLog           up to 1.1.1.9
external/gpl3/gcc/dist/libbacktrace/ChangeLog   up to 1.1.1.8
external/gpl3/gcc/dist/libcc1/ChangeLog         up to 1.1.1.3
external/gpl3/gcc/dist/libcpp/ChangeLog         up to 1.1.1.9
external/gpl3/gcc/dist/libcpp/line-map.c        up to 1.1.1.6
external/gpl3/gcc/dist/libdecnumber/ChangeLog   up to 1.1.1.9
external/gpl3/gcc/dist/libgcc/ChangeLog         up to 1.1.1.11
external/gpl3/gcc/dist/libgcc/config.host       up to 1.16
external/gpl3/gcc/dist/libgcc/libgcc2.c         up to 1.1.1.4
external/gpl3/gcc/dist/libgcc/libgcov-driver.c  up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/unwind-c.c        up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/aarch64/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/alpha/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/arm/unwind-arm.c up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/arm/unwind-arm.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/bfin/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/i386/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/libbid/ChangeLog up to 1.1.1.9
external/gpl3/gcc/dist/libgcc/config/m68k/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/nios2/linux-unwind.h up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/pa/linux-unwind.h up to 1.1.1.4
external/gpl3/gcc/dist/libgcc/config/rs6000/t-crtstuff up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/sh/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/sparc/lb1spc.S up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/tilepro/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/xtensa/ieee754-df.S up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/xtensa/ieee754-sf.S up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/xtensa/linux-unwind.h up to 1.1.1.3
external/gpl3/gcc/dist/libgcc/config/xtensa/t-elf up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/xtensa/t-linux up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/xtensa/t-windowed up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/xtensa/unwind-dw2-xtensa.c up to 1.4
external/gpl3/gcc/dist/libgomp/ChangeLog        up to 1.1.1.9
external/gpl3/gcc/dist/libgomp/env.c            up to 1.1.1.4
external/gpl3/gcc/dist/libgomp/hashtab.h        up to 1.1.1.2
external/gpl3/gcc/dist/libgomp/libgomp.info     up to 1.7
external/gpl3/gcc/dist/libiberty/ChangeLog      up to 1.1.1.9
external/gpl3/gcc/dist/libiberty/cp-demangle.c  up to 1.1.1.5
external/gpl3/gcc/dist/libiberty/vprintf-support.c up to 1.2
external/gpl3/gcc/dist/libitm/ChangeLog         up to 1.1.1.7
external/gpl3/gcc/dist/libitm/libitm.info       up to 1.1.1.6
external/gpl3/gcc/dist/libobjc/ChangeLog        up to 1.1.1.10
external/gpl3/gcc/dist/libsanitizer/ChangeLog   up to 1.1.1.7
external/gpl3/gcc/dist/libsanitizer/asan/asan_globals.cc up to 1.1.1.3
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc up to 1.5
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc up to 1.9
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.h up to 1.3
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc up to 1.6
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h up to 1.10
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_procmaps_netbsd.cc up to 1.3
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc up to 1.1.1.2
external/gpl3/gcc/dist/libsanitizer/tsan/tsan_platform_linux.cc up to 1.3
external/gpl3/gcc/dist/libsanitizer/tsan/tsan_rtl.cc up to 1.1.1.3
external/gpl3/gcc/dist/libssp/ChangeLog         up to 1.1.1.9
external/gpl3/gcc/dist/libstdc++-v3/ChangeLog   up to 1.1.1.11
external/gpl3/gcc/dist/libstdc++-v3/acinclude.m4 up to 1.4
external/gpl3/gcc/dist/libstdc++-v3/config.h.in up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/configure   up to 1.8
external/gpl3/gcc/dist/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/config/io/basic_file_stdio.cc up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/config/os/mingw32-w64/error_constants.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/doxygen/mainpage.html up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/doc/html/api.html up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/html/faq.html up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/doc/html/ext/lwg-active.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/html/ext/lwg-closed.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/html/ext/lwg-defects.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/abi.html up to 1.1.1.6
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/bugs.html up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/ext_demangling.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/memory.html up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/mt_allocator_impl.html up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/source_code_style.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/source_organization.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/status.html up to 1.1.1.6
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/api.xml up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/faq.xml up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/abi.xml up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/allocator.xml up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/appendix_contributing.xml up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/extensions.xml up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/intro.xml up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/mt_allocator.xml up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/status_cxx2011.xml up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/doc/xml/manual/status_cxx2014.xml up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/Makefile.am up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/Makefile.in up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/bits/allocator.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/basic_ios.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/basic_string.h up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/bits/basic_string.tcc up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/c++config up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/bits/hashtable.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/ios_base.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/istream.tcc up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/list.tcc up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/locale_classes.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/locale_conv.h up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/bits/mask_array.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/predefined_ops.h up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/bits/regex.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/bits/regex.tcc up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/bits/regex_compiler.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/bits/shared_ptr_base.h up to 1.1.1.6
external/gpl3/gcc/dist/libstdc++-v3/include/bits/slice_array.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/sstream.tcc up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_iterator.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_map.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_multimap.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_multiset.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_set.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_stack.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_tree.h up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/bits/uniform_int_dist.h up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/bits/unique_ptr.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/c_global/cmath up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/debug/safe_iterator.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/debug/string up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/algorithm up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/any up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/chrono up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/fs_dir.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/fs_fwd.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/fs_ops.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/fs_path.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/functional up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/optional up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/ratio up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/string_view up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/string_view.tcc up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/system_error up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/tuple up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/experimental/type_traits up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/include/ext/new_allocator.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/ext/pointer.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/ext/pb_ds/detail/binary_heap_/binary_heap_.hpp up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/ext/pb_ds/detail/binary_heap_/insert_fn_imps.hpp up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/atomic up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/chrono up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/complex up to 1.5
external/gpl3/gcc/dist/libstdc++-v3/include/std/functional up to 1.1.1.7
external/gpl3/gcc/dist/libstdc++-v3/include/std/istream up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/include/std/scoped_allocator up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/sstream up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/thread up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/tuple up to 1.1.1.6
external/gpl3/gcc/dist/libstdc++-v3/include/std/utility up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/tr1/cmath up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/libsupc++/cxxabi.h up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/python/libstdcxx/v6/printers.py up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/python/libstdcxx/v6/xmethods.py up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/src/c++11/codecvt.cc up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/src/c++11/cxx11-shim_facets.cc up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/src/c++11/shared_ptr.cc up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/src/filesystem/Makefile.in up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/src/filesystem/dir.cc up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/src/filesystem/ops.cc up to 1.1.1.3
external/gpl3/gcc/dist/lto-plugin/ChangeLog     up to 1.1.1.9
external/gpl3/gcc/dist/lto-plugin/lto-plugin.c  up to 1.1.1.4
external/gpl3/gcc/dist/maintainer-scripts/ChangeLog up to 1.1.1.10
external/gpl3/gcc/lib/libasan/Makefile          up to 1.18
external/gpl3/gcc/lib/libgcc/arch/i386/defs.mk  up to 1.5
external/gpl3/gcc/lib/libgcc/arch/m68000/defs.mk up to 1.7
external/gpl3/gcc/lib/libgcc/arch/x86_64/defs.mk up to 1.4
external/gpl3/gcc/lib/libgcc/libgcc/Makefile    up to 1.28
external/gpl3/gcc/lib/libgcc/libgcov/arch/alpha/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/arm/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/armeb/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/earm/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmeb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmhf/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmhfeb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv4/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv4eb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6eb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6hf/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6hfeb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7eb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7hf/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7hfeb/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/hppa/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/i386/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/ia64/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/m68000/gcov-iov.h up to 1.9
external/gpl3/gcc/lib/libgcc/libgcov/arch/m68k/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/mips64eb/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/mips64el/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/mipseb/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/mipsel/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/powerpc/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/powerpc64/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/sh3eb/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/sh3el/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/sparc/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/sparc64/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/vax/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libgcc/libgcov/arch/x86_64/gcov-iov.h up to 1.10
external/gpl3/gcc/lib/libiberty/defs.mk         up to 1.14
external/gpl3/gcc/lib/libiberty/arch/ia64/config.h up to 1.6
external/gpl3/gcc/lib/liblto_plugin/Makefile    up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/Makefile     up to 1.28
external/gpl3/gcc/lib/libstdc++-v3/arch/alpha/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/alpha/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/alpha/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/arm/c++config.h up to 1.23
external/gpl3/gcc/lib/libstdc++-v3/arch/arm/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/arm/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/armeb/c++config.h up to 1.23
external/gpl3/gcc/lib/libstdc++-v3/arch/armeb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/armeb/gstdint.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/coldfire/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/earm/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/earm/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earm/gstdint.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/earmeb/c++config.h up to 1.19
external/gpl3/gcc/lib/libstdc++-v3/arch/earmeb/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/earmeb/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhf/c++config.h up to 1.19
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhf/defs.mk up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhf/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhfeb/c++config.h up to 1.17
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhfeb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhfeb/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4eb/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4eb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4eb/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6eb/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6eb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6eb/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hfeb/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hfeb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hfeb/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7eb/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7eb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7eb/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hf/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hf/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hf/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hfeb/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hfeb/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hfeb/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/hppa/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/hppa/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/hppa/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/i386/c++config.h up to 1.22
external/gpl3/gcc/lib/libstdc++-v3/arch/i386/defs.mk up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/i386/gstdint.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/ia64/c++config.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/ia64/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/ia64/gstdint.h up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/m68000/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/m68000/defs.mk up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/m68000/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/m68k/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/m68k/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/m68k/gstdint.h up to 1.12
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64eb/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64eb/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64eb/gstdint.h up to 1.12
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64el/c++config.h up to 1.20
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64el/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64el/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/mipseb/c++config.h up to 1.23
external/gpl3/gcc/lib/libstdc++-v3/arch/mipseb/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/mipseb/gstdint.h up to 1.12
external/gpl3/gcc/lib/libstdc++-v3/arch/mipsel/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/mipsel/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/mipsel/gstdint.h up to 1.12
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc/c++config.h up to 1.22
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc64/c++config.h up to 1.10
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc64/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc64/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3eb/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3eb/defs.mk up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3eb/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3el/c++config.h up to 1.23
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3el/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3el/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc/c++config.h up to 1.22
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc/defs.mk up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc64/c++config.h up to 1.21
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc64/defs.mk up to 1.6
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc64/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/vax/c++config.h up to 1.23
external/gpl3/gcc/lib/libstdc++-v3/arch/vax/defs.mk up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/vax/gstdint.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/x86_64/c++config.h up to 1.25
external/gpl3/gcc/lib/libstdc++-v3/arch/x86_64/defs.mk up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/x86_64/gstdint.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/include/bits/Makefile up to 1.19
external/gpl3/gcc/lib/libubsan/Makefile         up to 1.3
external/gpl3/gcc/usr.bin/Makefile.backend      up to 1.6
external/gpl3/gcc/usr.bin/Makefile.inc          up to 1.29
external/gpl3/gcc/usr.bin/backend/Makefile      up to 1.39
external/gpl3/gcc/usr.bin/common/Makefile       up to 1.5
external/gpl3/gcc/usr.bin/frontend/Makefile     up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/alpha/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/alpha/configargs.h up to 1.23
external/gpl3/gcc/usr.bin/gcc/arch/alpha/defs.mk up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/alpha/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/arm/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/arm/configargs.h up to 1.26
external/gpl3/gcc/usr.bin/gcc/arch/arm/defs.mk  up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/arm/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/armeb/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/armeb/configargs.h up to 1.27
external/gpl3/gcc/usr.bin/gcc/arch/armeb/defs.mk up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/armeb/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/earm/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/earm/configargs.h up to 1.24
external/gpl3/gcc/usr.bin/gcc/arch/earm/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/earm/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/configargs.h up to 1.20
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/defs.mk up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/configargs.h up to 1.21
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/configargs.h up to 1.19
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/bversion.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/defs.mk up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/plugin-version.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/hppa/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/hppa/configargs.h up to 1.24
external/gpl3/gcc/usr.bin/gcc/arch/hppa/defs.mk up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/hppa/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/i386/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/i386/configargs.h up to 1.31
external/gpl3/gcc/usr.bin/gcc/arch/i386/defs.mk up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/i386/i386-builtin-types.inc up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/i386/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/ia64/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/ia64/bversion.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/ia64/configargs.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/ia64/defs.mk up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/ia64/plugin-version.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/m68000/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/m68000/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/m68000/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/m68000/plugin-version.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/m68k/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/m68k/configargs.h up to 1.21
external/gpl3/gcc/usr.bin/gcc/arch/m68k/defs.mk up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/m68k/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/configargs.h up to 1.22
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/configargs.h up to 1.23
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/configargs.h up to 1.22
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/defs.mk up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/configargs.h up to 1.23
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/defs.mk up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/configargs.h up to 1.28
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/defs.mk up to 1.13
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/bversion.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/configargs.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/defs.mk up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/plugin-version.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/configargs.h up to 1.24
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/configargs.h up to 1.26
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sparc/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/sparc/configargs.h up to 1.26
external/gpl3/gcc/usr.bin/gcc/arch/sparc/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sparc/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/configargs.h up to 1.26
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/defs.mk up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/vax/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/vax/configargs.h up to 1.24
external/gpl3/gcc/usr.bin/gcc/arch/vax/defs.mk  up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/vax/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/bversion.h up to 1.8
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/configargs.h up to 1.33
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/defs.mk up to 1.13
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/i386-builtin-types.inc up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/plugin-version.h up to 1.11
external/gpl3/gcc/usr.bin/include/arch/i386.mk  up to 1.3
external/gpl3/gcc/usr.bin/include/arch/x86_64.mk up to 1.3
external/gpl3/gcc/usr.bin/libcpp/arch/ia64/config.h up to 1.4
distrib/sets/lists/comp/md.amd64				1.252
distrib/sets/lists/comp/md.i386					1.175
distrib/sets/lists/comp/shl.mi					1.309
distrib/sets/lists/debug/shl.mi					1.187
external/gpl3/gcc/lib/liblto_plugin/Makefile			1.6
lib/libc/stdlib/jemalloc.c					1.43

Update gcc to gcc 5.5.
Bump lib minor for liblto_plugin.so link with -liberty.
The HPPA architectures (1.1 and 2.0) both define quadruple-word
(128-bit) floating point types.  Adjust alignment to match.
@
text
@d2744 1
a2744 2
  if (res >= 0 && lst && size > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
@


1.3
log
@merge GCC 5.3.  round 1.  this probably won't work  :-)

libsanitizer likely needs to be re-ported, though i've done most of
the updating we'll need i think already.
@
text
@d42 1
a42 1
#if SANITIZER_FREEBSD
@


1.2
log
@make this compile, pretending a lot that we are linux.
@
text
@d14 1
d17 1
d20 1
d22 7
d31 2
d34 1
d38 1
a38 1
#ifdef _WIN32
d42 303
d349 4
d354 2
a355 4
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
d358 1
a358 1
#define INIT_READ INTERCEPT_FUNCTION(read)
d367 4
d372 2
a373 4
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
d376 1
a376 1
#define INIT_PREAD INTERCEPT_FUNCTION(pread)
d385 4
d390 2
a391 4
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
d394 1
a394 1
#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
d399 48
d451 2
a452 2
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
d454 2
a455 2
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
d458 1
a458 1
#define INIT_WRITE INTERCEPT_FUNCTION(write)
d467 2
a468 2
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
d470 1
a470 2
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
d473 1
a473 1
#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
d483 2
a484 2
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
d486 1
a486 2
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
d489 1
a489 1
#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
d494 48
d543 3
a545 3
INTERCEPTOR(int, prctl, int option,
            unsigned long arg2, unsigned long arg3,   // NOLINT
            unsigned long arg4, unsigned long arg5) { // NOLINT
d558 1
a558 1
#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
d561 18
a578 1
#endif // SANITIZER_INTERCEPT_PRCTL
d581 10
a590 1
INTERCEPTOR(void *, localtime, unsigned long *timep) {
d593 1
a593 1
  void *res = REAL(localtime)(timep);
d596 1
a596 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
d600 1
a600 1
INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) {
d603 1
a603 1
  void *res = REAL(localtime_r)(timep, result);
d606 1
a606 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
d610 1
a610 1
INTERCEPTOR(void *, gmtime, unsigned long *timep) {
d613 1
a613 1
  void *res = REAL(gmtime)(timep);
d616 1
a616 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
d620 1
a620 1
INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) {
d623 1
a623 1
  void *res = REAL(gmtime_r)(timep, result);
d626 1
a626 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
d633 3
d646 3
d656 1
a656 1
INTERCEPTOR(char *, asctime, void *tm) {
d659 3
d664 1
a664 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
d669 1
a669 1
INTERCEPTOR(char *, asctime_r, void *tm, char *result) {
d672 3
d677 1
a677 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
d682 24
a705 9
#define INIT_LOCALTIME_AND_FRIENDS               \
  INTERCEPT_FUNCTION(localtime);                 \
  INTERCEPT_FUNCTION(localtime_r);               \
  INTERCEPT_FUNCTION(gmtime);                    \
  INTERCEPT_FUNCTION(gmtime_r);                  \
  INTERCEPT_FUNCTION(ctime);                     \
  INTERCEPT_FUNCTION(ctime_r);                   \
  INTERCEPT_FUNCTION(asctime);                   \
  INTERCEPT_FUNCTION(asctime_r);
d708 41
a748 1
#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
a751 2
#include "sanitizer_common_interceptors_scanf.inc"

a785 11
#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__);                          \
    va_list ap;                                                                \
    va_start(ap, format);                                                      \
    int res = vname(__VA_ARGS__, ap);                                          \
    va_end(ap);                                                                \
    return res;                                                                \
  }

d787 1
a787 1
SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
d790 1
a790 1
SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
d793 1
a793 1
SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
d805 1
a805 1
SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
d808 1
a808 1
SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
d811 16
a826 1
SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
d828 109
d938 58
a995 7
#define INIT_SCANF_ISOC99						       \
  INTERCEPT_FUNCTION(__isoc99_scanf);                                          \
  INTERCEPT_FUNCTION(__isoc99_sscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_fscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_vscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_vsscanf);                                        \
  INTERCEPT_FUNCTION(__isoc99_vfscanf);
d997 1
a997 1
#define INIT_SCANF_ISOC99
d1000 35
a1034 3
#define INIT_SCANF							       \
  INIT_SCANF_NORMAL							       \
  INIT_SCANF_ISOC99
d1036 9
d1046 24
a1069 1
#define INIT_SCANF
d1071 8
d1080 3688
a4767 9
#define SANITIZER_COMMON_INTERCEPTORS_INIT                                     \
  INIT_READ;                                                                   \
  INIT_PREAD;                                                                  \
  INIT_PREAD64;                                                                \
  INIT_PRCTL;                                                                  \
  INIT_WRITE;                                                                  \
  INIT_PWRITE;                                                                 \
  INIT_PWRITE64;                                                               \
  INIT_LOCALTIME_AND_FRIENDS;                                                  \
d4769 135
@


1.1
log
@Initial revision
@
text
@d299 8
a315 1
#endif
d317 2
a318 7
#define INIT_SCANF                                                             \
  INTERCEPT_FUNCTION(scanf);                                                   \
  INTERCEPT_FUNCTION(sscanf);                                                  \
  INTERCEPT_FUNCTION(fscanf);                                                  \
  INTERCEPT_FUNCTION(vscanf);                                                  \
  INTERCEPT_FUNCTION(vsscanf);                                                 \
  INTERCEPT_FUNCTION(vfscanf);                                                 \
d325 7
@


1.1.1.1
log
@import GCC 4.8 branch at r206687.

highlights from: http://gcc.gnu.org/gcc-4.6/changes.html

   GCC now has stricter checks for invalid command-line options
   New -Wunused-but-set-variable and -Wunused-but-set-parameter
      warnings
   Many platforms have been obsoleted
   Link-time optimization improvements
   A new switch -fstack-usage has been added
   A new function attribute leaf was introduced
   A new warning, enabled by -Wdouble-promotion
   Support for selectively enabling and disabling warnings via
      #pragma GCC diagnostic has been added
   There is now experimental support for some features from the
      upcoming C1X revision of the ISO C standard
   Improved experimental support for the upcoming C++0x ISO C++
      standard
   G++ now issues clearer diagnostics in several cases
   Updates for ARM, x86, MIPS, PPC/PPC64, SPARC
   Darwin, FreeBSD, Solaris 2, MinGW and Cygwin now all support
      __float128 on 32-bit and 64-bit x86 targets. [*1]

highlights from: http://gcc.gnu.org/gcc-4.7/changes.html

   The -fconserve-space flag has been deprecated
   Support for a new parameter --param case-values-threshold=n
      was added
   Interprocedural and Link-time optimization improvements
   A new built-in, __builtin_assume_aligned, has been added
   A new warning option -Wunused-local-typedefs was added
   A new experimental command-line option -ftrack-macro-expansion
      was added
   Support for atomic operations specifying the C++11/C11 memory
      model has been added
   There is support for some more features from the C11 revision
      of the ISO C standard
   Improved experimental support for the new ISO C++ standard,
      C++11
   Updates for ARM, x86, MIPS, PPC/PPC64, SH, SPARC, TILE*
   A new option (-grecord-gcc-switches) was added

highlights from: http://gcc.gnu.org/gcc-4.8/changes.html

   GCC now uses C++ as its implementation language.  This means
      that to build GCC from sources, you will need a C++
      compiler that understands C++ 2003
   DWARF4 is now the default when generating DWARF debug
      information
   A new general optimization level, -Og, has been introduced
   A new option -ftree-partial-pre was added
   The option -fconserve-space has been removed
   The command-line options -fipa-struct-reorg and
      -fipa-matrix-reorg have been removed
   Interprocedural and Link-time optimization improvements
   AddressSanitizer, a fast memory error detector, has been
      added  [*2]
   A new -Wsizeof-pointer-memaccess warning has been added
   G++ now supports a -std=c++1y option for experimentation
      with features proposed for the next revision of the
      standard, expected around 2014
   Improved experimental support for the new ISO C++ standard,
      C++11
   A new port has been added to support AArch64
   Updates for ARM, x86, MIPS, PPC/PPC64, SH, SPARC, TILE*


[*1] we should support this too!
[*2] we should look into this.
     https://code.google.com/p/address-sanitizer/
@
text
@@


1.1.1.2
log
@import GCC 5.3.0.  see these urls for details which are too large to
include here:

	http://gcc.gnu.org/gcc-4.9/changes.html
	http://gcc.gnu.org/gcc-5/changes.html

(note that GCC 5.x is a release stream like GCC 4.9.x, 4.8.x, etc.)


the main issues we will have are:

The default mode for C is now -std=gnu11 instead of -std=gnu89.

ARM:
The deprecated option -mwords-little-endian has been removed.
The options -mapcs, -mapcs-frame, -mtpcs-frame and -mtpcs-leaf-frame
 which are only applicable to the old ABI have been deprecated.

MIPS:
The o32 ABI has been modified and extended. The o32 64-bit
 floating-point register support is now obsolete and has been removed.
 It has been replaced by three ABI extensions FPXX, FP64A, and FP64.
 The meaning of the -mfp64 command-line option has changed. It is now
 used to enable the FP64A and FP64 ABI extensions.
@
text
@a13 1
//   COMMON_INTERCEPTOR_ENTER_NOIGNORE
a15 1
//   COMMON_INTERCEPTOR_INITIALIZE_RANGE
a17 1
//   COMMON_INTERCEPTOR_FD_ACCESS
a18 7
//   COMMON_INTERCEPTOR_ON_EXIT
//   COMMON_INTERCEPTOR_MUTEX_LOCK
//   COMMON_INTERCEPTOR_MUTEX_UNLOCK
//   COMMON_INTERCEPTOR_MUTEX_REPAIR
//   COMMON_INTERCEPTOR_SET_PTHREAD_NAME
//   COMMON_INTERCEPTOR_HANDLE_RECVMSG
//   COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
a20 2
#include "sanitizer_addrhashmap.h"
#include "sanitizer_placement_new.h"
a21 1
#include "sanitizer_tls_get_addr.h"
d25 1
a25 1
#if SANITIZER_WINDOWS && !defined(va_copy)
a28 303
#if SANITIZER_FREEBSD
#define pthread_setname_np pthread_set_name_np
#endif

#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
#endif

#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
#endif

#ifndef COMMON_INTERCEPTOR_FD_ACCESS
#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_LOCK
#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
#endif

#ifndef COMMON_INTERCEPTOR_FILE_OPEN
#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
#endif

#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
#endif

#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) {}
#endif

#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
#endif

#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
  COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
#endif

#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
#endif

struct FileMetadata {
  // For open_memstream().
  char **addr;
  SIZE_T *size;
};

struct CommonInterceptorMetadata {
  enum {
    CIMT_INVALID = 0,
    CIMT_FILE
  } type;
  union {
    FileMetadata file;
  };
};

typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;

static MetadataHashMap *interceptor_metadata_map;

#if SI_NOT_WINDOWS
UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
                                          const FileMetadata &file) {
  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
  CHECK(h.created());
  h->type = CommonInterceptorMetadata::CIMT_FILE;
  h->file = file;
}

UNUSED static const FileMetadata *GetInterceptorMetadata(
    __sanitizer_FILE *addr) {
  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
                            /* remove */ false,
                            /* create */ false);
  if (h.exists()) {
    CHECK(!h.created());
    CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
    return &h->file;
  } else {
    return 0;
  }
}

UNUSED static void DeleteInterceptorMetadata(void *addr) {
  MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
  CHECK(h.exists());
}
#endif  // SI_NOT_WINDOWS

#if SANITIZER_INTERCEPT_TEXTDOMAIN
INTERCEPTOR(char*, textdomain, const char *domainname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
  char* domain = REAL(textdomain)(domainname);
  if (domain) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
  }
  return domain;
}
#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
#else
#define INIT_TEXTDOMAIN
#endif

#if SANITIZER_INTERCEPT_STRCMP
static inline int CharCmpX(unsigned char c1, unsigned char c2) {
  return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
}

INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
  unsigned char c1, c2;
  uptr i;
  for (i = 0;; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (c1 != c2 || c1 == '\0') break;
  }
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
  return CharCmpX(c1, c2);
}

INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strncmp(s1, s2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
  unsigned char c1 = 0, c2 = 0;
  uptr i;
  for (i = 0; i < size; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (c1 != c2 || c1 == '\0') break;
  }
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
  return CharCmpX(c1, c2);
}

#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
#else
#define INIT_STRCMP
#define INIT_STRNCMP
#endif

#if SANITIZER_INTERCEPT_STRCASECMP
static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
  int c1_low = ToLower(c1);
  int c2_low = ToLower(c2);
  return c1_low - c2_low;
}

INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
  unsigned char c1 = 0, c2 = 0;
  uptr i;
  for (i = 0;; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
  }
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
  return CharCaseCmp(c1, c2);
}

INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
  unsigned char c1 = 0, c2 = 0;
  uptr i;
  for (i = 0; i < n; i++) {
    c1 = (unsigned char)s1[i];
    c2 = (unsigned char)s2[i];
    if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
  }
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
  return CharCaseCmp(c1, c2);
}

#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
#else
#define INIT_STRCASECMP
#define INIT_STRNCASECMP
#endif

#if SANITIZER_INTERCEPT_MEMCHR
INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
  void *res = REAL(memchr)(s, c, n);
  uptr len = res ? (char*)res - (char*)s + 1 : n;
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
  return res;
}

#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
#else
#define INIT_MEMCHR
#endif

#if SANITIZER_INTERCEPT_MEMRCHR
INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
  return REAL(memrchr)(s, c, n);
}

#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
#else
#define INIT_MEMRCHR
#endif

#if SANITIZER_INTERCEPT_FREXP
INTERCEPTOR(double, frexp, double x, int *exp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
  // Assuming frexp() always writes to |exp|.
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
  double res = REAL(frexp)(x, exp);
  return res;
}

#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
#else
#define INIT_FREXP
#endif  // SANITIZER_INTERCEPT_FREXP

#if SANITIZER_INTERCEPT_FREXPF_FREXPL
INTERCEPTOR(float, frexpf, float x, int *exp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  float res = REAL(frexpf)(x, exp);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
  return res;
}

INTERCEPTOR(long double, frexpl, long double x, int *exp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  long double res = REAL(frexpl)(x, exp);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
  return res;
}

#define INIT_FREXPF_FREXPL           \
  COMMON_INTERCEPT_FUNCTION(frexpf); \
  COMMON_INTERCEPT_FUNCTION(frexpl)
#else
#define INIT_FREXPF_FREXPL
#endif  // SANITIZER_INTERCEPT_FREXPF_FREXPL

#if SI_NOT_WINDOWS
static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
                        SIZE_T iovlen, SIZE_T maxlen) {
  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
    maxlen -= sz;
  }
}

static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
                       SIZE_T iovlen, SIZE_T maxlen) {
  COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
  for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
    SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
    maxlen -= sz;
  }
}
#endif

a32 4
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d34 4
a37 2
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
d40 1
a40 1
#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
a48 4
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d50 4
a53 2
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
d56 1
a56 1
#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
a64 4
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d66 4
a69 2
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
d72 1
a72 1
#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
a76 48
#if SANITIZER_INTERCEPT_READV
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
                        int iovcnt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
#else
#define INIT_READV
#endif

#if SANITIZER_INTERCEPT_PREADV
INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
#else
#define INIT_PREADV
#endif

#if SANITIZER_INTERCEPT_PREADV64
INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
  if (res > 0) write_iovec(ctx, iov, iovcnt, res);
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
#else
#define INIT_PREADV64
#endif

d81 2
a82 2
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
d84 2
a85 2
  // FIXME: this check should be _before_ the call to REAL(write), not after
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
d88 1
a88 1
#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
d97 2
a98 2
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
d100 2
a101 1
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
d104 1
a104 1
#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
d114 2
a115 2
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
d117 2
a118 1
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
d121 1
a121 1
#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
a125 48
#if SANITIZER_INTERCEPT_WRITEV
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
                        int iovcnt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
  return res;
}
#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
#else
#define INIT_WRITEV
#endif

#if SANITIZER_INTERCEPT_PWRITEV
INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
  return res;
}
#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
#else
#define INIT_PWRITEV
#endif

#if SANITIZER_INTERCEPT_PWRITEV64
INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
  if (res > 0) read_iovec(ctx, iov, iovcnt, res);
  return res;
}
#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
#else
#define INIT_PWRITEV64
#endif

d127 3
a129 3
INTERCEPTOR(int, prctl, int option, unsigned long arg2,
            unsigned long arg3,                        // NOLINT
            unsigned long arg4, unsigned long arg5) {  // NOLINT
d142 1
a142 1
#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
d145 1
a145 18
#endif  // SANITIZER_INTERCEPT_PRCTL

#if SANITIZER_INTERCEPT_TIME
INTERCEPTOR(unsigned long, time, unsigned long *t) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, time, t);
  unsigned long local_t;
  unsigned long res = REAL(time)(&local_t);
  if (t && res != (unsigned long)-1) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
    *t = local_t;
  }
  return res;
}
#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
#else
#define INIT_TIME
#endif  // SANITIZER_INTERCEPT_TIME
d148 1
a148 10
static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
  if (tm->tm_zone) {
    // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
    // can point to shared memory and tsan would report a data race.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
                                        REAL(strlen(tm->tm_zone)) + 1);
  }
}
INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
d151 1
a151 1
  __sanitizer_tm *res = REAL(localtime)(timep);
d154 1
a154 1
    unpoison_tm(ctx, res);
d158 1
a158 1
INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
d161 1
a161 1
  __sanitizer_tm *res = REAL(localtime_r)(timep, result);
d164 1
a164 1
    unpoison_tm(ctx, res);
d168 1
a168 1
INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
d171 1
a171 1
  __sanitizer_tm *res = REAL(gmtime)(timep);
d174 1
a174 1
    unpoison_tm(ctx, res);
d178 1
a178 1
INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
d181 1
a181 1
  __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
d184 1
a184 1
    unpoison_tm(ctx, res);
a190 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
a200 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d208 1
a208 1
INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
a210 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d213 1
a213 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
d218 1
a218 1
INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
a220 3
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
d223 1
a223 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
d228 9
a236 24
INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
  long res = REAL(mktime)(tm);
  if (res != -1) unpoison_tm(ctx, tm);
  return res;
}
#define INIT_LOCALTIME_AND_FRIENDS        \
  COMMON_INTERCEPT_FUNCTION(localtime);   \
  COMMON_INTERCEPT_FUNCTION(localtime_r); \
  COMMON_INTERCEPT_FUNCTION(gmtime);      \
  COMMON_INTERCEPT_FUNCTION(gmtime_r);    \
  COMMON_INTERCEPT_FUNCTION(ctime);       \
  COMMON_INTERCEPT_FUNCTION(ctime_r);     \
  COMMON_INTERCEPT_FUNCTION(asctime);     \
  COMMON_INTERCEPT_FUNCTION(asctime_r);   \
  COMMON_INTERCEPT_FUNCTION(mktime);
d239 1
a239 1
#endif  // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
d241 1
a241 39
#if SANITIZER_INTERCEPT_STRPTIME
INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
  if (format)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(strptime)(s, format, tm);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, res - s);
    // Do not call unpoison_tm here, because strptime does not, in fact,
    // initialize the entire struct tm. For example, tm_zone pointer is left
    // uninitialized.
    if (tm) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
  }
  return res;
}
#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
#else
#define INIT_STRPTIME
#endif

#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
#include "sanitizer_common_interceptors_format.inc"

#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...)                              \
  {                                                                            \
    void *ctx;                                                                 \
    va_list ap;                                                                \
    va_start(ap, format);                                                      \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap);                     \
    int res = WRAP(vname)(__VA_ARGS__, ap);                                    \
    va_end(ap);                                                                \
    return res;                                                                \
  }

#endif
d243 1
a243 1
#if SANITIZER_INTERCEPT_SCANF
d279 11
d291 1
a291 1
FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
d294 1
a294 1
FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
d297 1
a297 1
FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
d301 1
a301 1
FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
d304 1
a304 1
FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
d307 1
a307 1
FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
d310 13
a322 1
#endif
a323 8
#if SANITIZER_INTERCEPT_SCANF
#define INIT_SCANF                    \
  COMMON_INTERCEPT_FUNCTION(scanf);   \
  COMMON_INTERCEPT_FUNCTION(sscanf);  \
  COMMON_INTERCEPT_FUNCTION(fscanf);  \
  COMMON_INTERCEPT_FUNCTION(vscanf);  \
  COMMON_INTERCEPT_FUNCTION(vsscanf); \
  COMMON_INTERCEPT_FUNCTION(vfscanf);
d328 10
a337 4076
#if SANITIZER_INTERCEPT_ISOC99_SCANF
#define INIT_ISOC99_SCANF                      \
  COMMON_INTERCEPT_FUNCTION(__isoc99_scanf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
#else
#define INIT_ISOC99_SCANF
#endif

#if SANITIZER_INTERCEPT_PRINTF

#define VPRINTF_INTERCEPTOR_ENTER(vname, ...)                                  \
  void *ctx;                                                                   \
  COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                           \
  va_list aq;                                                                  \
  va_copy(aq, ap);

#define VPRINTF_INTERCEPTOR_RETURN()                                           \
  va_end(aq);

#define VPRINTF_INTERCEPTOR_IMPL(vname, ...)                                   \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__);                             \
    if (common_flags()->check_printf)                                          \
      printf_common(ctx, format, aq);                                          \
    int res = REAL(vname)(__VA_ARGS__);                                        \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

// FIXME: under ASan the REAL() call below may write to freed memory and
// corrupt its metadata. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...)                             \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__)                         \
    if (common_flags()->check_printf) {                                        \
      printf_common(ctx, format, aq);                                          \
    }                                                                          \
    int res = REAL(vname)(str, __VA_ARGS__);                                   \
    if (res >= 0) {                                                            \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1);                       \
    }                                                                          \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

// FIXME: under ASan the REAL() call below may write to freed memory and
// corrupt its metadata. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...)                      \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__)                   \
    if (common_flags()->check_printf) {                                        \
      printf_common(ctx, format, aq);                                          \
    }                                                                          \
    int res = REAL(vname)(str, size, __VA_ARGS__);                             \
    if (res >= 0) {                                                            \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1)));  \
    }                                                                          \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

// FIXME: under ASan the REAL() call below may write to freed memory and
// corrupt its metadata. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...)                           \
  {                                                                            \
    VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__)                        \
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *));                 \
    if (common_flags()->check_printf) {                                        \
      printf_common(ctx, format, aq);                                          \
    }                                                                          \
    int res = REAL(vname)(strp, __VA_ARGS__);                                  \
    if (res >= 0) {                                                            \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1);                     \
    }                                                                          \
    VPRINTF_INTERCEPTOR_RETURN();                                              \
    return res;                                                                \
  }

INTERCEPTOR(int, vprintf, const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)

INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
            va_list ap)
VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)

INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
            va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)

INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)

INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)

#if SANITIZER_INTERCEPT_ISOC99_PRINTF
INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)

INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
            const char *format, va_list ap)
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)

INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
            va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)

INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
            va_list ap)
VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
                          ap)

#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF

INTERCEPTOR(int, printf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)

INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)

INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT

INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)

INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)

#if SANITIZER_INTERCEPT_ISOC99_PRINTF
INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)

INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
            ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)

INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)

INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
                        format)

#endif  // SANITIZER_INTERCEPT_ISOC99_PRINTF

#endif  // SANITIZER_INTERCEPT_PRINTF

#if SANITIZER_INTERCEPT_PRINTF
#define INIT_PRINTF                     \
  COMMON_INTERCEPT_FUNCTION(printf);    \
  COMMON_INTERCEPT_FUNCTION(sprintf);   \
  COMMON_INTERCEPT_FUNCTION(snprintf);  \
  COMMON_INTERCEPT_FUNCTION(asprintf);  \
  COMMON_INTERCEPT_FUNCTION(fprintf);   \
  COMMON_INTERCEPT_FUNCTION(vprintf);   \
  COMMON_INTERCEPT_FUNCTION(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION(vasprintf); \
  COMMON_INTERCEPT_FUNCTION(vfprintf);
#else
#define INIT_PRINTF
#endif

#if SANITIZER_INTERCEPT_ISOC99_PRINTF
#define INIT_ISOC99_PRINTF                       \
  COMMON_INTERCEPT_FUNCTION(__isoc99_printf);    \
  COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
  COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
#else
#define INIT_ISOC99_PRINTF
#endif

#if SANITIZER_INTERCEPT_IOCTL
#include "sanitizer_common_interceptors_ioctl.inc"
INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);

  CHECK(ioctl_initialized);

  // Note: TSan does not use common flags, and they are zero-initialized.
  // This effectively disables ioctl handling in TSan.
  if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);

  const ioctl_desc *desc = ioctl_lookup(request);
  ioctl_desc decoded_desc;
  if (!desc) {
    VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
    if (!ioctl_decode(request, &decoded_desc))
      Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
    else
      desc = &decoded_desc;
  }

  if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
  int res = REAL(ioctl)(d, request, arg);
  // FIXME: some ioctls have different return values for success and failure.
  if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
  return res;
}
#define INIT_IOCTL \
  ioctl_init();    \
  COMMON_INTERCEPT_FUNCTION(ioctl);
#else
#define INIT_IOCTL
#endif

#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS || \
    SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT || \
    SANITIZER_INTERCEPT_GETPWENT_R || SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
  if (pwd) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
    if (pwd->pw_name)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_name,
                                          REAL(strlen)(pwd->pw_name) + 1);
    if (pwd->pw_passwd)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_passwd,
                                          REAL(strlen)(pwd->pw_passwd) + 1);
#if !SANITIZER_ANDROID
    if (pwd->pw_gecos)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_gecos,
                                          REAL(strlen)(pwd->pw_gecos) + 1);
#endif
#if SANITIZER_MAC
    if (pwd->pw_class)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_class,
                                          REAL(strlen)(pwd->pw_class) + 1);
#endif
    if (pwd->pw_dir)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_dir,
                                          REAL(strlen)(pwd->pw_dir) + 1);
    if (pwd->pw_shell)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_shell,
                                          REAL(strlen)(pwd->pw_shell) + 1);
  }
}

static void unpoison_group(void *ctx, __sanitizer_group *grp) {
  if (grp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
    if (grp->gr_name)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_name,
                                          REAL(strlen)(grp->gr_name) + 1);
    if (grp->gr_passwd)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_passwd,
                                          REAL(strlen)(grp->gr_passwd) + 1);
    char **p = grp->gr_mem;
    for (; *p; ++p) {
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(*p, REAL(strlen)(*p) + 1);
    }
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_mem,
                                        (p - grp->gr_mem + 1) * sizeof(*p));
  }
}
#endif  // SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS ||
        // SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT ||
        // SANITIZER_INTERCEPT_GETPWENT_R ||
        // SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS

#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  __sanitizer_passwd *res = REAL(getpwnam)(name);
  if (res != 0) unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
  __sanitizer_passwd *res = REAL(getpwuid)(uid);
  if (res != 0) unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  __sanitizer_group *res = REAL(getgrnam)(name);
  if (res != 0) unpoison_group(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
  __sanitizer_group *res = REAL(getgrgid)(gid);
  if (res != 0) unpoison_group(ctx, res);
  return res;
}
#define INIT_GETPWNAM_AND_FRIENDS      \
  COMMON_INTERCEPT_FUNCTION(getpwnam); \
  COMMON_INTERCEPT_FUNCTION(getpwuid); \
  COMMON_INTERCEPT_FUNCTION(getgrnam); \
  COMMON_INTERCEPT_FUNCTION(getgrgid);
#else
#define INIT_GETPWNAM_AND_FRIENDS
#endif

#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
            char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
  if (!res) {
    if (result && *result) unpoison_passwd(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
            SIZE_T buflen, __sanitizer_passwd **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
  if (!res) {
    if (result && *result) unpoison_passwd(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
            char *buf, SIZE_T buflen, __sanitizer_group **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
  if (!res) {
    if (result && *result) unpoison_group(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
            SIZE_T buflen, __sanitizer_group **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
  if (!res) {
    if (result && *result) unpoison_group(ctx, *result);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
#define INIT_GETPWNAM_R_AND_FRIENDS      \
  COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
  COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
  COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
  COMMON_INTERCEPT_FUNCTION(getgrgid_r);
#else
#define INIT_GETPWNAM_R_AND_FRIENDS
#endif

#if SANITIZER_INTERCEPT_GETPWENT
INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
  __sanitizer_passwd *res = REAL(getpwent)(dummy);
  if (res != 0) unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
  __sanitizer_group *res = REAL(getgrent)(dummy);
  if (res != 0) unpoison_group(ctx, res);;
  return res;
}
#define INIT_GETPWENT                  \
  COMMON_INTERCEPT_FUNCTION(getpwent); \
  COMMON_INTERCEPT_FUNCTION(getgrent);
#else
#define INIT_GETPWENT
#endif

#if SANITIZER_INTERCEPT_FGETPWENT
INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
  __sanitizer_passwd *res = REAL(fgetpwent)(fp);
  if (res != 0) unpoison_passwd(ctx, res);
  return res;
}
INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
  __sanitizer_group *res = REAL(fgetgrent)(fp);
  if (res != 0) unpoison_group(ctx, res);
  return res;
}
#define INIT_FGETPWENT                  \
  COMMON_INTERCEPT_FUNCTION(fgetpwent); \
  COMMON_INTERCEPT_FUNCTION(fgetgrent);
#else
#define INIT_FGETPWENT
#endif

#if SANITIZER_INTERCEPT_GETPWENT_R
INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
            __sanitizer_group **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_group **pwbufp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
  if (!res) {
    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
  return res;
}
#define INIT_GETPWENT_R                   \
  COMMON_INTERCEPT_FUNCTION(getpwent_r);  \
  COMMON_INTERCEPT_FUNCTION(fgetpwent_r); \
  COMMON_INTERCEPT_FUNCTION(getgrent_r);  \
  COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
#else
#define INIT_GETPWENT_R
#endif

#if SANITIZER_INTERCEPT_SETPWENT
// The only thing these interceptors do is disable any nested interceptors.
// These functions may open nss modules and call uninstrumented functions from
// them, and we don't want things like strlen() to trigger.
INTERCEPTOR(void, setpwent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
  REAL(setpwent)(dummy);
}
INTERCEPTOR(void, endpwent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
  REAL(endpwent)(dummy);
}
INTERCEPTOR(void, setgrent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
  REAL(setgrent)(dummy);
}
INTERCEPTOR(void, endgrent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
  REAL(endgrent)(dummy);
}
#define INIT_SETPWENT                  \
  COMMON_INTERCEPT_FUNCTION(setpwent); \
  COMMON_INTERCEPT_FUNCTION(endpwent); \
  COMMON_INTERCEPT_FUNCTION(setgrent); \
  COMMON_INTERCEPT_FUNCTION(endgrent);
#else
#define INIT_SETPWENT
#endif

#if SANITIZER_INTERCEPT_CLOCK_GETTIME
INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(clock_getres)(clk_id, tp);
  if (!res && tp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
  }
  return res;
}
INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(clock_gettime)(clk_id, tp);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
  }
  return res;
}
INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
  return REAL(clock_settime)(clk_id, tp);
}
#define INIT_CLOCK_GETTIME                  \
  COMMON_INTERCEPT_FUNCTION(clock_getres);  \
  COMMON_INTERCEPT_FUNCTION(clock_gettime); \
  COMMON_INTERCEPT_FUNCTION(clock_settime);
#else
#define INIT_CLOCK_GETTIME
#endif

#if SANITIZER_INTERCEPT_GETITIMER
INTERCEPTOR(int, getitimer, int which, void *curr_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getitimer)(which, curr_value);
  if (!res && curr_value) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
  }
  return res;
}
INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
  if (new_value)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(setitimer)(which, new_value, old_value);
  if (!res && old_value) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
  }
  return res;
}
#define INIT_GETITIMER                  \
  COMMON_INTERCEPT_FUNCTION(getitimer); \
  COMMON_INTERCEPT_FUNCTION(setitimer);
#else
#define INIT_GETITIMER
#endif

#if SANITIZER_INTERCEPT_GLOB
static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
  // +1 for NULL pointer at the end.
  if (pglob->gl_pathv)
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
  for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
    char *p = pglob->gl_pathv[i];
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
  }
}

static THREADLOCAL __sanitizer_glob_t *pglob_copy;

static void wrapped_gl_closedir(void *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  IndirectExternCall(pglob_copy->gl_closedir)(dir);
}

static void *wrapped_gl_readdir(void *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  return IndirectExternCall(pglob_copy->gl_readdir)(dir);
}

static void *wrapped_gl_opendir(const char *s) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
  return IndirectExternCall(pglob_copy->gl_opendir)(s);
}

static int wrapped_gl_lstat(const char *s, void *st) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
  return IndirectExternCall(pglob_copy->gl_lstat)(s, st);
}

static int wrapped_gl_stat(const char *s, void *st) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
  return IndirectExternCall(pglob_copy->gl_stat)(s, st);
}

INTERCEPTOR(int, glob, const char *pattern, int flags,
            int (*errfunc)(const char *epath, int eerrno),
            __sanitizer_glob_t *pglob) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
  __sanitizer_glob_t glob_copy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
    pglob_copy = &glob_copy;
  }
  int res = REAL(glob)(pattern, flags, errfunc, pglob);
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
  }
  pglob_copy = 0;
  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
  return res;
}

INTERCEPTOR(int, glob64, const char *pattern, int flags,
            int (*errfunc)(const char *epath, int eerrno),
            __sanitizer_glob_t *pglob) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
  __sanitizer_glob_t glob_copy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
    pglob_copy = &glob_copy;
  }
  int res = REAL(glob64)(pattern, flags, errfunc, pglob);
  if (flags & glob_altdirfunc) {
    Swap(pglob->gl_closedir, glob_copy.gl_closedir);
    Swap(pglob->gl_readdir, glob_copy.gl_readdir);
    Swap(pglob->gl_opendir, glob_copy.gl_opendir);
    Swap(pglob->gl_lstat, glob_copy.gl_lstat);
    Swap(pglob->gl_stat, glob_copy.gl_stat);
  }
  pglob_copy = 0;
  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
  return res;
}
#define INIT_GLOB                  \
  COMMON_INTERCEPT_FUNCTION(glob); \
  COMMON_INTERCEPT_FUNCTION(glob64);
#else  // SANITIZER_INTERCEPT_GLOB
#define INIT_GLOB
#endif  // SANITIZER_INTERCEPT_GLOB

#if SANITIZER_INTERCEPT_WAIT
// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
// details.
INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(wait)(status);
  if (res != -1 && status)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
  return res;
}
// On FreeBSD id_t is always 64-bit wide.
#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
                        int options) {
#else
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
                        int options) {
#endif
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(waitid)(idtype, id, infop, options);
  if (res != -1 && infop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
  return res;
}
INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(waitpid)(pid, status, options);
  if (res != -1 && status)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
  return res;
}
INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(wait3)(status, options, rusage);
  if (res != -1) {
    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
  }
  return res;
}
#if SANITIZER_ANDROID
INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(__wait4)(pid, status, options, rusage);
  if (res != -1) {
    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
  }
  return res;
}
#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
#else
INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(wait4)(pid, status, options, rusage);
  if (res != -1) {
    if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
    if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
  }
  return res;
}
#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
#endif  // SANITIZER_ANDROID
#define INIT_WAIT                     \
  COMMON_INTERCEPT_FUNCTION(wait);    \
  COMMON_INTERCEPT_FUNCTION(waitid);  \
  COMMON_INTERCEPT_FUNCTION(waitpid); \
  COMMON_INTERCEPT_FUNCTION(wait3);
#else
#define INIT_WAIT
#define INIT_WAIT4
#endif

#if SANITIZER_INTERCEPT_INET
INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
  uptr sz = __sanitizer_in_addr_sz(af);
  if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
  // FIXME: figure out read size based on the address family.
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(inet_ntop)(af, src, dst, size);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}
INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
  // FIXME: figure out read size based on the address family.
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(inet_pton)(af, src, dst);
  if (res == 1) {
    uptr sz = __sanitizer_in_addr_sz(af);
    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
  }
  return res;
}
#define INIT_INET                       \
  COMMON_INTERCEPT_FUNCTION(inet_ntop); \
  COMMON_INTERCEPT_FUNCTION(inet_pton);
#else
#define INIT_INET
#endif

#if SANITIZER_INTERCEPT_INET
INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(inet_aton)(cp, dst);
  if (res != 0) {
    uptr sz = __sanitizer_in_addr_sz(af_inet);
    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
  }
  return res;
}
#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
#else
#define INIT_INET_ATON
#endif

#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(pthread_getschedparam)(thread, policy, param);
  if (res == 0) {
    if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
    if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
  }
  return res;
}
#define INIT_PTHREAD_GETSCHEDPARAM \
  COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
#else
#define INIT_PTHREAD_GETSCHEDPARAM
#endif

#if SANITIZER_INTERCEPT_GETADDRINFO
INTERCEPTOR(int, getaddrinfo, char *node, char *service,
            struct __sanitizer_addrinfo *hints,
            struct __sanitizer_addrinfo **out) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
  if (service)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
  if (hints)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getaddrinfo)(node, service, hints, out);
  if (res == 0 && out) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
    struct __sanitizer_addrinfo *p = *out;
    while (p) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
      if (p->ai_addr)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
      if (p->ai_canonname)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
                                       REAL(strlen)(p->ai_canonname) + 1);
      p = p->ai_next;
    }
  }
  return res;
}
#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
#else
#define INIT_GETADDRINFO
#endif

#if SANITIZER_INTERCEPT_GETNAMEINFO
INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
            unsigned hostlen, char *serv, unsigned servlen, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
                           serv, servlen, flags);
  // FIXME: consider adding READ_RANGE(sockaddr, salen)
  // There is padding in in_addr that may make this too noisy
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res =
      REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
  if (res == 0) {
    if (host && hostlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
    if (serv && servlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
  }
  return res;
}
#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
#else
#define INIT_GETNAMEINFO
#endif

#if SANITIZER_INTERCEPT_GETSOCKNAME
INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
  int addrlen_in = *addrlen;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getsockname)(sock_fd, addr, addrlen);
  if (res == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
  }
  return res;
}
#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
#else
#define INIT_GETSOCKNAME
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
  if (h->h_name)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
  char **p = h->h_aliases;
  while (*p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
    ++p;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(
      ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
  p = h->h_addr_list;
  while (*p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
    ++p;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(
      ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
}
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
  struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
  if (res) write_hostent(ctx, res);
  return res;
}

INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
            int type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
  struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
  if (res) write_hostent(ctx, res);
  return res;
}

INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
  struct __sanitizer_hostent *res = REAL(gethostent)(fake);
  if (res) write_hostent(ctx, res);
  return res;
}

INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
  struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
  if (res) write_hostent(ctx, res);
  return res;
}
#define INIT_GETHOSTBYNAME                  \
  COMMON_INTERCEPT_FUNCTION(gethostent);    \
  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
  COMMON_INTERCEPT_FUNCTION(gethostbyname); \
  COMMON_INTERCEPT_FUNCTION(gethostbyname2);
#else
#define INIT_GETHOSTBYNAME
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
            char *buf, SIZE_T buflen, __sanitizer_hostent **result,
            int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
                           h_errnop);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
#else
#define INIT_GETHOSTBYNAME_R
#endif

#if SANITIZER_INTERCEPT_GETHOSTENT_R
INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
            SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
                           h_errnop);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTENT_R                  \
  COMMON_INTERCEPT_FUNCTION(gethostent_r);
#else
#define INIT_GETHOSTENT_R
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
            __sanitizer_hostent **result, int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
                           buflen, result, h_errnop);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
                                  h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTBYADDR_R                  \
  COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
#else
#define INIT_GETHOSTBYADDR_R
#endif

#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
            struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
            __sanitizer_hostent **result, int *h_errnop) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
                           result, h_errnop);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res =
      REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
  if (result) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (res == 0 && *result) write_hostent(ctx, *result);
  }
  if (h_errnop)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
  return res;
}
#define INIT_GETHOSTBYNAME2_R                  \
  COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
#else
#define INIT_GETHOSTBYNAME2_R
#endif

#if SANITIZER_INTERCEPT_GETSOCKOPT
INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
            int *optlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
                           optlen);
  if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
  if (res == 0)
    if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
  return res;
}
#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
#else
#define INIT_GETSOCKOPT
#endif

#if SANITIZER_INTERCEPT_ACCEPT
INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
  unsigned addrlen0 = 0;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addrlen0 = *addrlen;
  }
  int fd2 = REAL(accept)(fd, addr, addrlen);
  if (fd2 >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
    if (addr && addrlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
  }
  return fd2;
}
#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
#else
#define INIT_ACCEPT
#endif

#if SANITIZER_INTERCEPT_ACCEPT4
INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
  unsigned addrlen0 = 0;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addrlen0 = *addrlen;
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int fd2 = REAL(accept4)(fd, addr, addrlen, f);
  if (fd2 >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
    if (addr && addrlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
  }
  return fd2;
}
#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
#else
#define INIT_ACCEPT4
#endif

#if SANITIZER_INTERCEPT_MODF
INTERCEPTOR(double, modf, double x, double *iptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  double res = REAL(modf)(x, iptr);
  if (iptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
  }
  return res;
}
INTERCEPTOR(float, modff, float x, float *iptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  float res = REAL(modff)(x, iptr);
  if (iptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
  }
  return res;
}
INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  long double res = REAL(modfl)(x, iptr);
  if (iptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
  }
  return res;
}
#define INIT_MODF                   \
  COMMON_INTERCEPT_FUNCTION(modf);  \
  COMMON_INTERCEPT_FUNCTION(modff); \
  COMMON_INTERCEPT_FUNCTION(modfl);
#else
#define INIT_MODF
#endif

#if SANITIZER_INTERCEPT_RECVMSG
static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                         SSIZE_T maxlen) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
  if (msg->msg_name && msg->msg_namelen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
  if (msg->msg_iov && msg->msg_iovlen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
                                   sizeof(*msg->msg_iov) * msg->msg_iovlen);
  write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
  if (msg->msg_control && msg->msg_controllen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
}

INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
            int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
  if (res >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
    if (msg) {
      write_msghdr(ctx, msg, res);
      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
    }
  }
  return res;
}
#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
#else
#define INIT_RECVMSG
#endif

#if SANITIZER_INTERCEPT_GETPEERNAME
INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
  unsigned addr_sz;
  if (addrlen) addr_sz = *addrlen;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getpeername)(sockfd, addr, addrlen);
  if (!res && addr && addrlen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
  return res;
}
#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
#else
#define INIT_GETPEERNAME
#endif

#if SANITIZER_INTERCEPT_SYSINFO
INTERCEPTOR(int, sysinfo, void *info) {
  void *ctx;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
  int res = REAL(sysinfo)(info);
  if (!res && info)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
  return res;
}
#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
#else
#define INIT_SYSINFO
#endif

#if SANITIZER_INTERCEPT_READDIR
INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  __sanitizer_dirent *res = REAL(readdir)(dirp);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
  return res;
}

INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
            __sanitizer_dirent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(readdir_r)(dirp, entry, result);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (*result)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
  }
  return res;
}

#define INIT_READDIR                  \
  COMMON_INTERCEPT_FUNCTION(readdir); \
  COMMON_INTERCEPT_FUNCTION(readdir_r);
#else
#define INIT_READDIR
#endif

#if SANITIZER_INTERCEPT_READDIR64
INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
  return res;
}

INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
            __sanitizer_dirent64 **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(readdir64_r)(dirp, entry, result);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
    if (*result)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
  }
  return res;
}
#define INIT_READDIR64                  \
  COMMON_INTERCEPT_FUNCTION(readdir64); \
  COMMON_INTERCEPT_FUNCTION(readdir64_r);
#else
#define INIT_READDIR64
#endif

#if SANITIZER_INTERCEPT_PTRACE
INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);

  if (data) {
    if (request == ptrace_setregs)
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
    else if (request == ptrace_setfpregs)
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
    else if (request == ptrace_setfpxregs)
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
    else if (request == ptrace_setsiginfo)
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
    else if (request == ptrace_setregset) {
      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
    }
  }

  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  uptr res = REAL(ptrace)(request, pid, addr, data);

  if (!res && data) {
    // Note that PEEK* requests assign different meaning to the return value.
    // This function does not handle them (nor does it need to).
    if (request == ptrace_getregs)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
    else if (request == ptrace_getfpregs)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
    else if (request == ptrace_getfpxregs)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
    else if (request == ptrace_getsiginfo)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
    else if (request == ptrace_geteventmsg)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
    else if (request == ptrace_getregset) {
      __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
    }
  }
  return res;
}

#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
#else
#define INIT_PTRACE
#endif

#if SANITIZER_INTERCEPT_SETLOCALE
INTERCEPTOR(char *, setlocale, int category, char *locale) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
  if (locale)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
  char *res = REAL(setlocale)(category, locale);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}

#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
#else
#define INIT_SETLOCALE
#endif

#if SANITIZER_INTERCEPT_GETCWD
INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(getcwd)(buf, size);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}
#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
#else
#define INIT_GETCWD
#endif

#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
INTERCEPTOR(char *, get_current_dir_name, int fake) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(get_current_dir_name)(fake);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}

#define INIT_GET_CURRENT_DIR_NAME \
  COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
#else
#define INIT_GET_CURRENT_DIR_NAME
#endif

#if SANITIZER_INTERCEPT_STRTOIMAX
INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
  return res;
}

INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
  if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
  return res;
}

#define INIT_STRTOIMAX                  \
  COMMON_INTERCEPT_FUNCTION(strtoimax); \
  COMMON_INTERCEPT_FUNCTION(strtoumax);
#else
#define INIT_STRTOIMAX
#endif

#if SANITIZER_INTERCEPT_MBSTOWCS
INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(mbstowcs)(dest, src, len);
  if (res != (SIZE_T) - 1 && dest) {
    SIZE_T write_cnt = res + (res < len);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
  }
  return res;
}

INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
            void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
  if (res != (SIZE_T)(-1) && dest && src) {
    // This function, and several others, may or may not write the terminating
    // \0 character. They write it iff they clear *src.
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
  }
  return res;
}

#define INIT_MBSTOWCS                  \
  COMMON_INTERCEPT_FUNCTION(mbstowcs); \
  COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
#else
#define INIT_MBSTOWCS
#endif

#if SANITIZER_INTERCEPT_MBSNRTOWCS
INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
            SIZE_T len, void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
  if (src) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
  }
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
  if (res != (SIZE_T)(-1) && dest && src) {
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
  }
  return res;
}

#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
#else
#define INIT_MBSNRTOWCS
#endif

#if SANITIZER_INTERCEPT_WCSTOMBS
INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(wcstombs)(dest, src, len);
  if (res != (SIZE_T) - 1 && dest) {
    SIZE_T write_cnt = res + (res < len);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
            void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
  if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
  if (res != (SIZE_T) - 1 && dest && src) {
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

#define INIT_WCSTOMBS                  \
  COMMON_INTERCEPT_FUNCTION(wcstombs); \
  COMMON_INTERCEPT_FUNCTION(wcsrtombs);
#else
#define INIT_WCSTOMBS
#endif

#if SANITIZER_INTERCEPT_WCSNRTOMBS
INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
            SIZE_T len, void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
  if (src) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
    if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
  }
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
  if (res != (SIZE_T) - 1 && dest && src) {
    SIZE_T write_cnt = res + !*src;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
#else
#define INIT_WCSNRTOMBS
#endif

#if SANITIZER_INTERCEPT_TCGETATTR
INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(tcgetattr)(fd, termios_p);
  if (!res && termios_p)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
  return res;
}

#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
#else
#define INIT_TCGETATTR
#endif

#if SANITIZER_INTERCEPT_REALPATH
INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);

  // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
  // version of a versioned symbol. For realpath(), this gives us something
  // (called __old_realpath) that does not handle NULL in the second argument.
  // Handle it as part of the interceptor.
  char *allocated_path = 0;
  if (!resolved_path)
    allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);

  char *res = REAL(realpath)(path, resolved_path);
  if (allocated_path && !res) WRAP(free)(allocated_path);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}
#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
#else
#define INIT_REALPATH
#endif

#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  char *res = REAL(canonicalize_file_name)(path);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}
#define INIT_CANONICALIZE_FILE_NAME \
  COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
#else
#define INIT_CANONICALIZE_FILE_NAME
#endif

#if SANITIZER_INTERCEPT_CONFSTR
INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(confstr)(name, buf, len);
  if (buf && res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
  return res;
}
#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
#else
#define INIT_CONFSTR
#endif

#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
  return res;
}
#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
#else
#define INIT_SCHED_GETAFFINITY
#endif

#if SANITIZER_INTERCEPT_STRERROR
INTERCEPTOR(char *, strerror, int errnum) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
  char *res = REAL(strerror)(errnum);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  return res;
}
#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
#else
#define INIT_STRERROR
#endif

#if SANITIZER_INTERCEPT_STRERROR_R
INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(strerror_r)(errnum, buf, buflen);
  // There are 2 versions of strerror_r:
  //  * POSIX version returns 0 on success, negative error code on failure,
  //    writes message to buf.
  //  * GNU version returns message pointer, which points to either buf or some
  //    static storage.
  SIZE_T posix_res = (SIZE_T)res;
  if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
    // POSIX version. Spec is not clear on whether buf is NULL-terminated.
    // At least on OSX, buf contents are valid even when the call fails.
    SIZE_T sz = internal_strnlen(buf, buflen);
    if (sz < buflen) ++sz;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  } else {
    // GNU version.
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
#else
#define INIT_STRERROR_R
#endif

#if SANITIZER_INTERCEPT_XPG_STRERROR_R
INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
  // This version always returns a null-terminated string.
  if (buf && buflen)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
  return res;
}
#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
#else
#define INIT_XPG_STRERROR_R
#endif

#if SANITIZER_INTERCEPT_SCANDIR
typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
                                const struct __sanitizer_dirent **);

static THREADLOCAL scandir_filter_f scandir_filter;
static THREADLOCAL scandir_compar_f scandir_compar;

static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
  return IndirectExternCall(scandir_filter)(dir);
}

static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
                                  const struct __sanitizer_dirent **b) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
  return IndirectExternCall(scandir_compar)(a, b);
}

INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
            scandir_filter_f filter, scandir_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
  scandir_filter = filter;
  scandir_compar = compar;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : 0,
                          compar ? wrapped_scandir_compar : 0);
  scandir_filter = 0;
  scandir_compar = 0;
  if (namelist && res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
    for (int i = 0; i < res; ++i)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
                                     (*namelist)[i]->d_reclen);
  }
  return res;
}
#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
#else
#define INIT_SCANDIR
#endif

#if SANITIZER_INTERCEPT_SCANDIR64
typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
                                  const struct __sanitizer_dirent64 **);

static THREADLOCAL scandir64_filter_f scandir64_filter;
static THREADLOCAL scandir64_compar_f scandir64_compar;

static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
  return IndirectExternCall(scandir64_filter)(dir);
}

static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
                                    const struct __sanitizer_dirent64 **b) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
  return IndirectExternCall(scandir64_compar)(a, b);
}

INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
            scandir64_filter_f filter, scandir64_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
  scandir64_filter = filter;
  scandir64_compar = compar;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res =
      REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : 0,
                      compar ? wrapped_scandir64_compar : 0);
  scandir64_filter = 0;
  scandir64_compar = 0;
  if (namelist && res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
    for (int i = 0; i < res; ++i)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
                                     (*namelist)[i]->d_reclen);
  }
  return res;
}
#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
#else
#define INIT_SCANDIR64
#endif

#if SANITIZER_INTERCEPT_GETGROUPS
INTERCEPTOR(int, getgroups, int size, u32 *lst) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getgroups)(size, lst);
  if (res && lst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
  return res;
}
#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
#else
#define INIT_GETGROUPS
#endif

#if SANITIZER_INTERCEPT_POLL
static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
                        __sanitizer_nfds_t nfds) {
  for (unsigned i = 0; i < nfds; ++i) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
  }
}

static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
                         __sanitizer_nfds_t nfds) {
  for (unsigned i = 0; i < nfds; ++i)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
                                   sizeof(fds[i].revents));
}

INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
            int timeout) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
  if (fds && nfds) read_pollfd(ctx, fds, nfds);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
  if (fds && nfds) write_pollfd(ctx, fds, nfds);
  return res;
}
#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
#else
#define INIT_POLL
#endif

#if SANITIZER_INTERCEPT_PPOLL
INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
            void *timeout_ts, __sanitizer_sigset_t *sigmask) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
  if (fds && nfds) read_pollfd(ctx, fds, nfds);
  if (timeout_ts)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
  int res =
      COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
  if (fds && nfds) write_pollfd(ctx, fds, nfds);
  return res;
}
#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
#else
#define INIT_PPOLL
#endif

#if SANITIZER_INTERCEPT_WORDEXP
INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(wordexp)(s, p, flags);
  if (!res && p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
    if (p->we_wordc)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
                                     sizeof(*p->we_wordv) * p->we_wordc);
    for (uptr i = 0; i < p->we_wordc; ++i) {
      char *w = p->we_wordv[i];
      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
    }
  }
  return res;
}
#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
#else
#define INIT_WORDEXP
#endif

#if SANITIZER_INTERCEPT_SIGWAIT
INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigwait)(set, sig);
  if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
  return res;
}
#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
#else
#define INIT_SIGWAIT
#endif

#if SANITIZER_INTERCEPT_SIGWAITINFO
INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigwaitinfo)(set, info);
  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
  return res;
}
#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
#else
#define INIT_SIGWAITINFO
#endif

#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
            void *timeout) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigtimedwait)(set, info, timeout);
  if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
  return res;
}
#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
#else
#define INIT_SIGTIMEDWAIT
#endif

#if SANITIZER_INTERCEPT_SIGSETOPS
INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigemptyset)(set);
  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
  return res;
}

INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigfillset)(set);
  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
  return res;
}
#define INIT_SIGSETOPS                    \
  COMMON_INTERCEPT_FUNCTION(sigemptyset); \
  COMMON_INTERCEPT_FUNCTION(sigfillset);
#else
#define INIT_SIGSETOPS
#endif

#if SANITIZER_INTERCEPT_SIGPENDING
INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigpending)(set);
  if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
  return res;
}
#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
#else
#define INIT_SIGPENDING
#endif

#if SANITIZER_INTERCEPT_SIGPROCMASK
INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
            __sanitizer_sigset_t *oldset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(sigprocmask)(how, set, oldset);
  if (!res && oldset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
  return res;
}
#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
#else
#define INIT_SIGPROCMASK
#endif

#if SANITIZER_INTERCEPT_BACKTRACE
INTERCEPTOR(int, backtrace, void **buffer, int size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(backtrace)(buffer, size);
  if (res && buffer)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
  return res;
}

INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
  if (buffer && size)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char **res = REAL(backtrace_symbols)(buffer, size);
  if (res && size) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
    for (int i = 0; i < size; ++i)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
  }
  return res;
}
#define INIT_BACKTRACE                  \
  COMMON_INTERCEPT_FUNCTION(backtrace); \
  COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
#else
#define INIT_BACKTRACE
#endif

#if SANITIZER_INTERCEPT__EXIT
INTERCEPTOR(void, _exit, int status) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
  int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
  if (status == 0) status = status1;
  REAL(_exit)(status);
}
#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
#else
#define INIT__EXIT
#endif

#if SANITIZER_INTERCEPT_PHTREAD_MUTEX
INTERCEPTOR(int, pthread_mutex_lock, void *m) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
  int res = REAL(pthread_mutex_lock)(m);
  if (res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
  if (res == 0 || res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
  return res;
}

INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
  return REAL(pthread_mutex_unlock)(m);
}

#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
#define INIT_PTHREAD_MUTEX_UNLOCK \
  COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
#else
#define INIT_PTHREAD_MUTEX_LOCK
#define INIT_PTHREAD_MUTEX_UNLOCK
#endif

#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
  if (mnt->mnt_fsname)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
                                   REAL(strlen)(mnt->mnt_fsname) + 1);
  if (mnt->mnt_dir)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
                                   REAL(strlen)(mnt->mnt_dir) + 1);
  if (mnt->mnt_type)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
                                   REAL(strlen)(mnt->mnt_type) + 1);
  if (mnt->mnt_opts)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
                                   REAL(strlen)(mnt->mnt_opts) + 1);
}
#endif

#if SANITIZER_INTERCEPT_GETMNTENT
INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
  __sanitizer_mntent *res = REAL(getmntent)(fp);
  if (res) write_mntent(ctx, res);
  return res;
}
#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
#else
#define INIT_GETMNTENT
#endif

#if SANITIZER_INTERCEPT_GETMNTENT_R
INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
            __sanitizer_mntent *mntbuf, char *buf, int buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
  __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
  if (res) write_mntent(ctx, res);
  return res;
}
#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
#else
#define INIT_GETMNTENT_R
#endif

#if SANITIZER_INTERCEPT_STATFS
INTERCEPTOR(int, statfs, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(statfs)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
  return res;
}
INTERCEPTOR(int, fstatfs, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(fstatfs)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
  return res;
}
#define INIT_STATFS                  \
  COMMON_INTERCEPT_FUNCTION(statfs); \
  COMMON_INTERCEPT_FUNCTION(fstatfs);
#else
#define INIT_STATFS
#endif

#if SANITIZER_INTERCEPT_STATFS64
INTERCEPTOR(int, statfs64, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(statfs64)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
  return res;
}
INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(fstatfs64)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
  return res;
}
#define INIT_STATFS64                  \
  COMMON_INTERCEPT_FUNCTION(statfs64); \
  COMMON_INTERCEPT_FUNCTION(fstatfs64);
#else
#define INIT_STATFS64
#endif

#if SANITIZER_INTERCEPT_STATVFS
INTERCEPTOR(int, statvfs, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(statvfs)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(fstatvfs)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
  return res;
}
#define INIT_STATVFS                  \
  COMMON_INTERCEPT_FUNCTION(statvfs); \
  COMMON_INTERCEPT_FUNCTION(fstatvfs);
#else
#define INIT_STATVFS
#endif

#if SANITIZER_INTERCEPT_STATVFS64
INTERCEPTOR(int, statvfs64, char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(statvfs64)(path, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(fstatvfs64)(fd, buf);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
  return res;
}
#define INIT_STATVFS64                  \
  COMMON_INTERCEPT_FUNCTION(statvfs64); \
  COMMON_INTERCEPT_FUNCTION(fstatvfs64);
#else
#define INIT_STATVFS64
#endif

#if SANITIZER_INTERCEPT_INITGROUPS
INTERCEPTOR(int, initgroups, char *user, u32 group) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
  int res = REAL(initgroups)(user, group);
  return res;
}
#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
#else
#define INIT_INITGROUPS
#endif

#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
  char *res = REAL(ether_ntoa)(addr);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
  __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
  return res;
}
#define INIT_ETHER_NTOA_ATON             \
  COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
  COMMON_INTERCEPT_FUNCTION(ether_aton);
#else
#define INIT_ETHER_NTOA_ATON
#endif

#if SANITIZER_INTERCEPT_ETHER_HOST
INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(ether_ntohost)(hostname, addr);
  if (!res && hostname)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
  return res;
}
INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
  if (hostname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(ether_hostton)(hostname, addr);
  if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
  return res;
}
INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
            char *hostname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(ether_line)(line, addr, hostname);
  if (!res) {
    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
    if (hostname)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
  }
  return res;
}
#define INIT_ETHER_HOST                     \
  COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
  COMMON_INTERCEPT_FUNCTION(ether_hostton); \
  COMMON_INTERCEPT_FUNCTION(ether_line);
#else
#define INIT_ETHER_HOST
#endif

#if SANITIZER_INTERCEPT_ETHER_R
INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
  if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(ether_ntoa_r)(addr, buf);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
            __sanitizer_ether_addr *addr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
  return res;
}
#define INIT_ETHER_R                       \
  COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
  COMMON_INTERCEPT_FUNCTION(ether_aton_r);
#else
#define INIT_ETHER_R
#endif

#if SANITIZER_INTERCEPT_SHMCTL
INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(shmctl)(shmid, cmd, buf);
  if (res >= 0) {
    unsigned sz = 0;
    if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
      sz = sizeof(__sanitizer_shmid_ds);
    else if (cmd == shmctl_ipc_info)
      sz = struct_shminfo_sz;
    else if (cmd == shmctl_shm_info)
      sz = struct_shm_info_sz;
    if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  }
  return res;
}
#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
#else
#define INIT_SHMCTL
#endif

#if SANITIZER_INTERCEPT_RANDOM_R
INTERCEPTOR(int, random_r, void *buf, u32 *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(random_r)(buf, result);
  if (!res && result)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
#else
#define INIT_RANDOM_R
#endif

// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
// its metadata. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET ||              \
    SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
    SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET ||         \
    SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET ||        \
    SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET ||          \
    SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz)            \
  INTERCEPTOR(int, fn, void *attr, void *r) {                  \
    void *ctx;                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r);                \
    int res = REAL(fn)(attr, r);                               \
    if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
    return res;                                                \
  }
#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
  INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(pthread_attr_getstack)(attr, addr, size);
  if (!res) {
    if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
    if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
  }
  return res;
}

// We may need to call the real pthread_attr_getstack from the run-time
// in sanitizer_common, but we don't want to include the interception headers
// there. So, just define this function here.
namespace __sanitizer {
extern "C" {
int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
  return REAL(pthread_attr_getstack)(attr, addr, size);
}
}  // extern "C"
}  // namespace __sanitizer

#define INIT_PTHREAD_ATTR_GET                             \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize);   \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam);  \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy); \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope);       \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize);   \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
#else
#define INIT_PTHREAD_ATTR_GET
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))

#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
#else
#define INIT_PTHREAD_ATTR_GETINHERITSCHED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
            void *cpuset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
                           cpuset);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
  if (!res && cpusetsize && cpuset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
  return res;
}

#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
#else
#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
#else
#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
#else
#define INIT_PTHREAD_MUTEXATTR_GETTYPE
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
#else
#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
#else
#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
#else
#define INIT_PTHREAD_MUTEXATTR_GETROBUST
#endif

#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
#else
#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
#else
#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
#else
#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
#endif

#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
#define INIT_PTHREAD_CONDATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
#else
#define INIT_PTHREAD_CONDATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
#define INIT_PTHREAD_CONDATTR_GETCLOCK \
  COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
#else
#define INIT_PTHREAD_CONDATTR_GETCLOCK
#endif

#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
  COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
#else
#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
#endif

#if SANITIZER_INTERCEPT_TMPNAM
INTERCEPTOR(char *, tmpnam, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
  char *res = REAL(tmpnam)(s);
  if (res) {
    if (s)
      // FIXME: under ASan the call below may write to freed memory and corrupt
      // its metadata. See
      // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
    else
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
#else
#define INIT_TMPNAM
#endif

#if SANITIZER_INTERCEPT_TMPNAM_R
INTERCEPTOR(char *, tmpnam_r, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(tmpnam_r)(s);
  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
  return res;
}
#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
#else
#define INIT_TMPNAM_R
#endif

#if SANITIZER_INTERCEPT_TEMPNAM
INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
  char *res = REAL(tempnam)(dir, pfx);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  return res;
}
#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
#else
#define INIT_TEMPNAM
#endif

#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
  return REAL(pthread_setname_np)(thread, name);
}
#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
#else
#define INIT_PTHREAD_SETNAME_NP
#endif

#if SANITIZER_INTERCEPT_SINCOS
INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  REAL(sincos)(x, sin, cos);
  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
}
INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  REAL(sincosf)(x, sin, cos);
  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
}
INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  REAL(sincosl)(x, sin, cos);
  if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
  if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
}
#define INIT_SINCOS                   \
  COMMON_INTERCEPT_FUNCTION(sincos);  \
  COMMON_INTERCEPT_FUNCTION(sincosf); \
  COMMON_INTERCEPT_FUNCTION(sincosl);
#else
#define INIT_SINCOS
#endif

#if SANITIZER_INTERCEPT_REMQUO
INTERCEPTOR(double, remquo, double x, double y, int *quo) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  double res = REAL(remquo)(x, y, quo);
  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
  return res;
}
INTERCEPTOR(float, remquof, float x, float y, int *quo) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  float res = REAL(remquof)(x, y, quo);
  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
  return res;
}
INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  long double res = REAL(remquol)(x, y, quo);
  if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
  return res;
}
#define INIT_REMQUO                   \
  COMMON_INTERCEPT_FUNCTION(remquo);  \
  COMMON_INTERCEPT_FUNCTION(remquof); \
  COMMON_INTERCEPT_FUNCTION(remquol);
#else
#define INIT_REMQUO
#endif

#if SANITIZER_INTERCEPT_LGAMMA
extern int signgam;
INTERCEPTOR(double, lgamma, double x) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
  double res = REAL(lgamma)(x);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
  return res;
}
INTERCEPTOR(float, lgammaf, float x) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
  float res = REAL(lgammaf)(x);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
  return res;
}
INTERCEPTOR(long double, lgammal, long double x) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
  long double res = REAL(lgammal)(x);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
  return res;
}
#define INIT_LGAMMA                   \
  COMMON_INTERCEPT_FUNCTION(lgamma);  \
  COMMON_INTERCEPT_FUNCTION(lgammaf); \
  COMMON_INTERCEPT_FUNCTION(lgammal);
#else
#define INIT_LGAMMA
#endif

#if SANITIZER_INTERCEPT_LGAMMA_R
INTERCEPTOR(double, lgamma_r, double x, int *signp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  double res = REAL(lgamma_r)(x, signp);
  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
  return res;
}
INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  float res = REAL(lgammaf_r)(x, signp);
  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
  return res;
}
#define INIT_LGAMMA_R                   \
  COMMON_INTERCEPT_FUNCTION(lgamma_r);  \
  COMMON_INTERCEPT_FUNCTION(lgammaf_r);
#else
#define INIT_LGAMMA_R
#endif

#if SANITIZER_INTERCEPT_LGAMMAL_R
INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  long double res = REAL(lgammal_r)(x, signp);
  if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
  return res;
}
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION(lgammal_r);
#else
#define INIT_LGAMMAL_R
#endif

#if SANITIZER_INTERCEPT_DRAND48_R
INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(drand48_r)(buffer, result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(lrand48_r)(buffer, result);
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
  return res;
}
#define INIT_DRAND48_R                  \
  COMMON_INTERCEPT_FUNCTION(drand48_r); \
  COMMON_INTERCEPT_FUNCTION(lrand48_r);
#else
#define INIT_DRAND48_R
#endif

#if SANITIZER_INTERCEPT_RAND_R
INTERCEPTOR(int, rand_r, unsigned *seedp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
  return REAL(rand_r)(seedp);
}
#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
#else
#define INIT_RAND_R
#endif

#if SANITIZER_INTERCEPT_GETLINE
INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(getline)(lineptr, n, stream);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
  }
  return res;
}
INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
            void *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __getdelim, lineptr, n, delim, stream);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(__getdelim)(lineptr, n, delim, stream);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
  }
  return res;
}
INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
            void *stream) {
  return __getdelim(lineptr, n, delim, stream);
}
#define INIT_GETLINE                     \
  COMMON_INTERCEPT_FUNCTION(getline);    \
  COMMON_INTERCEPT_FUNCTION(__getdelim); \
  COMMON_INTERCEPT_FUNCTION(getdelim);
#else
#define INIT_GETLINE
#endif

#if SANITIZER_INTERCEPT_ICONV
INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
            char **outbuf, SIZE_T *outbytesleft) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
                           outbytesleft);
  if (inbytesleft)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
  if (inbuf && inbytesleft)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
  if (outbytesleft)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
  void *outbuf_orig = outbuf ? *outbuf : 0;
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
  if (res != (SIZE_T) - 1 && outbuf && *outbuf > outbuf_orig) {
    SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
  }
  return res;
}
#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
#else
#define INIT_ICONV
#endif

#if SANITIZER_INTERCEPT_TIMES
INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  __sanitizer_clock_t res = REAL(times)(tms);
  if (res != (__sanitizer_clock_t)-1 && tms)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
  return res;
}
#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
#else
#define INIT_TIMES
#endif

#if SANITIZER_INTERCEPT_TLS_GET_ADDR
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
INTERCEPTOR(void *, __tls_get_addr, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
  void *res = REAL(__tls_get_addr)(arg);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res);
  if (dtv) {
    // New DTLS block has been allocated.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
  }
  return res;
}
#else
#define INIT_TLS_GET_ADDR
#endif

#if SANITIZER_INTERCEPT_LISTXATTR
INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(listxattr)(path, list, size);
  // Here and below, size == 0 is a special case where nothing is written to the
  // buffer, and res contains the desired buffer size.
  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
  return res;
}
INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(llistxattr)(path, list, size);
  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
  return res;
}
INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(flistxattr)(fd, list, size);
  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
  return res;
}
#define INIT_LISTXATTR                   \
  COMMON_INTERCEPT_FUNCTION(listxattr);  \
  COMMON_INTERCEPT_FUNCTION(llistxattr); \
  COMMON_INTERCEPT_FUNCTION(flistxattr);
#else
#define INIT_LISTXATTR
#endif

#if SANITIZER_INTERCEPT_GETXATTR
INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
            SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(getxattr)(path, name, value, size);
  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
  return res;
}
INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
            SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
  return res;
}
INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
            SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
  return res;
}
#define INIT_GETXATTR                   \
  COMMON_INTERCEPT_FUNCTION(getxattr);  \
  COMMON_INTERCEPT_FUNCTION(lgetxattr); \
  COMMON_INTERCEPT_FUNCTION(fgetxattr);
#else
#define INIT_GETXATTR
#endif

#if SANITIZER_INTERCEPT_GETRESID
INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getresuid)(ruid, euid, suid);
  if (res >= 0) {
    if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
    if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
    if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
  }
  return res;
}
INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getresgid)(rgid, egid, sgid);
  if (res >= 0) {
    if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
    if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
    if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
  }
  return res;
}
#define INIT_GETRESID                   \
  COMMON_INTERCEPT_FUNCTION(getresuid); \
  COMMON_INTERCEPT_FUNCTION(getresgid);
#else
#define INIT_GETRESID
#endif

#if SANITIZER_INTERCEPT_GETIFADDRS
// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
// intercept freeifaddrs(). If that ceases to be the case, we might need to
// intercept it to poison the memory again.
INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(getifaddrs)(ifap);
  if (res == 0 && ifap) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
    __sanitizer_ifaddrs *p = *ifap;
    while (p) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
      if (p->ifa_name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
                                       REAL(strlen)(p->ifa_name) + 1);
      if (p->ifa_addr)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
      if (p->ifa_netmask)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
      // On Linux this is a union, but the other member also points to a
      // struct sockaddr, so the following is sufficient.
      if (p->ifa_dstaddr)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
      // FIXME(smatveev): Unpoison p->ifa_data as well.
      p = p->ifa_next;
    }
  }
  return res;
}
#define INIT_GETIFADDRS                  \
  COMMON_INTERCEPT_FUNCTION(getifaddrs);
#else
#define INIT_GETIFADDRS
#endif

#if SANITIZER_INTERCEPT_IF_INDEXTONAME
INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  char *res = REAL(if_indextoname)(ifindex, ifname);
  if (res && ifname)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
  return res;
}
INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
  if (ifname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
  return REAL(if_nametoindex)(ifname);
}
#define INIT_IF_INDEXTONAME                  \
  COMMON_INTERCEPT_FUNCTION(if_indextoname); \
  COMMON_INTERCEPT_FUNCTION(if_nametoindex);
#else
#define INIT_IF_INDEXTONAME
#endif

#if SANITIZER_INTERCEPT_CAPGET
INTERCEPTOR(int, capget, void *hdrp, void *datap) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
  if (hdrp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(capget)(hdrp, datap);
  if (res == 0 && datap)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
  // We can also return -1 and write to hdrp->version if the version passed in
  // hdrp->version is unsupported. But that's not a trivial condition to check,
  // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
  return res;
}
INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
  if (hdrp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
  if (datap)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
  return REAL(capset)(hdrp, datap);
}
#define INIT_CAPGET                  \
  COMMON_INTERCEPT_FUNCTION(capget); \
  COMMON_INTERCEPT_FUNCTION(capset);
#else
#define INIT_CAPGET
#endif

#if SANITIZER_INTERCEPT_AEABI_MEM
DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr);
DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr);
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);

INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
  return WRAP(memmove)(to, from, size);
}
INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
  return WRAP(memmove)(to, from, size);
}
INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
  return WRAP(memmove)(to, from, size);
}
INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
  return WRAP(memcpy)(to, from, size);
}
INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
  return WRAP(memcpy)(to, from, size);
}
INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
  return WRAP(memcpy)(to, from, size);
}
// Note the argument order.
INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
  return WRAP(memset)(block, c, size);
}
INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
  return WRAP(memset)(block, c, size);
}
INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
  return WRAP(memset)(block, c, size);
}
INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
  return WRAP(memset)(block, 0, size);
}
INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
  return WRAP(memset)(block, 0, size);
}
INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
  return WRAP(memset)(block, 0, size);
}
#define INIT_AEABI_MEM                         \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy);   \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memset);   \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memset4);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memset8);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr);   \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4);  \
  COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
#else
#define INIT_AEABI_MEM
#endif  // SANITIZER_INTERCEPT_AEABI_MEM

#if SANITIZER_INTERCEPT___BZERO
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);

INTERCEPTOR(void *, __bzero, void *block, uptr size) {
  return WRAP(memset)(block, 0, size);
}
#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
#else
#define INIT___BZERO
#endif  // SANITIZER_INTERCEPT___BZERO

#if SANITIZER_INTERCEPT_FTIME
INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(ftime)(tp);
  if (tp)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
  return res;
}
#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
#else
#define INIT_FTIME
#endif  // SANITIZER_INTERCEPT_FTIME

#if SANITIZER_INTERCEPT_XDR
INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
            unsigned size, int op) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  REAL(xdrmem_create)(xdrs, addr, size, op);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
  if (op == __sanitizer_XDR_ENCODE) {
    // It's not obvious how much data individual xdr_ routines write.
    // Simply unpoison the entire target buffer in advance.
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
  }
}

INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  REAL(xdrstdio_create)(xdrs, file, op);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
}

// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
#define XDR_INTERCEPTOR(F, T)                             \
  INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) {      \
    void *ctx;                                            \
    COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p);            \
    if (p && xdrs->x_op == __sanitizer_XDR_ENCODE)        \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));  \
    int res = REAL(F)(xdrs, p);                           \
    if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
    return res;                                           \
  }

XDR_INTERCEPTOR(xdr_short, short)
XDR_INTERCEPTOR(xdr_u_short, unsigned short)
XDR_INTERCEPTOR(xdr_int, int)
XDR_INTERCEPTOR(xdr_u_int, unsigned)
XDR_INTERCEPTOR(xdr_long, long)
XDR_INTERCEPTOR(xdr_u_long, unsigned long)
XDR_INTERCEPTOR(xdr_hyper, long long)
XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
XDR_INTERCEPTOR(xdr_longlong_t, long long)
XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
XDR_INTERCEPTOR(xdr_int8_t, u8)
XDR_INTERCEPTOR(xdr_uint8_t, u8)
XDR_INTERCEPTOR(xdr_int16_t, u16)
XDR_INTERCEPTOR(xdr_uint16_t, u16)
XDR_INTERCEPTOR(xdr_int32_t, u32)
XDR_INTERCEPTOR(xdr_uint32_t, u32)
XDR_INTERCEPTOR(xdr_int64_t, u64)
XDR_INTERCEPTOR(xdr_uint64_t, u64)
XDR_INTERCEPTOR(xdr_quad_t, long long)
XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
XDR_INTERCEPTOR(xdr_bool, bool)
XDR_INTERCEPTOR(xdr_enum, int)
XDR_INTERCEPTOR(xdr_char, char)
XDR_INTERCEPTOR(xdr_u_char, unsigned char)
XDR_INTERCEPTOR(xdr_float, float)
XDR_INTERCEPTOR(xdr_double, double)

// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
// wrapstring, sizeof

INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
            unsigned maxsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
  if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
  if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
    if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
  }
  return res;
}

INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
            unsigned maxsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
  if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
  }
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  int res = REAL(xdr_string)(xdrs, p, maxsize);
  if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
    if (res && *p)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
  }
  return res;
}

#define INIT_XDR                               \
  COMMON_INTERCEPT_FUNCTION(xdrmem_create);    \
  COMMON_INTERCEPT_FUNCTION(xdrstdio_create);  \
  COMMON_INTERCEPT_FUNCTION(xdr_short);        \
  COMMON_INTERCEPT_FUNCTION(xdr_u_short);      \
  COMMON_INTERCEPT_FUNCTION(xdr_int);          \
  COMMON_INTERCEPT_FUNCTION(xdr_u_int);        \
  COMMON_INTERCEPT_FUNCTION(xdr_long);         \
  COMMON_INTERCEPT_FUNCTION(xdr_u_long);       \
  COMMON_INTERCEPT_FUNCTION(xdr_hyper);        \
  COMMON_INTERCEPT_FUNCTION(xdr_u_hyper);      \
  COMMON_INTERCEPT_FUNCTION(xdr_longlong_t);   \
  COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
  COMMON_INTERCEPT_FUNCTION(xdr_int8_t);       \
  COMMON_INTERCEPT_FUNCTION(xdr_uint8_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_int16_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_uint16_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_int32_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_uint32_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_int64_t);      \
  COMMON_INTERCEPT_FUNCTION(xdr_uint64_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_quad_t);       \
  COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t);     \
  COMMON_INTERCEPT_FUNCTION(xdr_bool);         \
  COMMON_INTERCEPT_FUNCTION(xdr_enum);         \
  COMMON_INTERCEPT_FUNCTION(xdr_char);         \
  COMMON_INTERCEPT_FUNCTION(xdr_u_char);       \
  COMMON_INTERCEPT_FUNCTION(xdr_float);        \
  COMMON_INTERCEPT_FUNCTION(xdr_double);       \
  COMMON_INTERCEPT_FUNCTION(xdr_bytes);        \
  COMMON_INTERCEPT_FUNCTION(xdr_string);
#else
#define INIT_XDR
#endif  // SANITIZER_INTERCEPT_XDR

#if SANITIZER_INTERCEPT_TSEARCH
INTERCEPTOR(void *, tsearch, void *key, void **rootp,
            int (*compar)(const void *, const void *)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  void *res = REAL(tsearch)(key, rootp, compar);
  if (res && *(void **)res == key)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
  return res;
}
#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
#else
#define INIT_TSEARCH
#endif

#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
    SANITIZER_INTERCEPT_OPEN_MEMSTREAM
void unpoison_file(__sanitizer_FILE *fp) {
#if SANITIZER_HAS_STRUCT_FILE
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
  if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
                                        fp->_IO_read_end - fp->_IO_read_base);
#endif  // SANITIZER_HAS_STRUCT_FILE
}
#endif

#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
// These guys are called when a .c source is built with -O2.
INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
  int res = REAL(__uflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
  int res = REAL(__underflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
  int res = REAL(__overflow)(fp, ch);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
  int res = REAL(__wuflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
  int res = REAL(__wunderflow)(fp);
  unpoison_file(fp);
  return res;
}
INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
  int res = REAL(__woverflow)(fp, ch);
  unpoison_file(fp);
  return res;
}
#define INIT_LIBIO_INTERNALS               \
  COMMON_INTERCEPT_FUNCTION(__uflow);      \
  COMMON_INTERCEPT_FUNCTION(__underflow);  \
  COMMON_INTERCEPT_FUNCTION(__overflow);   \
  COMMON_INTERCEPT_FUNCTION(__wuflow);     \
  COMMON_INTERCEPT_FUNCTION(__wunderflow); \
  COMMON_INTERCEPT_FUNCTION(__woverflow);
#else
#define INIT_LIBIO_INTERNALS
#endif

#if SANITIZER_INTERCEPT_FOPEN
INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
  __sanitizer_FILE *res = REAL(fopen)(path, mode);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
  __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
  if (res) unpoison_file(res);
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
            __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_FOPEN                   \
  COMMON_INTERCEPT_FUNCTION(fopen);  \
  COMMON_INTERCEPT_FUNCTION(fdopen); \
  COMMON_INTERCEPT_FUNCTION(freopen);
#else
#define INIT_FOPEN
#endif

#if SANITIZER_INTERCEPT_FOPEN64
INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
  __sanitizer_FILE *res = REAL(fopen64)(path, mode);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
            __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_FOPEN64                  \
  COMMON_INTERCEPT_FUNCTION(fopen64); \
  COMMON_INTERCEPT_FUNCTION(freopen64);
#else
#define INIT_FOPEN64
#endif

#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
  if (res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
    unpoison_file(res);
    FileMetadata file = {ptr, sizeloc};
    SetInterceptorMetadata(res, file);
  }
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
            SIZE_T *sizeloc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
  __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
  if (res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
    unpoison_file(res);
    FileMetadata file = {(char **)ptr, sizeloc};
    SetInterceptorMetadata(res, file);
  }
  return res;
}
INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
            const char *mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_OPEN_MEMSTREAM                   \
  COMMON_INTERCEPT_FUNCTION(open_memstream);  \
  COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
  COMMON_INTERCEPT_FUNCTION(fmemopen);
#else
#define INIT_OPEN_MEMSTREAM
#endif

#if SANITIZER_INTERCEPT_OBSTACK
static void initialize_obstack(__sanitizer_obstack *obstack) {
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
  if (obstack->chunk)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
                                        sizeof(*obstack->chunk));
}

INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
            int align, void *(*alloc_fn)(uptr arg, uptr sz),
            void (*free_fn)(uptr arg, void *p)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
                           free_fn);
  int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
  if (res) initialize_obstack(obstack);
  return res;
}
INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
            int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
                           free_fn);
  int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
  if (res) initialize_obstack(obstack);
  return res;
}
INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
  REAL(_obstack_newchunk)(obstack, length);
  if (obstack->chunk)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(
        obstack->chunk, obstack->next_free - (char *)obstack->chunk);
}
#define INIT_OBSTACK                           \
  COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
  COMMON_INTERCEPT_FUNCTION(_obstack_begin);   \
  COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
#else
#define INIT_OBSTACK
#endif

#if SANITIZER_INTERCEPT_FFLUSH
INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
  int res = REAL(fflush)(fp);
  // FIXME: handle fp == NULL
  if (fp) {
    const FileMetadata *m = GetInterceptorMetadata(fp);
    if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
  }
  return res;
}
#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
#else
#define INIT_FFLUSH
#endif

#if SANITIZER_INTERCEPT_FCLOSE
INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
  if (fp) {
    COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
    const FileMetadata *m = GetInterceptorMetadata(fp);
    if (m) {
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
      DeleteInterceptorMetadata(fp);
    }
  }
  return REAL(fclose)(fp);
}
#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
#else
#define INIT_FCLOSE
#endif

#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
  void *res = REAL(dlopen)(filename, flag);
  COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
  return res;
}

INTERCEPTOR(int, dlclose, void *handle) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
  int res = REAL(dlclose)(handle);
  COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
  return res;
}
#define INIT_DLOPEN_DLCLOSE          \
  COMMON_INTERCEPT_FUNCTION(dlopen); \
  COMMON_INTERCEPT_FUNCTION(dlclose);
#else
#define INIT_DLOPEN_DLCLOSE
#endif

#if SANITIZER_INTERCEPT_GETPASS
INTERCEPTOR(char *, getpass, const char *prompt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
  if (prompt)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
  char *res = REAL(getpass)(prompt);
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
  return res;
}

#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
#else
#define INIT_GETPASS
#endif

#if SANITIZER_INTERCEPT_TIMERFD
INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
            void *old_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
                           old_value);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
  int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
  if (res != -1 && old_value)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
  return res;
}

INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
  int res = REAL(timerfd_gettime)(fd, curr_value);
  if (res != -1 && curr_value)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
  return res;
}
#define INIT_TIMERFD                          \
  COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
  COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
#else
#define INIT_TIMERFD
#endif

#if SANITIZER_INTERCEPT_MLOCKX
// Linux kernel has a bug that leads to kernel deadlock if a process
// maps TBs of memory and then calls mlock().
static void MlockIsUnsupported() {
  static atomic_uint8_t printed;
  if (atomic_exchange(&printed, 1, memory_order_relaxed))
    return;
  VPrintf(1, "INFO: %s ignores mlock/mlockall/munlock/munlockall\n",
          SanitizerToolName);
}

INTERCEPTOR(int, mlock, const void *addr, uptr len) {
  MlockIsUnsupported();
  return 0;
}

INTERCEPTOR(int, munlock, const void *addr, uptr len) {
  MlockIsUnsupported();
  return 0;
}

INTERCEPTOR(int, mlockall, int flags) {
  MlockIsUnsupported();
  return 0;
}

INTERCEPTOR(int, munlockall, void) {
  MlockIsUnsupported();
  return 0;
}

#define INIT_MLOCKX                                                            \
  COMMON_INTERCEPT_FUNCTION(mlock);                                            \
  COMMON_INTERCEPT_FUNCTION(munlock);                                          \
  COMMON_INTERCEPT_FUNCTION(mlockall);                                         \
  COMMON_INTERCEPT_FUNCTION(munlockall);

#else
#define INIT_MLOCKX
#endif  // SANITIZER_INTERCEPT_MLOCKX

static void InitializeCommonInterceptors() {
  static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
  interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();

  INIT_TEXTDOMAIN;
  INIT_STRCMP;
  INIT_STRNCMP;
  INIT_STRCASECMP;
  INIT_STRNCASECMP;
  INIT_MEMCHR;
  INIT_MEMRCHR;
  INIT_READ;
  INIT_PREAD;
  INIT_PREAD64;
  INIT_READV;
  INIT_PREADV;
  INIT_PREADV64;
  INIT_WRITE;
  INIT_PWRITE;
  INIT_PWRITE64;
  INIT_WRITEV;
  INIT_PWRITEV;
  INIT_PWRITEV64;
  INIT_PRCTL;
  INIT_LOCALTIME_AND_FRIENDS;
  INIT_STRPTIME;
  INIT_SCANF;
  INIT_ISOC99_SCANF;
  INIT_PRINTF;
  INIT_ISOC99_PRINTF;
  INIT_FREXP;
  INIT_FREXPF_FREXPL;
  INIT_GETPWNAM_AND_FRIENDS;
  INIT_GETPWNAM_R_AND_FRIENDS;
  INIT_GETPWENT;
  INIT_FGETPWENT;
  INIT_GETPWENT_R;
  INIT_SETPWENT;
  INIT_CLOCK_GETTIME;
  INIT_GETITIMER;
  INIT_TIME;
  INIT_GLOB;
  INIT_WAIT;
  INIT_WAIT4;
  INIT_INET;
  INIT_PTHREAD_GETSCHEDPARAM;
  INIT_GETADDRINFO;
  INIT_GETNAMEINFO;
  INIT_GETSOCKNAME;
  INIT_GETHOSTBYNAME;
  INIT_GETHOSTBYNAME_R;
  INIT_GETHOSTBYNAME2_R;
  INIT_GETHOSTBYADDR_R;
  INIT_GETHOSTENT_R;
  INIT_GETSOCKOPT;
  INIT_ACCEPT;
  INIT_ACCEPT4;
  INIT_MODF;
  INIT_RECVMSG;
  INIT_GETPEERNAME;
  INIT_IOCTL;
  INIT_INET_ATON;
  INIT_SYSINFO;
  INIT_READDIR;
  INIT_READDIR64;
  INIT_PTRACE;
  INIT_SETLOCALE;
  INIT_GETCWD;
  INIT_GET_CURRENT_DIR_NAME;
  INIT_STRTOIMAX;
  INIT_MBSTOWCS;
  INIT_MBSNRTOWCS;
  INIT_WCSTOMBS;
  INIT_WCSNRTOMBS;
  INIT_TCGETATTR;
  INIT_REALPATH;
  INIT_CANONICALIZE_FILE_NAME;
  INIT_CONFSTR;
  INIT_SCHED_GETAFFINITY;
  INIT_STRERROR;
  INIT_STRERROR_R;
  INIT_XPG_STRERROR_R;
  INIT_SCANDIR;
  INIT_SCANDIR64;
  INIT_GETGROUPS;
  INIT_POLL;
  INIT_PPOLL;
  INIT_WORDEXP;
  INIT_SIGWAIT;
  INIT_SIGWAITINFO;
  INIT_SIGTIMEDWAIT;
  INIT_SIGSETOPS;
  INIT_SIGPENDING;
  INIT_SIGPROCMASK;
  INIT_BACKTRACE;
  INIT__EXIT;
  INIT_PTHREAD_MUTEX_LOCK;
  INIT_PTHREAD_MUTEX_UNLOCK;
  INIT_GETMNTENT;
  INIT_GETMNTENT_R;
  INIT_STATFS;
  INIT_STATFS64;
  INIT_STATVFS;
  INIT_STATVFS64;
  INIT_INITGROUPS;
  INIT_ETHER_NTOA_ATON;
  INIT_ETHER_HOST;
  INIT_ETHER_R;
  INIT_SHMCTL;
  INIT_RANDOM_R;
  INIT_PTHREAD_ATTR_GET;
  INIT_PTHREAD_ATTR_GETINHERITSCHED;
  INIT_PTHREAD_ATTR_GETAFFINITY_NP;
  INIT_PTHREAD_MUTEXATTR_GETPSHARED;
  INIT_PTHREAD_MUTEXATTR_GETTYPE;
  INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
  INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
  INIT_PTHREAD_MUTEXATTR_GETROBUST;
  INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
  INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
  INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
  INIT_PTHREAD_CONDATTR_GETPSHARED;
  INIT_PTHREAD_CONDATTR_GETCLOCK;
  INIT_PTHREAD_BARRIERATTR_GETPSHARED;
  INIT_TMPNAM;
  INIT_TMPNAM_R;
  INIT_TEMPNAM;
  INIT_PTHREAD_SETNAME_NP;
  INIT_SINCOS;
  INIT_REMQUO;
  INIT_LGAMMA;
  INIT_LGAMMA_R;
  INIT_LGAMMAL_R;
  INIT_DRAND48_R;
  INIT_RAND_R;
  INIT_GETLINE;
  INIT_ICONV;
  INIT_TIMES;
  INIT_TLS_GET_ADDR;
  INIT_LISTXATTR;
  INIT_GETXATTR;
  INIT_GETRESID;
  INIT_GETIFADDRS;
  INIT_IF_INDEXTONAME;
  INIT_CAPGET;
  INIT_AEABI_MEM;
  INIT___BZERO;
  INIT_FTIME;
  INIT_XDR;
  INIT_TSEARCH;
  INIT_LIBIO_INTERNALS;
  INIT_FOPEN;
  INIT_FOPEN64;
  INIT_OPEN_MEMSTREAM;
  INIT_OBSTACK;
  INIT_FFLUSH;
  INIT_FCLOSE;
  INIT_DLOPEN_DLCLOSE;
  INIT_GETPASS;
  INIT_TIMERFD;
  INIT_MLOCKX;
}
@


1.1.1.3
log
@initial import of GCC 5.5.0.  this fixes a very large number of PRs.
280 are listed here:
    https://gcc.gnu.org/bugzilla/buglist.cgi?bug_status=RESOLVED&resolution=FIXED&target_milestone=5.5
and this list is likely not complete, and not reproduced here.  the
only specific change in functionality is removal of x86 "pcommit"
instruction (which was apparently never implemented.)
@
text
@d2736 1
a2736 2
  if (res >= 0 && lst && size > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
@


1.1.1.4
log
@import GCC 6.4.0.  see this url for details which are too large to
include here:

   http://gcc.gnu.org/gcc-6/changes.html

the main visible changes appear to be:

- The default mode for C++ is now -std=gnu++14 instead of -std=gnu++98.
- The C and C++ compilers now support attributes on enumerators.
- Diagnostics can now contain "fix-it hints"
- more warnings (some added to -Wall)
@
text
@a17 1
//   COMMON_INTERCEPTOR_DIR_ACQUIRE
a21 1
//   COMMON_INTERCEPTOR_ON_DLOPEN
a29 1

a37 16
#if SANITIZER_INTERCEPTOR_HOOKS
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)                                     \
  do {                                                                         \
    if (f)                                                                     \
      f(__VA_ARGS__);                                                          \
  } while (false);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)                                  \
  extern "C" {                                                                 \
  SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);  \
  } // extern "C"
#else
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)

#endif  // SANITIZER_INTERCEPTOR_HOOKS

a43 3
#define inet_aton __inet_aton
#define inet_pton __inet_pton
#define iconv __bsd_iconv
d83 1
a83 1
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
a98 23
#define COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n)       \
    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
      common_flags()->strict_string_checks ? (len) + 1 : (n) )

#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n)                   \
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))

#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) {}
#endif

#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
#endif

#ifndef COMMON_INTERCEPTOR_ACQUIRE
#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
#endif

#ifndef COMMON_INTERCEPTOR_RELEASE
#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
#endif

d152 1
a152 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
  char *domain = REAL(textdomain)(domainname);
a167 3
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
                              const char *s1, const char *s2)

a170 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
                             s2);
d178 2
a179 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
a182 3
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
                              const char *s1, const char *s2, uptr n)

a187 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
                             s2, size);
d224 2
a225 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
a250 133
#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
static inline void StrstrCheck(void *ctx, char *r, const char *s1,
                               const char *s2) {
    uptr len1 = REAL(strlen)(s1);
    uptr len2 = REAL(strlen)(s2);
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s1, len1,
                                          r ? r - s1 + len2 : len1 + 1);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
}
#endif

#if SANITIZER_INTERCEPT_STRSTR
INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strstr(s1, s2);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
  char *r = REAL(strstr)(s1, s2);
  if (common_flags()->intercept_strstr)
    StrstrCheck(ctx, r, s1, s2);
  return r;
}

#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
#else
#define INIT_STRSTR
#endif

#if SANITIZER_INTERCEPT_STRCASESTR
INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
  char *r = REAL(strcasestr)(s1, s2);
  if (common_flags()->intercept_strstr)
    StrstrCheck(ctx, r, s1, s2);
  return r;
}

#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
#else
#define INIT_STRCASESTR
#endif

#if SANITIZER_INTERCEPT_STRSPN
INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
  SIZE_T r = REAL(strspn)(s1, s2);
  if (common_flags()->intercept_strspn) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
  }
  return r;
}

INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
  SIZE_T r = REAL(strcspn)(s1, s2);
  if (common_flags()->intercept_strspn) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
  }
  return r;
}

#define INIT_STRSPN \
  COMMON_INTERCEPT_FUNCTION(strspn); \
  COMMON_INTERCEPT_FUNCTION(strcspn);
#else
#define INIT_STRSPN
#endif

#if SANITIZER_INTERCEPT_STRPBRK
INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
  char *r = REAL(strpbrk)(s1, s2);
  if (common_flags()->intercept_strpbrk) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
        r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
  }
  return r;
}

#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
#else
#define INIT_STRPBRK
#endif

#if SANITIZER_INTERCEPT_MEMCMP

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
                              const void *s1, const void *s2, uptr n)

INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
                             a2, size);
  if (common_flags()->intercept_memcmp) {
    if (common_flags()->strict_memcmp) {
      // Check the entire regions even if the first bytes of the buffers are
      // different.
      COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
      COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
      // Fallthrough to REAL(memcmp) below.
    } else {
      unsigned char c1 = 0, c2 = 0;
      const unsigned char *s1 = (const unsigned char*)a1;
      const unsigned char *s2 = (const unsigned char*)a2;
      uptr i;
      for (i = 0; i < size; i++) {
        c1 = s1[i];
        c2 = s2[i];
        if (c1 != c2) break;
      }
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
      return CharCmpX(c1, c2);
    }
  }
  return REAL(memcmp(a1, a2, size));
}

#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
#else
#define INIT_MEMCMP
#endif

a252 2
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memchr(s, c, n);
d256 1
a256 1
  uptr len = res ? (char *)res - (const char *)s + 1 : n;
d720 2
a721 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
  if (res && tm) {
d725 1
a725 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
a915 10
#if SANITIZER_INTERCEPT_PRINTF_L
INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
            const char *format, va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)

INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
#endif  // SANITIZER_INTERCEPT_PRINTF_L

a991 8
#if SANITIZER_INTERCEPT_PRINTF_L
#define INIT_PRINTF_L                     \
  COMMON_INTERCEPT_FUNCTION(snprintf_l);  \
  COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
#else
#define INIT_PRINTF_L
#endif

d1008 1
a1008 7
INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
  // We need a frame pointer, because we call into ioctl_common_[pre|post] which
  // can trigger a report and we need to be able to unwind through this
  // function.  On Mac in debug mode we might not have a frame pointer, because
  // ioctl_common_[pre|post] doesn't get inlined here.
  ENABLE_FRAME_POINTER;

a1009 4
  va_list ap;
  va_start(ap, request);
  void *arg = va_arg(ap, void *);
  va_end(ap);
a1017 4
  // Although request is unsigned long, the rest of the interceptor uses it
  // as just "unsigned" to save space, because we know that all values fit in
  // "unsigned" - they are compile-time constants.

d1100 1
a1100 1
  if (res) unpoison_passwd(ctx, res);
d1107 1
a1107 1
  if (res) unpoison_passwd(ctx, res);
d1115 1
a1115 1
  if (res) unpoison_group(ctx, res);
d1122 1
a1122 1
  if (res) unpoison_group(ctx, res);
d1211 1
a1211 1
  if (res) unpoison_passwd(ctx, res);
d1218 1
a1218 1
  if (res) unpoison_group(ctx, res);;
d1233 1
a1233 1
  if (res) unpoison_passwd(ctx, res);
d1240 1
a1240 1
  if (res) unpoison_group(ctx, res);
d1443 1
a1443 1
  pglob_copy->gl_closedir(dir);
d1448 1
a1448 1
  return pglob_copy->gl_readdir(dir);
d1454 1
a1454 1
  return pglob_copy->gl_opendir(s);
d1460 1
a1460 1
  return pglob_copy->gl_lstat(s, st);
d1466 1
a1466 1
  return pglob_copy->gl_stat(s, st);
a1473 1
  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
a1503 1
  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
a1649 1
  COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
a2139 10
INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  __sanitizer_dirent *res = REAL(opendir)(path);
  if (res)
    COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
  return res;
}

a2167 1
  COMMON_INTERCEPT_FUNCTION(opendir); \
a2211 1
  __sanitizer_iovec local_iovec;
a2219 2
    else if (request == ptrace_setvfpregs)
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
d2222 3
a2224 9
    // Some kernel might zero the iovec::iov_base in case of invalid
    // write access.  In this case copy the invalid address for further
    // inspection.
    else if (request == ptrace_setregset || request == ptrace_getregset) {
      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
      local_iovec = *iovec;
      if (request == ptrace_setregset)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
a2241 2
    else if (request == ptrace_getvfpregs)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
d2247 2
a2248 4
      __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
                                     local_iovec.iov_len);
a2308 31
UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
  CHECK(endptr);
  if (nptr == *endptr) {
    // No digits were found at strtol call, we need to find out the last
    // symbol accessed by strtoll on our own.
    // We get this symbol by skipping leading blanks and optional +/- sign.
    while (IsSpace(*nptr)) nptr++;
    if (*nptr == '+' || *nptr == '-') nptr++;
    *endptr = const_cast<char *>(nptr);
  }
  CHECK(*endptr >= nptr);
}

UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
                             char **endptr, char *real_endptr, int base) {
  if (endptr) {
    *endptr = real_endptr;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
  }
  // If base has unsupported value, strtol can exit with EINVAL
  // without reading any characters. So do additional checks only
  // if base is valid.
  bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
  if (is_valid_base) {
    FixRealStrtolEndptr(nptr, &real_endptr);
  }
  COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
                                 (real_endptr - nptr) + 1 : 0);
}


d2316 2
a2317 3
  char *real_endptr;
  INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
d2327 2
a2328 3
  char *real_endptr;
  INTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
d2459 1
a2459 1
  if (res != ((SIZE_T)-1) && dest && src) {
a2470 22

#if SANITIZER_INTERCEPT_WCRTOMB
INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
  if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://code.google.com/p/address-sanitizer/issues/detail?id=321.
  SIZE_T res = REAL(wcrtomb)(dest, src, ps);
  if (res != ((SIZE_T)-1) && dest) {
    SIZE_T write_cnt = res;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
  }
  return res;
}

#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
#else
#define INIT_WCRTOMB
#endif

d2499 1
a2499 1
  char *allocated_path = nullptr;
a2560 13
#if SANITIZER_INTERCEPT_SCHED_GETPARAM
INTERCEPTOR(int, sched_getparam, int pid, void *param) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
  int res = REAL(sched_getparam)(pid, param);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
  return res;
}
#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
#else
#define INIT_SCHED_GETPARAM
#endif

d2634 1
a2634 1
  return scandir_filter(dir);
d2644 1
a2644 1
  return scandir_compar(a, b);
d2657 4
a2660 5
  int res = REAL(scandir)(dirp, namelist,
                          filter ? wrapped_scandir_filter : nullptr,
                          compar ? wrapped_scandir_compar : nullptr);
  scandir_filter = nullptr;
  scandir_compar = nullptr;
d2686 1
a2686 1
  return scandir64_filter(dir);
d2696 1
a2696 1
  return scandir64_compar(a, b);
d2710 4
a2713 5
      REAL(scandir64)(dirp, namelist,
                      filter ? wrapped_scandir64_filter : nullptr,
                      compar ? wrapped_scandir64_compar : nullptr);
  scandir64_filter = nullptr;
  scandir64_compar = nullptr;
a3579 1
  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
d3796 12
a3807 15

// FIXME: under ASan the call below may write to freed memory and corrupt its
// metadata. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=321.
#define GETDELIM_INTERCEPTOR_IMPL(vname)                                       \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream);           \
    SSIZE_T res = REAL(vname)(lineptr, n, delim, stream);                      \
    if (res > 0) {                                                             \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));          \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));                      \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);                  \
    }                                                                          \
    return res;                                                                \
d3809 2
a3810 7

INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
            void *stream)
GETDELIM_INTERCEPTOR_IMPL(__getdelim)

// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
// with its own body.
d3812 3
a3814 3
            void *stream)
GETDELIM_INTERCEPTOR_IMPL(getdelim)

d3835 1
a3835 1
  void *outbuf_orig = outbuf ? *outbuf : nullptr;
a3869 6
// If you see any crashes around this functions, there are 2 known issues with
// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
// 2. It can be called recursively if sanitizer code uses __tls_get_addr
// to access thread local variables (it should not happen normally,
// because sanitizers use initial-exec tls model).
d3874 1
a3874 3
  uptr tls_begin, tls_end;
  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
d4110 3
a4112 3
DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr)
d4452 1
a4452 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4483 1
a4483 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4612 7
a4618 6
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  const FileMetadata *m = GetInterceptorMetadata(fp);
  int res = REAL(fclose)(fp);
  if (m) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
    DeleteInterceptorMetadata(fp);
d4620 1
a4620 1
  return res;
a4630 2
  if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
  COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
d4701 1
a4701 1
  VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
a4734 213
#if SANITIZER_INTERCEPT_FOPENCOOKIE
struct WrappedCookie {
  void *real_cookie;
  __sanitizer_cookie_io_functions_t real_io_funcs;
};

static uptr wrapped_read(void *cookie, char *buf, uptr size) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
  return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
}

static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
  return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
}

static int wrapped_seek(void *cookie, u64 *offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
  return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
                   : -1;
}

static int wrapped_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
  __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
  int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
            __sanitizer_cookie_io_functions_t io_funcs) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
  WrappedCookie *wrapped_cookie =
      (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_io_funcs = io_funcs;
  __sanitizer_FILE *res =
      REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
                                               wrapped_seek, wrapped_close});
  return res;
}

#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
#else
#define INIT_FOPENCOOKIE
#endif  // SANITIZER_INTERCEPT_FOPENCOOKIE

#if SANITIZER_INTERCEPT_SEM
INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
  // Workaround a bug in glibc's "old" semaphore implementation by
  // zero-initializing the sem_t contents. This has to be done here because
  // interceptors bind to the lowest symbols version by default, hitting the
  // buggy code path while the non-sanitized build of the same code works fine.
  REAL(memset)(s, 0, sizeof(*s));
  int res = REAL(sem_init)(s, pshared, value);
  return res;
}

INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
  int res = REAL(sem_destroy)(s);
  return res;
}

INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
  }
  return res;
}

INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
  }
  return res;
}

INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
  }
  return res;
}

INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
  COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
  int res = REAL(sem_post)(s);
  return res;
}

INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
  int res = REAL(sem_getvalue)(s, sval);
  if (res == 0) {
    COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
  }
  return res;
}
#define INIT_SEM                                                               \
  COMMON_INTERCEPT_FUNCTION(sem_init);                                         \
  COMMON_INTERCEPT_FUNCTION(sem_destroy);                                      \
  COMMON_INTERCEPT_FUNCTION(sem_wait);                                         \
  COMMON_INTERCEPT_FUNCTION(sem_trywait);                                      \
  COMMON_INTERCEPT_FUNCTION(sem_timedwait);                                    \
  COMMON_INTERCEPT_FUNCTION(sem_post);                                         \
  COMMON_INTERCEPT_FUNCTION(sem_getvalue);
#else
#define INIT_SEM
#endif // SANITIZER_INTERCEPT_SEM

#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
  int res = REAL(pthread_setcancelstate)(state, oldstate);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
  return res;
}

INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
  int res = REAL(pthread_setcanceltype)(type, oldtype);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
  return res;
}
#define INIT_PTHREAD_SETCANCEL                                                 \
  COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate);                           \
  COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
#else
#define INIT_PTHREAD_SETCANCEL
#endif

#if SANITIZER_INTERCEPT_MINCORE
INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
  int res = REAL(mincore)(addr, length, vec);
  if (res == 0) {
    uptr page_size = GetPageSizeCached();
    uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
  }
  return res;
}
#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
#else
#define INIT_MINCORE
#endif

#if SANITIZER_INTERCEPT_PROCESS_VM_READV
INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
            uptr flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
                           remote_iov, riovcnt, flags);
  SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
                                       riovcnt, flags);
  if (res > 0)
    write_iovec(ctx, local_iov, liovcnt, res);
  return res;
}

INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
            uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
            uptr flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
                           remote_iov, riovcnt, flags);
  SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
                                        riovcnt, flags);
  if (res > 0)
    read_iovec(ctx, local_iov, liovcnt, res);
  return res;
}
#define INIT_PROCESS_VM_READV                                                  \
  COMMON_INTERCEPT_FUNCTION(process_vm_readv);                                 \
  COMMON_INTERCEPT_FUNCTION(process_vm_writev);
#else
#define INIT_PROCESS_VM_READV
#endif

a4743 4
  INIT_STRSTR;
  INIT_STRCASESTR;
  INIT_STRSPN;
  INIT_STRPBRK;
a4744 1
  INIT_MEMCMP;
a4763 1
  INIT_PRINTF_L;
a4808 1
  INIT_WCRTOMB;
a4813 1
  INIT_SCHED_GETPARAM;
a4895 5
  INIT_FOPENCOOKIE;
  INIT_SEM;
  INIT_PTHREAD_SETCANCEL;
  INIT_MINCORE;
  INIT_PROCESS_VM_READV;
@


1.1.1.5
log
@import GCC 7.4.0.  main changes include:

The non-standard C++0x type traits has_trivial_default_constructor,
has_trivial_copy_constructor and has_trivial_copy_assign have been
removed.

On ARM targets (arm*-*-*), a bug introduced in GCC 5 that affects
conformance to the procedure call standard (AAPCS) has been fixed.

Many optimiser improvements

DWARF-5 support.

Many new and enhanced warnings.

Warnings about format strings now underline the pertinent part of
the string, and can offer suggested fixes.

Several new warnings related to buffer overflows and buffer
truncation.

New __builtin_add_overflow_p, __builtin_sub_overflow_p,
__builtin_mul_overflow_p built-ins added that test for overflow.

The C++ front end has experimental support for all of the current
C++17 draft.

The -fverbose-asm option has been expanded to prints comments
showing the source lines that correspond to the assembly.

The gcc and g++ driver programs will now provide suggestions for
misspelled arguments to command-line options.


AArch64 specific:

GCC has been updated to the latest revision of the procedure call
standard (AAPCS64) to provide support for parameter passing when
data types have been over-aligned.

The ARMv8.2-A and ARMv8.3-A architecture are now supported.

ARM specific:

Support for the ARMv5 and ARMv5E architectures has been
deprecated (which have no known implementations).

A new command-line option -mpure-code has been added. It does not
allow constant data to be placed in code sections.

x86 specific:

Support for the AVX-512 4FMAPS, 4VNNIW, VPOPCNTDQ and Software
Guard Extensions (SGX) ISA extensions has been added.

PPC specific:

GCC now diagnoses inline assembly that clobbers register r2.

RISC-V specific:

Support for the RISC-V instruction set has been added.

SH specific:

Support for SH5/SH64 has been removed.

Support for SH2A has been enhanced.
@
text
@d12 1
a12 1
// which has to define its own macros:
a91 4
#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
#endif

a143 16
#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
#endif

#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
#endif

#ifdef SANITIZER_NLDBL_VERSION
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
#else
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn)                          \
    COMMON_INTERCEPT_FUNCTION(fn)
#endif

a192 34
#if SANITIZER_INTERCEPT_STRLEN
INTERCEPTOR(SIZE_T, strlen, const char *s) {
  // Sometimes strlen is called prior to InitializeCommonInterceptors,
  // in which case the REAL(strlen) typically used in
  // COMMON_INTERCEPTOR_ENTER will fail.  We use internal_strlen here
  // to handle that.
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strlen(s);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
  SIZE_T result = REAL(strlen)(s);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
  return result;
}
#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
#else
#define INIT_STRLEN
#endif

#if SANITIZER_INTERCEPT_STRNLEN
INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
  SIZE_T length = REAL(strnlen)(s, maxlen);
  if (common_flags()->intercept_strlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
  return length;
}
#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
#else
#define INIT_STRNLEN
#endif

d215 1
a215 1
                              const char *s1, const char *s2, int result)
d220 2
d231 1
a231 4
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
                             s2, result);
  return result;
d235 1
a235 2
                              const char *s1, const char *s2, uptr n,
                              int result)
d242 2
d251 3
a253 6
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, Min(i + 1, size));
  int result = CharCmpX(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
                             s2, size, result);
  return result;
a269 3
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
                              const char *s1, const char *s2, int result)

d282 1
a282 4
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
                             s1, s2, result);
  return result;
a284 4
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
                              const char *s1, const char *s2, uptr n,
                              int result)

d297 1
a297 4
  int result = CharCaseCmp(c1, c2);
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
                             s1, s2, n, result);
  return result;
a318 4

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

a326 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
                             s2, r);
a335 4

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
                              const char *s1, const char *s2, char *result)

a341 2
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
                             s1, s2, r);
a349 73
#if SANITIZER_INTERCEPT_MEMMEM
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
                              const void *s1, SIZE_T len1, const void *s2,
                              SIZE_T len2, void *result)

INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
            SIZE_T len2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
  void *r = REAL(memmem)(s1, len1, s2, len2);
  if (common_flags()->intercept_memmem) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
  }
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
                             s1, len1, s2, len2, r);
  return r;
}

#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
#else
#define INIT_MEMMEM
#endif  // SANITIZER_INTERCEPT_MEMMEM

#if SANITIZER_INTERCEPT_STRCHR
INTERCEPTOR(char*, strchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
  char *result = REAL(strchr)(s, c);
  uptr len = internal_strlen(s);
  uptr n = result ? result - s + 1 : len + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n);
  return result;
}
#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
#else
#define INIT_STRCHR
#endif

#if SANITIZER_INTERCEPT_STRCHRNUL
INTERCEPTOR(char*, strchrnul, const char *s, int c) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
  char *result = REAL(strchrnul)(s, c);
  uptr len = result - s + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
  return result;
}
#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
#else
#define INIT_STRCHRNUL
#endif

#if SANITIZER_INTERCEPT_STRRCHR
INTERCEPTOR(char*, strrchr, const char *s, int c) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_strrchr(s, c);
  COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
  uptr len = internal_strlen(s);
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, len + 1);
  return REAL(strrchr)(s, c);
}
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
#else
#define INIT_STRRCHR
#endif

a397 58
#if SANITIZER_INTERCEPT_MEMSET
INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memset(dst, v, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);
  if (common_flags()->intercept_intrin)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
  return REAL(memset)(dst, v, size);
}

#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
#else
#define INIT_MEMSET
#endif

#if SANITIZER_INTERCEPT_MEMMOVE
INTERCEPTOR(void*, memmove, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memmove(dst, src, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  return REAL(memmove)(dst, src, size);
}

#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
#else
#define INIT_MEMMOVE
#endif

#if SANITIZER_INTERCEPT_MEMCPY
INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {
    // On OS X, calling internal_memcpy here will cause memory corruptions,
    // because memcpy and memmove are actually aliases of the same
    // implementation.  We need to use internal_memmove here.
    return internal_memmove(dst, src, size);
  }
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
  // due to memcpy being an alias of memmove on OS X.
  return REAL(memcpy)(dst, src, size);
}

#define INIT_MEMCPY COMMON_INTERCEPT_FUNCTION(memcpy)
#else
#define INIT_MEMCPY
#endif

d401 1
a401 2
                              const void *s1, const void *s2, uptr n,
                              int result)
d404 2
d408 2
a409 2
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
d429 1
a429 4
      int r = CharCmpX(c1, c2);
      CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
                                 a1, a2, size, r);
      return r;
d432 1
a432 4
  int result = REAL(memcmp(a1, a2, size));
  CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
                             a2, size, result);
  return result;
a445 8
#if SANITIZER_WINDOWS
  void *res;
  if (REAL(memchr)) {
    res = REAL(memchr)(s, c, n);
  } else {
    res = internal_memchr(s, c, n);
  }
#else
a446 1
#endif
d491 1
a491 1
  // https://github.com/google/sanitizers/issues/321.
d502 1
a502 1
  // https://github.com/google/sanitizers/issues/321.
d510 1
a510 1
  COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
d543 1
a543 1
  // https://github.com/google/sanitizers/issues/321.
d561 1
a561 1
  // https://github.com/google/sanitizers/issues/321.
d579 1
a579 1
  // https://github.com/google/sanitizers/issues/321.
d826 1
a826 1
  // https://github.com/google/sanitizers/issues/321.
d839 1
a839 1
  // https://github.com/google/sanitizers/issues/321.
d852 1
a852 1
  // https://github.com/google/sanitizers/issues/321.
d865 1
a865 1
  // https://github.com/google/sanitizers/issues/321.
d909 1
a909 1
  // https://github.com/google/sanitizers/issues/321.
d1046 1
a1046 1
// https://github.com/google/sanitizers/issues/321.
d1063 1
a1063 1
// https://github.com/google/sanitizers/issues/321.
d1080 1
a1080 1
// https://github.com/google/sanitizers/issues/321.
d1365 1
a1365 1
  // https://github.com/google/sanitizers/issues/321.
d1380 1
a1380 1
  // https://github.com/google/sanitizers/issues/321.
d1396 1
a1396 1
  // https://github.com/google/sanitizers/issues/321.
d1411 1
a1411 1
  // https://github.com/google/sanitizers/issues/321.
d1480 1
a1480 1
  // https://github.com/google/sanitizers/issues/321.
d1495 1
a1495 1
  // https://github.com/google/sanitizers/issues/321.
d1510 1
a1510 1
  // https://github.com/google/sanitizers/issues/321.
d1525 1
a1525 1
  // https://github.com/google/sanitizers/issues/321.
d1582 1
a1582 1
  // https://github.com/google/sanitizers/issues/321.
d1594 1
a1594 1
  // https://github.com/google/sanitizers/issues/321.
d1621 1
a1621 1
  // https://github.com/google/sanitizers/issues/321.
d1635 1
a1635 1
  // https://github.com/google/sanitizers/issues/321.
a1691 5
static const __sanitizer_glob_t kGlobCopy = {
      0,                  0,                   0,
      0,                  wrapped_gl_closedir, wrapped_gl_readdir,
      wrapped_gl_opendir, wrapped_gl_lstat,    wrapped_gl_stat};

d1698 4
a1701 2
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
d1729 4
a1732 2
  __sanitizer_glob_t glob_copy;
  internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
d1769 1
a1769 1
  // https://github.com/google/sanitizers/issues/321.
d1787 1
a1787 1
  // https://github.com/google/sanitizers/issues/321.
d1798 1
a1798 1
  // https://github.com/google/sanitizers/issues/321.
d1809 1
a1809 1
  // https://github.com/google/sanitizers/issues/321.
d1823 1
a1823 1
  // https://github.com/google/sanitizers/issues/321.
d1838 1
a1838 1
  // https://github.com/google/sanitizers/issues/321.
d1867 1
a1867 1
  // https://github.com/google/sanitizers/issues/321.
d1879 1
a1879 1
  // https://github.com/google/sanitizers/issues/321.
d1901 1
a1901 1
  // https://github.com/google/sanitizers/issues/321.
d1920 1
a1920 1
  // https://github.com/google/sanitizers/issues/321.
d1947 1
a1947 1
  // https://github.com/google/sanitizers/issues/321.
d1979 1
a1979 1
  // https://github.com/google/sanitizers/issues/321.
d2003 1
a2003 1
  // https://github.com/google/sanitizers/issues/321.
d2089 1
a2089 1
  // https://github.com/google/sanitizers/issues/321.
d2112 1
a2112 1
  // https://github.com/google/sanitizers/issues/321.
d2138 1
a2138 1
  // https://github.com/google/sanitizers/issues/321.
d2164 1
a2164 1
  // https://github.com/google/sanitizers/issues/321.
d2190 1
a2190 1
  // https://github.com/google/sanitizers/issues/321.
d2234 1
a2234 1
  // https://github.com/google/sanitizers/issues/321.
d2254 1
a2254 1
  // https://github.com/google/sanitizers/issues/321.
d2266 1
a2266 1
  // https://github.com/google/sanitizers/issues/321.
d2278 1
a2278 1
  // https://github.com/google/sanitizers/issues/321.
d2288 1
a2288 1
  COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
d2313 1
a2313 1
  // https://github.com/google/sanitizers/issues/321.
a2328 69
#if SANITIZER_INTERCEPT_SENDMSG
static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
  const unsigned kCmsgDataOffset =
      RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));

  char *p = (char *)control;
  char *const control_end = p + controllen;
  while (true) {
    if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
    __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));

    if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;

    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
                                  sizeof(cmsg->cmsg_level));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
                                  sizeof(cmsg->cmsg_type));

    if (cmsg->cmsg_len > kCmsgDataOffset) {
      char *data = p + kCmsgDataOffset;
      unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
      if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
    }

    p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
  }
}

static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                        SSIZE_T maxlen) {
#define R(f) \
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
  R(name);
  R(namelen);
  R(iov);
  R(iovlen);
  R(control);
  R(controllen);
  R(flags);
#undef R
  if (msg->msg_name && msg->msg_namelen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
  if (msg->msg_iov && msg->msg_iovlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
                                  sizeof(*msg->msg_iov) * msg->msg_iovlen);
  read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
  if (msg->msg_control && msg->msg_controllen)
    read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
}

INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
            int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
  if (common_flags()->intercept_send && res >= 0 && msg)
    read_msghdr(ctx, msg, res);
  return res;
}
#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
#else
#define INIT_SENDMSG
#endif

d2337 1
a2337 1
  // https://github.com/google/sanitizers/issues/321.
d2353 1
a2353 1
  // https://github.com/google/sanitizers/issues/321.
d2381 1
a2381 1
  // https://github.com/google/sanitizers/issues/321.
d2393 1
a2393 1
  // https://github.com/google/sanitizers/issues/321.
d2417 1
a2417 1
  // https://github.com/google/sanitizers/issues/321.
d2429 1
a2429 1
  // https://github.com/google/sanitizers/issues/321.
d2476 1
a2476 1
  // https://github.com/google/sanitizers/issues/321.
d2531 1
a2531 1
  // https://github.com/google/sanitizers/issues/321.
d2547 1
a2547 1
  // https://github.com/google/sanitizers/issues/321.
d2596 1
a2596 1
  // https://github.com/google/sanitizers/issues/321.
d2608 1
a2608 1
  // https://github.com/google/sanitizers/issues/321.
d2628 1
a2628 1
  // https://github.com/google/sanitizers/issues/321.
d2645 1
a2645 1
  // https://github.com/google/sanitizers/issues/321.
d2675 1
a2675 1
  // https://github.com/google/sanitizers/issues/321.
d2695 1
a2695 1
  // https://github.com/google/sanitizers/issues/321.
d2712 1
a2712 1
  // https://github.com/google/sanitizers/issues/321.
d2740 1
a2740 1
  // https://github.com/google/sanitizers/issues/321.
d2762 1
a2762 1
  // https://github.com/google/sanitizers/issues/321.
d2782 1
a2782 1
  // https://github.com/google/sanitizers/issues/321.
d2839 1
a2839 1
  // https://github.com/google/sanitizers/issues/321.
d2856 1
a2856 1
  // https://github.com/google/sanitizers/issues/321.
d2898 1
a2898 1
  // https://github.com/google/sanitizers/issues/321.
d2929 1
a2929 1
  // https://github.com/google/sanitizers/issues/321.
d2974 1
a2974 1
  // https://github.com/google/sanitizers/issues/321.
d3027 1
a3027 1
  // https://github.com/google/sanitizers/issues/321.
d3054 1
a3054 1
  // https://github.com/google/sanitizers/issues/321.
d3121 1
a3121 1
  // https://github.com/google/sanitizers/issues/321.
d3147 1
a3147 1
  // https://github.com/google/sanitizers/issues/321.
d3164 1
a3164 1
  // https://github.com/google/sanitizers/issues/321.
d3183 1
a3183 1
  // https://github.com/google/sanitizers/issues/321.
d3199 1
a3199 1
  // https://github.com/google/sanitizers/issues/321.
d3210 1
a3210 1
  // https://github.com/google/sanitizers/issues/321.
d3228 1
a3228 1
  // https://github.com/google/sanitizers/issues/321.
d3246 1
a3246 1
  // https://github.com/google/sanitizers/issues/321.
d3263 1
a3263 1
  // https://github.com/google/sanitizers/issues/321.
d3277 1
a3277 1
  // https://github.com/google/sanitizers/issues/321.
a3296 1
  COMMON_INTERCEPTOR_USER_CALLBACK_START();
a3297 1
  COMMON_INTERCEPTOR_USER_CALLBACK_END();
a3314 2
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
d3322 1
a3322 4
  int res = REAL(pthread_mutex_unlock)(m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
d3385 1
a3385 1
  // https://github.com/google/sanitizers/issues/321.
d3395 1
a3395 1
  // https://github.com/google/sanitizers/issues/321.
d3414 1
a3414 1
  // https://github.com/google/sanitizers/issues/321.
d3424 1
a3424 1
  // https://github.com/google/sanitizers/issues/321.
d3443 1
a3443 1
  // https://github.com/google/sanitizers/issues/321.
d3453 1
a3453 1
  // https://github.com/google/sanitizers/issues/321.
d3472 1
a3472 1
  // https://github.com/google/sanitizers/issues/321.
d3482 1
a3482 1
  // https://github.com/google/sanitizers/issues/321.
d3538 1
a3538 1
  // https://github.com/google/sanitizers/issues/321.
d3551 1
a3551 1
  // https://github.com/google/sanitizers/issues/321.
d3563 1
a3563 1
  // https://github.com/google/sanitizers/issues/321.
d3587 1
a3587 1
  // https://github.com/google/sanitizers/issues/321.
d3599 1
a3599 1
  // https://github.com/google/sanitizers/issues/321.
d3617 1
a3617 1
  // https://github.com/google/sanitizers/issues/321.
d3642 1
a3642 1
  // https://github.com/google/sanitizers/issues/321.
d3655 1
a3655 1
// https://github.com/google/sanitizers/issues/321.
d3694 1
a3694 1
  // https://github.com/google/sanitizers/issues/321.
d3743 1
a3743 1
  // https://github.com/google/sanitizers/issues/321.
d3853 1
a3853 1
      // https://github.com/google/sanitizers/issues/321.
d3871 1
a3871 1
  // https://github.com/google/sanitizers/issues/321.
a3880 14
#if SANITIZER_INTERCEPT_TTYNAME_R
INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
  int res = REAL(ttyname_r)(fd, name, namesize);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
  return res;
}
#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
#else
#define INIT_TTYNAME_R
#endif

d3915 1
a3915 1
  // https://github.com/google/sanitizers/issues/321.
d3925 1
a3925 1
  // https://github.com/google/sanitizers/issues/321.
d3935 1
a3935 1
  // https://github.com/google/sanitizers/issues/321.
d3943 1
a3943 1
  COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
d3954 1
a3954 1
  // https://github.com/google/sanitizers/issues/321.
d3964 1
a3964 1
  // https://github.com/google/sanitizers/issues/321.
d3974 1
a3974 1
  // https://github.com/google/sanitizers/issues/321.
d3982 1
a3982 1
  COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
d4013 1
a4013 1
  COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
d4024 1
a4024 1
  // https://github.com/google/sanitizers/issues/321.
d4034 1
a4034 1
  // https://github.com/google/sanitizers/issues/321.
d4052 1
a4052 1
  // https://github.com/google/sanitizers/issues/321.
d4057 1
a4057 1
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
d4068 1
a4068 1
  // https://github.com/google/sanitizers/issues/321.
d4078 1
a4078 1
  // https://github.com/google/sanitizers/issues/321.
d4108 1
a4108 1
  // https://github.com/google/sanitizers/issues/321.
d4120 1
a4120 1
// https://github.com/google/sanitizers/issues/321.
d4167 1
a4167 1
  // https://github.com/google/sanitizers/issues/321.
d4186 1
a4186 1
  // https://github.com/google/sanitizers/issues/321.
a4197 1
#if !SANITIZER_S390
a4217 76
#if SANITIZER_PPC
// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
// mostly the same semantics as __tls_get_addr, but its presence enables
// some optimizations in linker (which are safe to ignore here).
extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
                          visibility("default")))
void *__tls_get_addr_opt(void *arg);
#endif
#else // SANITIZER_S390
// On s390, we have to intercept two functions here:
// - __tls_get_addr_internal, which is a glibc-internal function that is like
//   the usual __tls_get_addr, but returns a TP-relative offset instead of
//   a proper pointer.  It is used by dlsym for TLS symbols.
// - __tls_get_offset, which is like the above, but also takes a GOT-relative
//   descriptor offset as an argument instead of a pointer.  GOT address
//   is passed in r12, so it's necessary to write it in assembly.  This is
//   the function used by the compiler.
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
  uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
  uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
  void *ptr = reinterpret_cast<void *>(res + tp);
  uptr tls_begin, tls_end;
  COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
  DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
  if (dtv) {
    // New DTLS block has been allocated.
    COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
  }
  return res;
}
// We need a hidden symbol aliasing the above, so that we can jump
// directly to it from the assembly below.
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
                          visibility("hidden")))
uptr __tls_get_addr_hidden(void *arg);
// Now carefully intercept __tls_get_offset.
asm(
  ".text\n"
// The __intercept_ version has to exist, so that gen_dynamic_list.py
// exports our symbol.
  ".weak __tls_get_offset\n"
  ".type __tls_get_offset, @@function\n"
  "__tls_get_offset:\n"
  ".global __interceptor___tls_get_offset\n"
  ".type __interceptor___tls_get_offset, @@function\n"
  "__interceptor___tls_get_offset:\n"
#ifdef __s390x__
  "la %r2, 0(%r2,%r12)\n"
  "jg __tls_get_addr_hidden\n"
#else
  "basr %r3,0\n"
  "0: la %r2,0(%r2,%r12)\n"
  "l %r4,1f-0b(%r3)\n"
  "b 0(%r4,%r3)\n"
  "1: .long __tls_get_addr_hidden - 0b\n"
#endif
  ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
// Assembly wrapper to call REAL(__tls_get_offset)(arg)
  ".type __tls_get_offset_wrapper, @@function\n"
  "__tls_get_offset_wrapper:\n"
#ifdef __s390x__
  "sgr %r2,%r12\n"
#else
  "sr %r2,%r12\n"
#endif
  "br %r3\n"
  ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
);
#endif // SANITIZER_S390
d4229 1
a4229 1
  // https://github.com/google/sanitizers/issues/321.
d4242 1
a4242 1
  // https://github.com/google/sanitizers/issues/321.
d4252 1
a4252 1
  // https://github.com/google/sanitizers/issues/321.
d4274 1
a4274 1
  // https://github.com/google/sanitizers/issues/321.
d4287 1
a4287 1
  // https://github.com/google/sanitizers/issues/321.
d4299 1
a4299 1
  // https://github.com/google/sanitizers/issues/321.
d4318 1
a4318 1
  // https://github.com/google/sanitizers/issues/321.
d4332 1
a4332 1
  // https://github.com/google/sanitizers/issues/321.
d4357 1
a4357 1
  // https://github.com/google/sanitizers/issues/321.
d4393 1
a4393 1
  // https://github.com/google/sanitizers/issues/321.
d4421 1
a4421 1
  // https://github.com/google/sanitizers/issues/321.
d4522 1
a4522 1
  // https://github.com/google/sanitizers/issues/321.
d4540 1
a4540 1
  // https://github.com/google/sanitizers/issues/321.
d4555 1
a4555 1
  // https://github.com/google/sanitizers/issues/321.
d4562 1
a4562 1
// https://github.com/google/sanitizers/issues/321.
d4616 1
a4616 1
  // https://github.com/google/sanitizers/issues/321.
d4636 1
a4636 1
  // https://github.com/google/sanitizers/issues/321.
d4688 1
a4688 1
  // https://github.com/google/sanitizers/issues/321.
d4770 1
a4770 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
d4841 1
a4841 1
  // https://github.com/google/sanitizers/issues/321.
d4872 1
a4872 1
  // https://github.com/google/sanitizers/issues/321.
a5285 214
#if SANITIZER_INTERCEPT_CTERMID
INTERCEPTOR(char *, ctermid, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
  char *res = REAL(ctermid)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
#else
#define INIT_CTERMID
#endif

#if SANITIZER_INTERCEPT_CTERMID_R
INTERCEPTOR(char *, ctermid_r, char *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
  char *res = REAL(ctermid_r)(s);
  if (res) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
#else
#define INIT_CTERMID_R
#endif

#if SANITIZER_INTERCEPT_RECV_RECVFROM
INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SSIZE_T res = REAL(recv)(fd, buf, len, flags);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
  }
  if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}

INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
            void *srcaddr, int *addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
                           addrlen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  SIZE_T srcaddr_sz;
  if (srcaddr) srcaddr_sz = *addrlen;
  (void)srcaddr_sz;  // prevent "set but not used" warning
  SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
  if (res > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
    if (srcaddr)
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
                                          Min((SIZE_T)*addrlen, srcaddr_sz));
  }
  return res;
}
#define INIT_RECV_RECVFROM          \
  COMMON_INTERCEPT_FUNCTION(recv);  \
  COMMON_INTERCEPT_FUNCTION(recvfrom);
#else
#define INIT_RECV_RECVFROM
#endif

#if SANITIZER_INTERCEPT_SEND_SENDTO
INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  SSIZE_T res = REAL(send)(fd, buf, len, flags);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}

INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
            void *dstaddr, int addrlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  // Can't check dstaddr as it may have uninitialized padding at the end.
  SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
  if (common_flags()->intercept_send && res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
  return res;
}
#define INIT_SEND_SENDTO           \
  COMMON_INTERCEPT_FUNCTION(send); \
  COMMON_INTERCEPT_FUNCTION(sendto);
#else
#define INIT_SEND_SENDTO
#endif

#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(eventfd_read)(fd, value);
  if (res == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  int res = REAL(eventfd_write)(fd, value);
  return res;
}
#define INIT_EVENTFD_READ_WRITE            \
  COMMON_INTERCEPT_FUNCTION(eventfd_read); \
  COMMON_INTERCEPT_FUNCTION(eventfd_write)
#else
#define INIT_EVENTFD_READ_WRITE
#endif

#if SANITIZER_INTERCEPT_STAT
INTERCEPTOR(int, stat, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(stat)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
#else
#define INIT_STAT
#endif

#if SANITIZER_INTERCEPT___XSTAT
INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
#else
#define INIT___XSTAT
#endif

#if SANITIZER_INTERCEPT___XSTAT64
INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__xstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
#else
#define INIT___XSTAT64
#endif

#if SANITIZER_INTERCEPT___LXSTAT
INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
#else
#define INIT___LXSTAT
#endif

#if SANITIZER_INTERCEPT___LXSTAT64
INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(__lxstat64)(version, path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
#else
#define INIT___LXSTAT64
#endif

// FIXME: add other *stat interceptor

a5290 2
  INIT_STRLEN;
  INIT_STRNLEN;
a5296 3
  INIT_STRCHR;
  INIT_STRCHRNUL;
  INIT_STRRCHR;
a5298 3
  INIT_MEMSET;
  INIT_MEMMOVE;
  INIT_MEMCPY;
a5301 1
  INIT_MEMMEM;
a5350 1
  INIT_SENDMSG;
a5419 1
  INIT_TTYNAME_R;
a5459 11
  INIT_CTERMID;
  INIT_CTERMID_R;
  INIT_RECV_RECVFROM;
  INIT_SEND_SENDTO;
  INIT_STAT;
  INIT_EVENTFD_READ_WRITE;
  INIT___XSTAT;
  INIT___XSTAT64;
  INIT___LXSTAT;
  INIT___LXSTAT64;
  // FIXME: add other *stat interceptors.
@


1.1.1.6
log
@import GCC 8.3.  it includes these new features:
- many optimisations improved: inter-procedural, profile-directed,
  LTO, loops including user-controllable unroll support, and more.
- columns numbers added to line numbers in dwarf
- gcov extended significantly
- many sanitizer updates
- many new warning messages
- many better hints and more useful error messages
- minor ABI changes on x86-64 libstdc++, and some c++17 modes
- draft c++2a features
- better c++17 experimental support
- Armv8.4-A supported, better 8.2-A and 8.3-A support, including
  32 bit arm port.  cortex a-55, a-75 and a-55.a-75 combo support.
- in the GCC bugzilla, 8.1 shows 1149 bugs fixed, 8.2 shows 100, and
  8.3 shows 158.
@
text
@d25 1
a25 2
//   COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
//   COMMON_INTERCEPTOR_MUTEX_POST_LOCK
a30 5
//   COMMON_INTERCEPTOR_MEMSET_IMPL
//   COMMON_INTERCEPTOR_MEMMOVE_IMPL
//   COMMON_INTERCEPTOR_MEMCPY_IMPL
//   COMMON_INTERCEPTOR_COPY_STRING
//   COMMON_INTERCEPTOR_STRNDUP_IMPL
a34 1
#include "sanitizer_errno.h"
a36 1
#include "sanitizer_symbolizer.h"
d42 9
a50 3
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
  SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
a67 13
// Platform-specific options.
#if SANITIZER_MAC
namespace __sanitizer {
bool PlatformHasDifferentMemcpyAndMemmove();
}
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
  (__sanitizer::PlatformHasDifferentMemcpyAndMemmove())
#elif SANITIZER_WINDOWS64
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
#else
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
#endif  // SANITIZER_MAC

d80 2
a81 6
#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
d125 4
d130 1
a130 2
    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
      common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
d133 1
a133 2
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
  CheckNoDeepBind(filename, flag);
a163 59
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
  {                                                       \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)        \
      return internal_memset(dst, v, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);  \
    if (common_flags()->intercept_intrin)                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);     \
    return REAL(memset)(dst, v, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
  {                                                          \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)           \
      return internal_memmove(dst, src, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                  \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);        \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);         \
    }                                                        \
    return REAL(memmove)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
  {                                                         \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {        \
      return internal_memmove(dst, src, size);              \
    }                                                       \
    COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);       \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);        \
    }                                                       \
    return REAL(memcpy)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_COPY_STRING
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
#endif

#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size)                         \
  COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size);                            \
  uptr copy_length = internal_strnlen(s, size);                               \
  char *new_mem = (char *)WRAP(malloc)(copy_length + 1);                      \
  if (common_flags()->intercept_strndup) {                                    \
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1));       \
  }                                                                           \
  COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);               \
  internal_memcpy(new_mem, s, copy_length);                                   \
  new_mem[copy_length] = '\0';                                                \
  return new_mem;
#endif

d184 1
a184 1
#if SI_POSIX
d211 1
a211 1
#endif  // SI_POSIX
a246 20
#if SANITIZER_INTERCEPT_STRNDUP
INTERCEPTOR(char*, strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
#else
#define INIT_STRNDUP
#endif // SANITIZER_INTERCEPT_STRNDUP

#if SANITIZER_INTERCEPT___STRNDUP
INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
#else
#define INIT___STRNDUP
#endif // SANITIZER_INTERCEPT___STRNDUP

d251 1
a251 1
  if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
d305 2
a306 8
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
d349 1
a349 1
                              const char *s1, const char *s2, uptr size,
d352 1
a352 1
INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
d354 1
a354 1
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
d357 1
a357 1
  for (i = 0; i < size; i++) {
d362 2
a363 8
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
d366 1
a366 1
                             s1, s2, size, result);
d382 2
a383 1
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
a431 46
#if SANITIZER_INTERCEPT_STRTOK

INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
  if (!common_flags()->intercept_strtok) {
    return REAL(strtok)(str, delimiters);
  }
  if (common_flags()->strict_string_checks) {
    // If strict_string_checks is enabled, we check the whole first argument
    // string on the first call (strtok saves this string in a static buffer
    // for subsequent calls). We do not need to check strtok's result.
    // As the delimiters can change, we check them every call.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
                                  REAL(strlen)(delimiters) + 1);
    return REAL(strtok)(str, delimiters);
  } else {
    // However, when strict_string_checks is disabled we cannot check the
    // whole string on the first call. Instead, we check the result string
    // which is guaranteed to be a NULL-terminated substring of the first
    // argument. We also conservatively check one character of str and the
    // delimiters.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
    char *result = REAL(strtok)(str, delimiters);
    if (result != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
    } else if (str != nullptr) {
      // No delimiter were found, it's safe to assume that the entire str was
      // scanned.
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
    }
    return result;
  }
}

#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
#else
#define INIT_STRTOK
#endif

d463 4
a466 5
  if (common_flags()->intercept_strchr) {
    // Keep strlen as macro argument, as macro may ignore it.
    COMMON_INTERCEPTOR_READ_STRING(ctx, s,
      (result ? result - s : REAL(strlen)(s)) + 1);
  }
d495 1
d497 1
a497 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d554 3
a556 1
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
d558 4
a561 1
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
d570 3
a572 1
INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
d574 6
a579 1
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
d588 13
a600 4
INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
  // On OS X, calling internal_memcpy here will cause memory corruptions,
  // because memcpy and memmove are actually aliases of the same
  // implementation.  We need to use internal_memmove here.
d603 1
a603 6
  void *ctx;
  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
    COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
  } else {
    COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
  }
d606 1
a606 10
#define INIT_MEMCPY                                  \
  do {                                               \
    if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
      COMMON_INTERCEPT_FUNCTION(memcpy);             \
    } else {                                         \
      ASSIGN_REAL(memcpy, memmove);                  \
    }                                                \
    CHECK(REAL(memcpy));                             \
  } while (false)

d742 1
a742 1
#if SI_POSIX
a780 17
#if SANITIZER_INTERCEPT_FREAD
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
  return res;
}
#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
#else
#define INIT_FREAD
#endif

a880 14
#if SANITIZER_INTERCEPT_FWRITE
INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
  SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
  return res;
}
#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
#else
#define INIT_FWRITE
#endif

d1228 6
a1233 6
  COMMON_INTERCEPT_FUNCTION_LDBL(scanf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(sscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
d1406 10
a1415 10
  COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
a3189 24
// There are 2 versions of strerror_r:
//  * POSIX version returns 0 on success, negative error code on failure,
//    writes message to buf.
//  * GNU version returns message pointer, which points to either buf or some
//    static storage.
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
    SANITIZER_MAC || SANITIZER_ANDROID
// POSIX version. Spec is not clear on whether buf is NULL-terminated.
// At least on OSX, buf contents are valid even when the call fails.
INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(strerror_r)(errnum, buf, buflen);

  SIZE_T sz = internal_strnlen(buf, buflen);
  if (sz < buflen) ++sz;
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  return res;
}
#else
// GNU version.
d3197 14
a3210 1
  if (res == buf)
d3212 1
a3212 2
  else
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
a3214 2
#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
       //SANITIZER_MAC
d3400 1
a3400 1
  if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
d3441 1
a3441 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3458 1
a3458 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3477 1
a3477 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3540 1
a3540 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
a3608 1
  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
d3613 1
a3613 1
    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
d4487 1
a4487 1
  if (outbuf && *outbuf > outbuf_orig) {
d4842 4
d4847 1
a4847 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4848 1

d4850 1
a4850 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4851 1

d4853 1
a4853 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4854 1

d4856 1
a4856 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4857 1

d4859 1
a4859 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4860 1

d4862 1
a4862 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4863 1

d4866 1
a4866 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4867 1

d4869 1
a4869 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4870 1

d4872 1
a4872 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4873 1

d4875 1
a4875 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4876 1

d4878 1
a4878 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4879 1

d4881 1
a4881 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4882 1

d4901 2
d4904 1
a4904 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4905 1

a5364 1
  Symbolizer::GetOrInit()->InvalidateModuleList();
a5372 1
  Symbolizer::GetOrInit()->InvalidateModuleList();
a5894 146
#if SANITIZER_INTERCEPT_UTMP
INTERCEPTOR(void *, getutent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
  void *res = REAL(getutent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
  void *res = REAL(getutid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
  void *res = REAL(getutline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
#define INIT_UTMP                      \
  COMMON_INTERCEPT_FUNCTION(getutent); \
  COMMON_INTERCEPT_FUNCTION(getutid);  \
  COMMON_INTERCEPT_FUNCTION(getutline);
#else
#define INIT_UTMP
#endif

#if SANITIZER_INTERCEPT_UTMPX
INTERCEPTOR(void *, getutxent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
  void *res = REAL(getutxent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
  void *res = REAL(getutxid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
  void *res = REAL(getutxline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
#define INIT_UTMPX                      \
  COMMON_INTERCEPT_FUNCTION(getutxent); \
  COMMON_INTERCEPT_FUNCTION(getutxid);  \
  COMMON_INTERCEPT_FUNCTION(getutxline);
#else
#define INIT_UTMPX
#endif

#if SANITIZER_INTERCEPT_GETLOADAVG
INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
  int res = REAL(getloadavg)(loadavg, nelem);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
  return res;
}
#define INIT_GETLOADAVG                      \
  COMMON_INTERCEPT_FUNCTION(getloadavg);
#else
#define INIT_GETLOADAVG
#endif

#if SANITIZER_INTERCEPT_MCHECK_MPROBE
INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mprobe, void *ptr) {
  return 0;
}
#endif

INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
  SIZE_T res = REAL(wcslen)(s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
  return res;
}

INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
  SIZE_T res = REAL(wcsnlen)(s, n);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
  return res;
}
#define INIT_WCSLEN                  \
  COMMON_INTERCEPT_FUNCTION(wcslen); \
  COMMON_INTERCEPT_FUNCTION(wcsnlen);

#if SANITIZER_INTERCEPT_WCSCAT
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
  SIZE_T src_size = REAL(wcslen)(src);
  SIZE_T dst_size = REAL(wcslen)(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcscat)(dst, src);  // NOLINT
}

INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
  SIZE_T src_size = REAL(wcsnlen)(src, n);
  SIZE_T dst_size = REAL(wcslen)(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
                                Min(src_size + 1, n) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcsncat)(dst, src, n);  // NOLINT
}
#define INIT_WCSCAT                  \
  COMMON_INTERCEPT_FUNCTION(wcscat); \
  COMMON_INTERCEPT_FUNCTION(wcsncat);
#else
#define INIT_WCSCAT
#endif

a5901 2
  INIT_STRNDUP;
  INIT___STRNDUP;
a5911 1
  INIT_STRTOK;
a5920 1
  INIT_FREAD;
a5926 1
  INIT_FWRITE;
a6090 5
  INIT_UTMP;
  INIT_UTMPX;
  INIT_GETLOADAVG;
  INIT_WCSLEN;
  INIT_WCSCAT;
@


1.1.1.7
log
@import GCC 7.5.0.  doing this here so that the vendor branch has
the code we'll merge into gcc.old and the netbsd-9 tree gcc tree.
GCC 8.4.0 will be imported immediately on top of this again,
restoring the current status.

these PRs in the GCC bugzilla are fixed with this update:

89869 80693 89795 84272 85593 86669 87148 87647 87895 88103 88107 88563
88870 88976 89002 89187 89195 89234 89303 89314 89354 89361 89403 89412
89512 89520 89590 89621 89663 89679 89704 89734 89872 89933 90090 90208
87075 85870 89009 89242 88167 80864 81933 85890 86608 87145 88857 89024
89119 89214 89511 89612 89705 89400 81740 82186 84552 86554 87609 88105
88149 88415 88739 88903 89135 89223 89296 89505 89572 89677 89698 89710
90006 90020 90071 90328 90474 91126 91162 91812 91887 90075 88998 89945
87047 87506 88074 88656 88740 91137 89008 84010 89349 91136 91347 91995
89397 87030 60702 78884 85594 87649 87725 88181 88470 88553 88568 88588
88620 88644 88906 88949 89246 89587 89726 89768 89796 89998 90108 90756
90950 91704 88825 88983 86538 51333 89446 90220 91308 92143 89392 90213
90278 91131 91200 91510 89037 91481 87673 88418 88938 88948 90547 27221
58321 61250 67183 67958 77583 83531 86215 88648 88720 88726 89091 89466
89629 90105 90329 90585 90760 90924 91087 89222 81956 71861 35031 69455
81849 82993 85798 88138 88155 88169 88205 88206 88228 88249 88269 88376
77703 80260 82077 86248 88393 90786 57048 66089 66695 67679 68009 71723
72714 84394 85544 87734 88298 90937 91557 63891 64132 65342 68649 68717
71066 71860 71935 77746 78421 78645 78865 78983 79485 79540 85953 88326
89651 90744
@
text
@d25 2
a26 1
//   COMMON_INTERCEPTOR_MUTEX_LOCK
d32 5
d41 1
d44 1
d50 3
a52 9
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)                                     \
  do {                                                                         \
    if (f)                                                                     \
      f(__VA_ARGS__);                                                          \
  } while (false);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)                                  \
  extern "C" {                                                                 \
  SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);  \
  } // extern "C"
d70 13
d95 6
a100 2
#ifndef COMMON_INTERCEPTOR_MUTEX_LOCK
#define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m) {}
d144 1
a144 1
#define COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n)       \
d146 1
a146 4
      common_flags()->strict_string_checks ? (len) + 1 : (n) )

#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n)                   \
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
d149 2
a150 1
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) {}
d181 59
d260 1
a260 1
#if SI_NOT_WINDOWS
d287 1
a287 1
#endif  // SI_NOT_WINDOWS
d323 20
d347 1
a347 1
  COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
d401 8
a408 2
  COMMON_INTERCEPTOR_READ_STRING(ctx, s1, Min(i + 1, size));
  COMMON_INTERCEPTOR_READ_STRING(ctx, s2, Min(i + 1, size));
d451 1
a451 1
                              const char *s1, const char *s2, uptr n,
d454 1
a454 1
INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
d456 1
a456 1
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
d459 1
a459 1
  for (i = 0; i < n; i++) {
d464 8
a471 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
d474 1
a474 1
                             s1, s2, n, result);
d490 1
a490 2
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s1, len1,
                                          r ? r - s1 + len2 : len1 + 1);
d539 46
d616 5
a620 4
  uptr len = internal_strlen(s);
  uptr n = result ? result - s + 1 : len + 1;
  if (common_flags()->intercept_strchr)
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n);
a648 1
  uptr len = internal_strlen(s);
d650 1
a650 1
    COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, len + 1);
d707 1
a707 3
INTERCEPTOR(void*, memset, void *dst, int v, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memset(dst, v, size);
d709 1
a709 4
  COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);
  if (common_flags()->intercept_intrin)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
  return REAL(memset)(dst, v, size);
d718 1
a718 3
INTERCEPTOR(void*, memmove, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memmove(dst, src, size);
d720 1
a720 6
  COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
  }
  return REAL(memmove)(dst, src, size);
d729 6
a734 7
INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {
    // On OS X, calling internal_memcpy here will cause memory corruptions,
    // because memcpy and memmove are actually aliases of the same
    // implementation.  We need to use internal_memmove here.
    return internal_memmove(dst, src, size);
  }
d736 4
a739 4
  COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);
  if (common_flags()->intercept_intrin) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);
a740 3
  // N.B.: If we switch this to internal_ we'll have to use internal_memmove
  // due to memcpy being an alias of memmove on OS X.
  return REAL(memcpy)(dst, src, size);
d743 10
a752 1
#define INIT_MEMCPY COMMON_INTERCEPT_FUNCTION(memcpy)
d888 1
a888 1
#if SI_NOT_WINDOWS
d927 17
d1044 14
d1405 6
a1410 6
  COMMON_INTERCEPT_FUNCTION(scanf);   \
  COMMON_INTERCEPT_FUNCTION(sscanf);  \
  COMMON_INTERCEPT_FUNCTION(fscanf);  \
  COMMON_INTERCEPT_FUNCTION(vscanf);  \
  COMMON_INTERCEPT_FUNCTION(vsscanf); \
  COMMON_INTERCEPT_FUNCTION(vfscanf);
d1583 10
a1592 10
  COMMON_INTERCEPT_FUNCTION(printf);    \
  COMMON_INTERCEPT_FUNCTION(sprintf);   \
  COMMON_INTERCEPT_FUNCTION(snprintf);  \
  COMMON_INTERCEPT_FUNCTION(asprintf);  \
  COMMON_INTERCEPT_FUNCTION(fprintf);   \
  COMMON_INTERCEPT_FUNCTION(vprintf);   \
  COMMON_INTERCEPT_FUNCTION(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION(vasprintf); \
  COMMON_INTERCEPT_FUNCTION(vfprintf);
d3367 24
d3398 1
a3398 14
  // There are 2 versions of strerror_r:
  //  * POSIX version returns 0 on success, negative error code on failure,
  //    writes message to buf.
  //  * GNU version returns message pointer, which points to either buf or some
  //    static storage.
  SIZE_T posix_res = (SIZE_T)res;
  if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
    // POSIX version. Spec is not clear on whether buf is NULL-terminated.
    // At least on OSX, buf contents are valid even when the call fails.
    SIZE_T sz = internal_strnlen(buf, buflen);
    if (sz < buflen) ++sz;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  } else {
    // GNU version.
d3400 2
a3401 1
  }
d3404 2
d3591 1
a3591 1
  // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
d3632 1
a3632 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3649 1
a3649 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3668 1
a3668 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3731 1
a3731 1
  // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
d3800 1
d3805 1
a3805 1
    COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
d4679 1
a4679 1
  if (res != (SIZE_T) - 1 && outbuf && *outbuf > outbuf_orig) {
a5033 4
DECLARE_REAL_AND_INTERCEPTOR(void *, memmove, void *, const void *, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void *, memcpy, void *, const void *, uptr)
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr)

d5035 2
a5036 1
  return WRAP(memmove)(to, from, size);
d5038 1
d5040 2
a5041 1
  return WRAP(memmove)(to, from, size);
d5043 1
d5045 2
a5046 1
  return WRAP(memmove)(to, from, size);
d5048 1
d5050 2
a5051 1
  return WRAP(memcpy)(to, from, size);
d5053 1
d5055 2
a5056 1
  return WRAP(memcpy)(to, from, size);
d5058 1
d5060 2
a5061 1
  return WRAP(memcpy)(to, from, size);
d5063 1
d5066 2
a5067 1
  return WRAP(memset)(block, c, size);
d5069 1
d5071 2
a5072 1
  return WRAP(memset)(block, c, size);
d5074 1
d5076 2
a5077 1
  return WRAP(memset)(block, c, size);
d5079 1
d5081 2
a5082 1
  return WRAP(memset)(block, 0, size);
d5084 1
d5086 2
a5087 1
  return WRAP(memset)(block, 0, size);
d5089 1
d5091 2
a5092 1
  return WRAP(memset)(block, 0, size);
d5094 1
a5112 2
DECLARE_REAL_AND_INTERCEPTOR(void *, memset, void *, int, uptr);

d5114 2
a5115 1
  return WRAP(memset)(block, 0, size);
d5117 1
d5577 1
d5586 1
d6109 146
d6262 2
d6274 1
d6284 1
d6291 1
d6456 5
@


1.1.1.8
log
@re-import GCC 8.4.0.
@
text
@d25 1
a25 2
//   COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
//   COMMON_INTERCEPTOR_MUTEX_POST_LOCK
a30 5
//   COMMON_INTERCEPTOR_MEMSET_IMPL
//   COMMON_INTERCEPTOR_MEMMOVE_IMPL
//   COMMON_INTERCEPTOR_MEMCPY_IMPL
//   COMMON_INTERCEPTOR_COPY_STRING
//   COMMON_INTERCEPTOR_STRNDUP_IMPL
a34 1
#include "sanitizer_errno.h"
a36 1
#include "sanitizer_symbolizer.h"
d42 9
a50 3
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
  SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
a67 13
// Platform-specific options.
#if SANITIZER_MAC
namespace __sanitizer {
bool PlatformHasDifferentMemcpyAndMemmove();
}
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
  (__sanitizer::PlatformHasDifferentMemcpyAndMemmove())
#elif SANITIZER_WINDOWS64
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
#else
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
#endif  // SANITIZER_MAC

d80 2
a81 6
#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
#endif

#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
d125 4
d130 1
a130 2
    COMMON_INTERCEPTOR_READ_RANGE((ctx), (s),                       \
      common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
d133 1
a133 2
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
  CheckNoDeepBind(filename, flag);
a163 59
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
  {                                                       \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)        \
      return internal_memset(dst, v, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);  \
    if (common_flags()->intercept_intrin)                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);     \
    return REAL(memset)(dst, v, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
  {                                                          \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)           \
      return internal_memmove(dst, src, size);               \
    COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                  \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);        \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);         \
    }                                                        \
    return REAL(memmove)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
  {                                                         \
    if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) {        \
      return internal_memmove(dst, src, size);              \
    }                                                       \
    COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size);  \
    if (common_flags()->intercept_intrin) {                 \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);       \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size);        \
    }                                                       \
    return REAL(memcpy)(dst, src, size);                    \
  }
#endif

#ifndef COMMON_INTERCEPTOR_COPY_STRING
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
#endif

#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size)                         \
  COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size);                            \
  uptr copy_length = internal_strnlen(s, size);                               \
  char *new_mem = (char *)WRAP(malloc)(copy_length + 1);                      \
  if (common_flags()->intercept_strndup) {                                    \
    COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1));       \
  }                                                                           \
  COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);               \
  internal_memcpy(new_mem, s, copy_length);                                   \
  new_mem[copy_length] = '\0';                                                \
  return new_mem;
#endif

d184 1
a184 1
#if SI_POSIX
d211 1
a211 1
#endif  // SI_POSIX
a246 20
#if SANITIZER_INTERCEPT_STRNDUP
INTERCEPTOR(char*, strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
#else
#define INIT_STRNDUP
#endif // SANITIZER_INTERCEPT_STRNDUP

#if SANITIZER_INTERCEPT___STRNDUP
INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
}
#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
#else
#define INIT___STRNDUP
#endif // SANITIZER_INTERCEPT___STRNDUP

d251 1
a251 1
  if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
d305 2
a306 8
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
d349 1
a349 1
                              const char *s1, const char *s2, uptr size,
d352 1
a352 1
INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
d354 1
a354 1
  COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
d357 1
a357 1
  for (i = 0; i < size; i++) {
d362 2
a363 8
  uptr i1 = i;
  uptr i2 = i;
  if (common_flags()->strict_string_checks) {
    for (; i1 < size && s1[i1]; i1++) {}
    for (; i2 < size && s2[i2]; i2++) {}
  }
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
  COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
d366 1
a366 1
                             s1, s2, size, result);
d382 2
a383 1
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
a431 46
#if SANITIZER_INTERCEPT_STRTOK

INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
  if (!common_flags()->intercept_strtok) {
    return REAL(strtok)(str, delimiters);
  }
  if (common_flags()->strict_string_checks) {
    // If strict_string_checks is enabled, we check the whole first argument
    // string on the first call (strtok saves this string in a static buffer
    // for subsequent calls). We do not need to check strtok's result.
    // As the delimiters can change, we check them every call.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
                                  REAL(strlen)(delimiters) + 1);
    return REAL(strtok)(str, delimiters);
  } else {
    // However, when strict_string_checks is disabled we cannot check the
    // whole string on the first call. Instead, we check the result string
    // which is guaranteed to be a NULL-terminated substring of the first
    // argument. We also conservatively check one character of str and the
    // delimiters.
    if (str != nullptr) {
      COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
    }
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
    char *result = REAL(strtok)(str, delimiters);
    if (result != nullptr) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
    } else if (str != nullptr) {
      // No delimiter were found, it's safe to assume that the entire str was
      // scanned.
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
    }
    return result;
  }
}

#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
#else
#define INIT_STRTOK
#endif

d463 4
a466 5
  if (common_flags()->intercept_strchr) {
    // Keep strlen as macro argument, as macro may ignore it.
    COMMON_INTERCEPTOR_READ_STRING(ctx, s,
      (result ? result - s : REAL(strlen)(s)) + 1);
  }
d495 1
d497 1
a497 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
d554 3
a556 1
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
d558 4
a561 1
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
d570 3
a572 1
INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
d574 6
a579 1
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
d588 13
a600 4
INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
  // On OS X, calling internal_memcpy here will cause memory corruptions,
  // because memcpy and memmove are actually aliases of the same
  // implementation.  We need to use internal_memmove here.
d603 1
a603 6
  void *ctx;
  if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
    COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
  } else {
    COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
  }
d606 1
a606 10
#define INIT_MEMCPY                                  \
  do {                                               \
    if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
      COMMON_INTERCEPT_FUNCTION(memcpy);             \
    } else {                                         \
      ASSIGN_REAL(memcpy, memmove);                  \
    }                                                \
    CHECK(REAL(memcpy));                             \
  } while (false)

d742 1
a742 1
#if SI_POSIX
a780 17
#if SANITIZER_INTERCEPT_FREAD
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
  return res;
}
#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
#else
#define INIT_FREAD
#endif

a880 14
#if SANITIZER_INTERCEPT_FWRITE
INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
  SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
  return res;
}
#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
#else
#define INIT_FWRITE
#endif

d1228 6
a1233 6
  COMMON_INTERCEPT_FUNCTION_LDBL(scanf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(sscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vscanf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
d1406 10
a1415 10
  COMMON_INTERCEPT_FUNCTION_LDBL(printf);    \
  COMMON_INTERCEPT_FUNCTION_LDBL(sprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(snprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(asprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(fprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vprintf);   \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf);  \
  COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
  COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
a3189 24
// There are 2 versions of strerror_r:
//  * POSIX version returns 0 on success, negative error code on failure,
//    writes message to buf.
//  * GNU version returns message pointer, which points to either buf or some
//    static storage.
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
    SANITIZER_MAC || SANITIZER_ANDROID
// POSIX version. Spec is not clear on whether buf is NULL-terminated.
// At least on OSX, buf contents are valid even when the call fails.
INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(strerror_r)(errnum, buf, buflen);

  SIZE_T sz = internal_strnlen(buf, buflen);
  if (sz < buflen) ++sz;
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
  return res;
}
#else
// GNU version.
d3197 14
a3210 1
  if (res == buf)
d3212 1
a3212 2
  else
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
a3214 2
#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
       //SANITIZER_MAC
d3400 1
a3400 1
  if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
d3441 1
a3441 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3458 1
a3458 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3477 1
a3477 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
d3540 1
a3540 1
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
a3608 1
  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
d3613 1
a3613 1
    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
d4487 1
a4487 1
  if (outbuf && *outbuf > outbuf_orig) {
d4842 4
d4847 1
a4847 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4848 1

d4850 1
a4850 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4851 1

d4853 1
a4853 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
a4854 1

d4856 1
a4856 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4857 1

d4859 1
a4859 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4860 1

d4862 1
a4862 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
a4863 1

d4866 1
a4866 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4867 1

d4869 1
a4869 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4870 1

d4872 1
a4872 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
a4873 1

d4875 1
a4875 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4876 1

d4878 1
a4878 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4879 1

d4881 1
a4881 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4882 1

d4901 2
d4904 1
a4904 2
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
a4905 1

a5364 1
  Symbolizer::GetOrInit()->InvalidateModuleList();
a5372 1
  Symbolizer::GetOrInit()->InvalidateModuleList();
a5894 146
#if SANITIZER_INTERCEPT_UTMP
INTERCEPTOR(void *, getutent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
  void *res = REAL(getutent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
  void *res = REAL(getutid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
INTERCEPTOR(void *, getutline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
  void *res = REAL(getutline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
  return res;
}
#define INIT_UTMP                      \
  COMMON_INTERCEPT_FUNCTION(getutent); \
  COMMON_INTERCEPT_FUNCTION(getutid);  \
  COMMON_INTERCEPT_FUNCTION(getutline);
#else
#define INIT_UTMP
#endif

#if SANITIZER_INTERCEPT_UTMPX
INTERCEPTOR(void *, getutxent, int dummy) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
  void *res = REAL(getutxent)(dummy);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxid, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
  void *res = REAL(getutxid)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
INTERCEPTOR(void *, getutxline, void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
  void *res = REAL(getutxline)(ut);
  if (res)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
  return res;
}
#define INIT_UTMPX                      \
  COMMON_INTERCEPT_FUNCTION(getutxent); \
  COMMON_INTERCEPT_FUNCTION(getutxid);  \
  COMMON_INTERCEPT_FUNCTION(getutxline);
#else
#define INIT_UTMPX
#endif

#if SANITIZER_INTERCEPT_GETLOADAVG
INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
  int res = REAL(getloadavg)(loadavg, nelem);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
  return res;
}
#define INIT_GETLOADAVG                      \
  COMMON_INTERCEPT_FUNCTION(getloadavg);
#else
#define INIT_GETLOADAVG
#endif

#if SANITIZER_INTERCEPT_MCHECK_MPROBE
INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
  return 0;
}

INTERCEPTOR(int, mprobe, void *ptr) {
  return 0;
}
#endif

INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
  SIZE_T res = REAL(wcslen)(s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
  return res;
}

INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
  SIZE_T res = REAL(wcsnlen)(s, n);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
  return res;
}
#define INIT_WCSLEN                  \
  COMMON_INTERCEPT_FUNCTION(wcslen); \
  COMMON_INTERCEPT_FUNCTION(wcsnlen);

#if SANITIZER_INTERCEPT_WCSCAT
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
  SIZE_T src_size = REAL(wcslen)(src);
  SIZE_T dst_size = REAL(wcslen)(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcscat)(dst, src);  // NOLINT
}

INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
  SIZE_T src_size = REAL(wcsnlen)(src, n);
  SIZE_T dst_size = REAL(wcslen)(dst);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
                                Min(src_size + 1, n) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
                                 (src_size + 1) * sizeof(wchar_t));
  return REAL(wcsncat)(dst, src, n);  // NOLINT
}
#define INIT_WCSCAT                  \
  COMMON_INTERCEPT_FUNCTION(wcscat); \
  COMMON_INTERCEPT_FUNCTION(wcsncat);
#else
#define INIT_WCSCAT
#endif

a5901 2
  INIT_STRNDUP;
  INIT___STRNDUP;
a5911 1
  INIT_STRTOK;
a5920 1
  INIT_FREAD;
a5926 1
  INIT_FWRITE;
a6090 5
  INIT_UTMP;
  INIT_UTMPX;
  INIT_GETLOADAVG;
  INIT_WCSLEN;
  INIT_WCSCAT;
@


1.1.1.9
log
@initial import of GCC 9.3.0.  changes include:

- live patching support
- shell completion help
- generally better diagnostic output (less verbose/more useful)
- diagnostics and optimisation choices can be emitted in json
- asan memory usage reduction
- many general, and specific to switch, inter-procedure,
  profile and link-time optimisations.  from the release notes:
  "Overall compile time of Firefox 66 and LibreOffice 6.2.3 on
  an 8-core machine was reduced by about 5% compared to GCC 8.3"
- OpenMP 5.0 support
- better spell-guesser
- partial experimental support for c2x and c++2a
- c++17 is no longer experimental
- arm AAPCS GCC 6-8 structure passing bug fixed, may cause
  incompatibility (restored compat with GCC 5 and earlier.)
- openrisc support
@
text
@a34 1
//   COMMON_INTERCEPTOR_MMAP_IMPL
a69 46
#if SANITIZER_NETBSD
#define clock_getres __clock_getres50
#define clock_gettime __clock_gettime50
#define clock_settime __clock_settime50
#define ctime __ctime50
#define ctime_r __ctime_r50
#define devname __devname50
#define getitimer __getitimer50
#define getpwent __getpwent50
#define getpwnam __getpwnam50
#define getpwnam_r __getpwnam_r50
#define getpwuid __getpwuid50
#define getpwuid_r __getpwuid_r50
#define getutent __getutent50
#define getutxent __getutxent50
#define getutxid __getutxid50
#define getutxline __getutxline50
#define glob __glob30
#define gmtime __gmtime50
#define gmtime_r __gmtime_r50
#define localtime __locatime50
#define localtime_r __localtime_r50
#define mktime __mktime50
#define lstat __lstat50
#define opendir __opendir30
#define readdir __readdir30
#define readdir_r __readdir_r30
#define scandir __scandir30
#define setitimer __setitimer50
#define setlocale __setlocale50
#define shmctl __shmctl50
#define sigemptyset __sigemptyset14
#define sigfillset __sigfillset14
#define sigpending __sigpending14
#define sigprocmask __sigprocmask14
#define sigtimedwait __sigtimedwait50
#define stat __stat50
#define time __time50
#define times __times13
#define wait3 __wait350
#define wait4 __wait450
extern const unsigned short *_ctype_tab_;
extern const short *_toupper_tab_;
extern const short *_tolower_tab_;
#endif

a221 6
#ifndef COMMON_INTERCEPTOR_MMAP_IMPL
#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
                                     off)                                  \
  { return REAL(mmap)(addr, sz, prot, flags, fd, off); }
#endif

d274 1
a274 1
  if (addr && h.exists()) {
a1136 44
#if SANITIZER_INTERCEPT_FGETS
INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgets, s, size, file);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  char *res = REAL(fgets)(s, size, file);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
  return res;
}
#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
#else
#define INIT_FGETS
#endif

#if SANITIZER_INTERCEPT_FPUTS
INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
  return REAL(fputs)(s, file);
}
#define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs)
#else
#define INIT_FPUTS
#endif

#if SANITIZER_INTERCEPT_PUTS
INTERCEPTOR(int, puts, char *s) {
  // libc file streams can call user-supplied functions, see fopencookie.
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
  return REAL(puts)(s);
}
#define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts)
#else
#define INIT_PUTS
#endif

a1177 1
#if !SANITIZER_SOLARIS
a1183 1
#endif
a1510 6
#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag,
            SIZE_T size_to, const char *format, va_list ap)
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
#endif

a1523 6
#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
            const char *format, va_list ap)
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
#endif

a1551 6
#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
#endif

a1554 6
#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
            const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT
#endif

a1557 6
#if SANITIZER_INTERCEPT___PRINTF_CHK
INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
            SIZE_T size_to, const char *format, ...) // NOLINT
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT
#endif

a1596 11
#if SANITIZER_INTERCEPT___PRINTF_CHK
#define INIT___PRINTF_CHK                     \
  COMMON_INTERCEPT_FUNCTION(__sprintf_chk);   \
  COMMON_INTERCEPT_FUNCTION(__snprintf_chk);  \
  COMMON_INTERCEPT_FUNCTION(__vsprintf_chk);  \
  COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \
  COMMON_INTERCEPT_FUNCTION(__fprintf_chk);
#else
#define INIT___PRINTF_CHK
#endif

a1620 1
#include "sanitizer_interceptors_ioctl_netbsd.inc"
d1725 1
a1725 2
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
a2004 7
namespace __sanitizer {
extern "C" {
int real_clock_gettime(u32 clk_id, void *tp) {
  return REAL(clock_gettime)(clk_id, tp);
}
}  // extern "C"
}  // namespace __sanitizer
d2035 2
a2036 13
  if (new_value) {
    // itimerval can contain padding that may be legitimately uninitialized
    const struct __sanitizer_itimerval *nv =
        (const struct __sanitizer_itimerval *)new_value;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec,
                                  sizeof(__sanitizer_time_t));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec,
                                  sizeof(__sanitizer_suseconds_t));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec,
                                  sizeof(__sanitizer_time_t));
    COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec,
                                  sizeof(__sanitizer_suseconds_t));
  }
a2065 12
#if SANITIZER_SOLARIS
INTERCEPTOR(int, glob, const char *pattern, int flags,
            int (*errfunc)(const char *epath, int eerrno),
            __sanitizer_glob_t *pglob) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
  COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
  int res = REAL(glob)(pattern, flags, errfunc, pglob);
  if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
  return res;
}
#else
a2128 6
#endif  // SANITIZER_SOLARIS
#define INIT_GLOB                  \
  COMMON_INTERCEPT_FUNCTION(glob);
#else  // SANITIZER_INTERCEPT_GLOB
#define INIT_GLOB
#endif  // SANITIZER_INTERCEPT_GLOB
a2129 1
#if SANITIZER_INTERCEPT_GLOB64
d2158 2
a2159 1
#define INIT_GLOB64                \
d2161 3
a2163 3
#else  // SANITIZER_INTERCEPT_GLOB64
#define INIT_GLOB64
#endif  // SANITIZER_INTERCEPT_GLOB64
a2467 7
#define INIT_GETHOSTBYNAME                  \
  COMMON_INTERCEPT_FUNCTION(gethostent);    \
  COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
  COMMON_INTERCEPT_FUNCTION(gethostbyname);
#else
#define INIT_GETHOSTBYNAME
#endif  // SANITIZER_INTERCEPT_GETHOSTBYNAME
a2468 1
#if SANITIZER_INTERCEPT_GETHOSTBYNAME2
d2476 5
a2480 1
#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2);
d2482 2
a2483 2
#define INIT_GETHOSTBYNAME2
#endif  // SANITIZER_INTERCEPT_GETHOSTBYNAME2
a2652 24
#if SANITIZER_INTERCEPT_PACCEPT
INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen,
            __sanitizer_sigset_t *set, int f) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, paccept, fd, addr, addrlen, set, f);
  unsigned addrlen0 = 0;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addrlen0 = *addrlen;
  }
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  int fd2 = REAL(paccept)(fd, addr, addrlen, set, f);
  if (fd2 >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
    if (addr && addrlen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
  }
  return fd2;
}
#define INIT_PACCEPT COMMON_INTERCEPT_FUNCTION(paccept);
#else
#define INIT_PACCEPT
#endif

d2698 1
a2698 1
#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
a2710 1
#endif
a2711 1
#if SANITIZER_INTERCEPT_RECVMSG
d2734 1
a2734 24
#if SANITIZER_INTERCEPT_RECVMMSG
INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
            unsigned int vlen, int flags, void *timeout) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
  int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
  if (res >= 0) {
    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
    for (int i = 0; i < res; ++i) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
                                     sizeof(msgvec[i].msg_len));
      write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
    }
  }
  return res;
}
#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
#else
#define INIT_RECVMMSG
#endif

#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
a2783 1
#endif
a2784 1
#if SANITIZER_INTERCEPT_SENDMSG
a2802 24
#if SANITIZER_INTERCEPT_SENDMMSG
INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
            unsigned vlen, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
  if (fd >= 0) {
    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  }
  int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
  if (res >= 0 && msgvec)
    for (int i = 0; i < res; ++i) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
                                     sizeof(msgvec[i].msg_len));
      if (common_flags()->intercept_send)
        read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
    }
  return res;
}
#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
#else
#define INIT_SENDMMSG
#endif

a2983 9
static void unpoison_ctype_arrays(void *ctx) {
#if SANITIZER_NETBSD
  // These arrays contain 256 regular elements in unsigned char range + 1 EOF
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short));
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short));
#endif
}

d2990 1
a2990 4
  if (res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
    unpoison_ctype_arrays(ctx);
  }
d3077 1
a3077 1
INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
d3084 1
a3084 1
  UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
d3373 1
a3373 2
    SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD ||                 \
    SANITIZER_FREEBSD || SANITIZER_OPENBSD
d3796 1
a3796 1
#if SANITIZER_INTERCEPT_PTHREAD_MUTEX
a3828 38
#if SANITIZER_INTERCEPT___PTHREAD_MUTEX
INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
  return WRAP(pthread_mutex_lock)(m);
}

INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
  return WRAP(pthread_mutex_unlock)(m);
}

#define INIT___PTHREAD_MUTEX_LOCK \
  COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock)
#define INIT___PTHREAD_MUTEX_UNLOCK \
  COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock)
#else
#define INIT___PTHREAD_MUTEX_LOCK
#define INIT___PTHREAD_MUTEX_UNLOCK
#endif

#if SANITIZER_INTERCEPT___LIBC_MUTEX
INTERCEPTOR(int, __libc_mutex_lock, void *m)
ALIAS(WRAPPER_NAME(pthread_mutex_lock));

INTERCEPTOR(int, __libc_mutex_unlock, void *m)
ALIAS(WRAPPER_NAME(pthread_mutex_unlock));

INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate)
ALIAS(WRAPPER_NAME(pthread_setcancelstate));

#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock)
#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock)
#define INIT___LIBC_THR_SETCANCELSTATE \
  COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate)
#else
#define INIT___LIBC_MUTEX_LOCK
#define INIT___LIBC_MUTEX_UNLOCK
#define INIT___LIBC_THR_SETCANCELSTATE
#endif

a4152 1
    SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED ||        \
d4181 2
d4213 2
a4221 11
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED
INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))

#define INIT_PTHREAD_ATTR_GET_SCHED                      \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \
  COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy);
#else
#define INIT_PTHREAD_ATTR_GET_SCHED
#endif

d4406 1
a4406 1
#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD
a4414 11
#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) {
  void *ctx;
  char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
  COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
  internal_snprintf(newname, sizeof(newname), name, arg);
  COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
  return REAL(pthread_setname_np)(thread, name, arg);
}
#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
a4418 14
#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP
INTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len);
  int res = REAL(pthread_getname_np)(thread, name, len);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1);
  return res;
}
#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
#else
#define INIT_PTHREAD_GETNAME_NP
#endif

d5825 1
a5825 1
  if (res == 0 && oldstate != nullptr)
d5834 1
a5834 1
  if (res == 0 && oldtype != nullptr)
a6042 16
#if SANITIZER_INTERCEPT_LSTAT
INTERCEPTOR(int, lstat, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lstat, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(lstat)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
  return res;
}
#define INIT_LSTAT COMMON_INTERCEPT_FUNCTION(lstat)
#else
#define INIT_LSTAT
#endif

a6254 624
#if SANITIZER_INTERCEPT_STRXFRM
static SIZE_T RealStrLen(const char *str) { return REAL(strlen)(str); }

static SIZE_T RealStrLen(const wchar_t *str) { return REAL(wcslen)(str); }

#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...)             \
  {                                                                        \
    void *ctx;                                                             \
    COMMON_INTERCEPTOR_ENTER(ctx, strxfrm, dest, src, len, ##__VA_ARGS__); \
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src,                                \
                                  sizeof(*src) * (RealStrLen(src) + 1));   \
    SIZE_T res = REAL(strxfrm)(dest, src, len, ##__VA_ARGS__);             \
    if (res < len)                                                         \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, sizeof(*src) * (res + 1)); \
    return res;                                                            \
  }

INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T len) {
  STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len);
}

INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(strxfrm_l, dest, src, len, locale);
}

#define INIT_STRXFRM                  \
  COMMON_INTERCEPT_FUNCTION(strxfrm); \
  COMMON_INTERCEPT_FUNCTION(strxfrm_l);
#else
#define INIT_STRXFRM
#endif

#if SANITIZER_INTERCEPT___STRXFRM_L
INTERCEPTOR(SIZE_T, __strxfrm_l, char *dest, const char *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(__strxfrm_l, dest, src, len, locale);
}

#define INIT___STRXFRM_L COMMON_INTERCEPT_FUNCTION(__strxfrm_l);
#else
#define INIT___STRXFRM_L
#endif

#if SANITIZER_INTERCEPT_WCSXFRM
INTERCEPTOR(SIZE_T, wcsxfrm, wchar_t *dest, const wchar_t *src, SIZE_T len) {
  STRXFRM_INTERCEPTOR_IMPL(wcsxfrm, dest, src, len);
}

INTERCEPTOR(SIZE_T, wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(wcsxfrm_l, dest, src, len, locale);
}

#define INIT_WCSXFRM                  \
  COMMON_INTERCEPT_FUNCTION(wcsxfrm); \
  COMMON_INTERCEPT_FUNCTION(wcsxfrm_l);
#else
#define INIT_WCSXFRM
#endif

#if SANITIZER_INTERCEPT___WCSXFRM_L
INTERCEPTOR(SIZE_T, __wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
            void *locale) {
  STRXFRM_INTERCEPTOR_IMPL(__wcsxfrm_l, dest, src, len, locale);
}

#define INIT___WCSXFRM_L COMMON_INTERCEPT_FUNCTION(__wcsxfrm_l);
#else
#define INIT___WCSXFRM_L
#endif

#if SANITIZER_INTERCEPT_ACCT
INTERCEPTOR(int, acct, const char *file) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
  if (file)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
  return REAL(acct)(file);
}
#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
#else
#define INIT_ACCT
#endif

#if SANITIZER_INTERCEPT_USER_FROM_UID
INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
  void *ctx;
  const char *user;
  COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
  user = REAL(user_from_uid)(uid, nouser);
  if (user)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1);
  return user;
}
#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
#else
#define INIT_USER_FROM_UID
#endif

#if SANITIZER_INTERCEPT_UID_FROM_USER
INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  res = REAL(uid_from_user)(name, uid);
  if (uid)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
  return res;
}
#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user)
#else
#define INIT_UID_FROM_USER
#endif

#if SANITIZER_INTERCEPT_GROUP_FROM_GID
INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
  void *ctx;
  const char *group;
  COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
  group = REAL(group_from_gid)(gid, nogroup);
  if (group)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1);
  return group;
}
#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
#else
#define INIT_GROUP_FROM_GID
#endif

#if SANITIZER_INTERCEPT_GID_FROM_GROUP
INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
  if (group)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1);
  res = REAL(gid_from_group)(group, gid);
  if (gid)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
  return res;
}
#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group)
#else
#define INIT_GID_FROM_GROUP
#endif

#if SANITIZER_INTERCEPT_ACCESS
INTERCEPTOR(int, access, const char *path, int mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  return REAL(access)(path, mode);
}
#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
#else
#define INIT_ACCESS
#endif

#if SANITIZER_INTERCEPT_FACCESSAT
INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  return REAL(faccessat)(fd, path, mode, flags);
}
#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
#else
#define INIT_FACCESSAT
#endif

#if SANITIZER_INTERCEPT_GETGROUPLIST
INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
            int *ngroups) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  if (ngroups)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
  res = REAL(getgrouplist)(name, basegid, groups, ngroups);
  if (!res && groups && ngroups) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
  }
  return res;
}

#define INIT_GETGROUPLIST COMMON_INTERCEPT_FUNCTION(getgrouplist);
#else
#define INIT_GETGROUPLIST
#endif

#if SANITIZER_INTERCEPT_GETGROUPMEMBERSHIP
INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
            int maxgrp, int *ngroups) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
                           maxgrp, ngroups);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
  if (!res && groups && ngroups) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
  }
  return res;
}

#define INIT_GETGROUPMEMBERSHIP COMMON_INTERCEPT_FUNCTION(getgroupmembership);
#else
#define INIT_GETGROUPMEMBERSHIP
#endif

#if SANITIZER_INTERCEPT_READLINK
INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
  return res;
}

#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink)
#else
#define INIT_READLINK
#endif

#if SANITIZER_INTERCEPT_READLINKAT
INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
            SIZE_T bufsiz) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
  return res;
}

#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat)
#else
#define INIT_READLINKAT
#endif

#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT
INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
            struct file_handle *handle, int *mount_id, int flags) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
                           mount_id, flags);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1);

  __sanitizer_file_handle *sanitizer_handle =
      reinterpret_cast<__sanitizer_file_handle*>(handle);
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->handle_bytes,
      sizeof(sanitizer_handle->handle_bytes));

  int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, &sanitizer_handle->handle_bytes,
        sizeof(sanitizer_handle->handle_bytes));
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, &sanitizer_handle->handle_type,
        sizeof(sanitizer_handle->handle_type));
    COMMON_INTERCEPTOR_WRITE_RANGE(
        ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id));
  }
  return res;
}

#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at)
#else
#define INIT_NAME_TO_HANDLE_AT
#endif

#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT
INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
            int flags) {
  void* ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags);

  __sanitizer_file_handle *sanitizer_handle =
      reinterpret_cast<__sanitizer_file_handle*>(handle);
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->handle_bytes,
      sizeof(sanitizer_handle->handle_bytes));
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->handle_type,
      sizeof(sanitizer_handle->handle_type));
  COMMON_INTERCEPTOR_READ_RANGE(
      ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);

  return REAL(open_by_handle_at)(mount_fd, handle, flags);
}

#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
#else
#define INIT_OPEN_BY_HANDLE_AT
#endif

#if SANITIZER_INTERCEPT_STRLCPY
INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
  void *ctx;
  SIZE_T res;
  COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size);
  if (src) {
    // Keep strnlen as macro argument, as macro may ignore it.
    COMMON_INTERCEPTOR_READ_STRING(
        ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
  }
  res = REAL(strlcpy)(dst, src, size);
  COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1);
  return res;
}

INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) {
  void *ctx;
  SIZE_T len = 0;
  COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size);
  // src is checked in the strlcpy() interceptor
  if (dst) {
    len = internal_strnlen(dst, size);
    COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1);
  }
  // Reuse the rest of the code in the strlcpy() interceptor
  return WRAP(strlcpy)(dst + len, src, size - len) + len;
}
#define INIT_STRLCPY \
  COMMON_INTERCEPT_FUNCTION(strlcpy); \
  COMMON_INTERCEPT_FUNCTION(strlcat);
#else
#define INIT_STRLCPY
#endif

#if SANITIZER_INTERCEPT_MMAP
INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
            OFF_T off) {
  void *ctx;
  if (common_flags()->detect_write_exec)
    ReportMmapWriteExec(prot);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off);
}

INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
  void *ctx;
  if (common_flags()->detect_write_exec)
    ReportMmapWriteExec(prot);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (int)internal_mprotect(addr, sz, prot);
  COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot);
  MprotectMallocZones(addr, prot);
  return REAL(mprotect)(addr, sz, prot);
}
#define INIT_MMAP                                                              \
  COMMON_INTERCEPT_FUNCTION(mmap);                                             \
  COMMON_INTERCEPT_FUNCTION(mprotect);
#else
#define INIT_MMAP
#endif

#if SANITIZER_INTERCEPT_MMAP64
INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
            OFF64_T off) {
  void *ctx;
  if (common_flags()->detect_write_exec)
    ReportMmapWriteExec(prot);
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
  COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap64, addr, sz, prot, flags, fd, off);
}
#define INIT_MMAP64 COMMON_INTERCEPT_FUNCTION(mmap64);
#else
#define INIT_MMAP64
#endif

#if SANITIZER_INTERCEPT_DEVNAME
INTERCEPTOR(char *, devname, u64 dev, u32 type) {
  void *ctx;
  char *name;
  COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
  name = REAL(devname)(dev, type);
  if (name)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
  return name;
}
#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
#else
#define INIT_DEVNAME
#endif

#if SANITIZER_INTERCEPT_DEVNAME_R
INTERCEPTOR(int, devname_r, u64 dev, u32 type, char *path, uptr len) {
  void *ctx;
  int res;
  COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
  res = REAL(devname_r)(dev, type, path, len);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1);
  return res;
}
#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
#else
#define INIT_DEVNAME_R
#endif

#if SANITIZER_INTERCEPT_FGETLN
INTERCEPTOR(char *, fgetln, __sanitizer_FILE *stream, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetln, stream, len);
  char *str = REAL(fgetln)(stream, len);
  if (str && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, *len);
  }
  return str;
}
#define INIT_FGETLN COMMON_INTERCEPT_FUNCTION(fgetln)
#else
#define INIT_FGETLN
#endif

#if SANITIZER_INTERCEPT_STRMODE
INTERCEPTOR(void, strmode, u32 mode, char *bp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
  REAL(strmode)(mode, bp);
  if (bp)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, REAL(strlen)(bp) + 1);
}
#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
#else
#define INIT_STRMODE
#endif

#if SANITIZER_INTERCEPT_TTYENT
INTERCEPTOR(struct __sanitizer_ttyent *, getttyent, void) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getttyent);
  struct __sanitizer_ttyent *ttyent = REAL(getttyent)();
  if (ttyent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
  return ttyent;
}
INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
  if (ttyent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
  return ttyent;
}
INTERCEPTOR(int, setttyentpath, char *path) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  return REAL(setttyentpath)(path);
}
#define INIT_TTYENT \
  COMMON_INTERCEPT_FUNCTION(getttyent); \
  COMMON_INTERCEPT_FUNCTION(getttynam); \
  COMMON_INTERCEPT_FUNCTION(setttyentpath)
#else
#define INIT_TTYENT
#endif

#if SANITIZER_INTERCEPT_PROTOENT
INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
  struct __sanitizer_protoent *p = REAL(getprotoent)();
  if (p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);

    SIZE_T pp_size = 1; // One handles the trailing \0

    for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                   pp_size * sizeof(char **));
  }
  return p;
}

INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
  if (p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);

    SIZE_T pp_size = 1; // One handles the trailing \0

    for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                   pp_size * sizeof(char **));
  }
  return p;
}

INTERCEPTOR(struct __sanitizer_protoent *, getprotobynumber, int proto) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber, proto);
  struct __sanitizer_protoent *p = REAL(getprotobynumber)(proto);
  if (p) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);

    SIZE_T pp_size = 1; // One handles the trailing \0

    for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
       COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                   pp_size * sizeof(char **));
  }
  return p;
}
#define INIT_PROTOENT \
  COMMON_INTERCEPT_FUNCTION(getprotoent); \
  COMMON_INTERCEPT_FUNCTION(getprotobyname); \
  COMMON_INTERCEPT_FUNCTION(getprotobynumber)
#else
#define INIT_PROTOENT
#endif

#if SANITIZER_INTERCEPT_NETENT
INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnetent);
  struct __sanitizer_netent *n = REAL(getnetent)();
  if (n) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);

    SIZE_T nn_size = 1; // One handles the trailing \0

    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
                                   nn_size * sizeof(char **));
  }
  return n;
}

INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
  struct __sanitizer_netent *n = REAL(getnetbyname)(name);
  if (n) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);

    SIZE_T nn_size = 1; // One handles the trailing \0

    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
                                   nn_size * sizeof(char **));
  }
  return n;
}

INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type);
  struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type);
  if (n) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);

    SIZE_T nn_size = 1; // One handles the trailing \0

    for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);

    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
                                   nn_size * sizeof(char **));
  }
  return n;
}
#define INIT_NETENT \
  COMMON_INTERCEPT_FUNCTION(getnetent); \
  COMMON_INTERCEPT_FUNCTION(getnetbyname); \
  COMMON_INTERCEPT_FUNCTION(getnetbyaddr)
#else
#define INIT_NETENT
#endif

a6258 2
  INIT_MMAP;
  INIT_MMAP64;
a6275 2
  INIT_STRXFRM;
  INIT___STRXFRM_L;
a6296 3
  INIT_FGETS;
  INIT_FPUTS;
  INIT_PUTS;
a6316 1
  INIT_GLOB64;
a6324 1
  INIT_GETHOSTBYNAME2;
a6331 1
  INIT_PACCEPT;
a6334 2
  INIT_RECVMMSG;
  INIT_SENDMMSG;
a6375 5
  INIT___PTHREAD_MUTEX_LOCK;
  INIT___PTHREAD_MUTEX_UNLOCK;
  INIT___LIBC_MUTEX_LOCK;
  INIT___LIBC_MUTEX_UNLOCK;
  INIT___LIBC_THR_SETCANCELSTATE;
a6388 1
  INIT_PTHREAD_ATTR_GET_SCHED;
a6406 1
  INIT_PTHREAD_GETNAME_NP;
a6450 1
  INIT_LSTAT;
a6460 25
  INIT_WCSXFRM;
  INIT___WCSXFRM_L;
  INIT_ACCT;
  INIT_USER_FROM_UID;
  INIT_UID_FROM_USER;
  INIT_GROUP_FROM_GID;
  INIT_GID_FROM_GROUP;
  INIT_ACCESS;
  INIT_FACCESSAT;
  INIT_GETGROUPLIST;
  INIT_GETGROUPMEMBERSHIP;
  INIT_READLINK;
  INIT_READLINKAT;
  INIT_NAME_TO_HANDLE_AT;
  INIT_OPEN_BY_HANDLE_AT;
  INIT_STRLCPY;
  INIT_DEVNAME;
  INIT_DEVNAME_R;
  INIT_FGETLN;
  INIT_STRMODE;
  INIT_TTYENT;
  INIT_PROTOENT;
  INIT_NETENT;

  INIT___PRINTF_CHK;
@


1.1.1.10
log
@initial import of GCC 10.3.0.  main changes include:

caveats:
- ABI issue between c++14 and c++17 fixed
- profile mode is removed from libstdc++
- -fno-common is now the default

new features:
- new flags -fallocation-dce, -fprofile-partial-training,
  -fprofile-reproducible, -fprofile-prefix-path, and -fanalyzer
- many new compile and link time optimisations
- enhanced drive optimisations
- openacc 2.6 support
- openmp 5.0 features
- new warnings: -Wstring-compare and -Wzero-length-bounds
- extended warnings: -Warray-bounds, -Wformat-overflow,
  -Wrestrict, -Wreturn-local-addr, -Wstringop-overflow,
  -Warith-conversion, -Wmismatched-tags, and -Wredundant-tags
- some likely C2X features implemented
- more C++20 implemented
- many new arm & intel CPUs known

hundreds of reported bugs are fixed.  full list of changes
can be found at:

   https://gcc.gnu.org/gcc-10/changes.html
@
text
@d3 2
a4 3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
a37 1
//   COMMON_INTERCEPTOR_STRERROR
a77 7
#define fgetpos __fgetpos50
#define fsetpos __fsetpos50
#define fts_children __fts_children60
#define fts_close __fts_close60
#define fts_open __fts_open60
#define fts_read __fts_read60
#define fts_set __fts_set60
a78 1
#define getmntinfo __getmntinfo13
a87 1
#define pututxline __pututxline50
a109 1
#define unvis __unvis50
a292 4
#ifndef COMMON_INTERCEPTOR_STRERROR
#define COMMON_INTERCEPTOR_STRERROR() {}
#endif

a308 1
#if SI_POSIX
d313 1
d811 1
d816 5
a820 4
// Common code for `memcmp` and `bcmp`.
int MemcmpInterceptorCommon(void *ctx,
                            int (*real_fn)(const void *, const void *, uptr),
                            const void *a1, const void *a2, uptr size) {
d846 1
a846 1
  int result = real_fn(a1, a2, size);
a851 8
INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
  return MemcmpInterceptorCommon(ctx, REAL(memcmp), a1, a2, size);
}

a856 14
#if SANITIZER_INTERCEPT_BCMP
INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_memcmp(a1, a2, size);
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size);
  return MemcmpInterceptorCommon(ctx, REAL(bcmp), a1, a2, size);
}

#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp)
#else
#define INIT_BCMP
#endif

d1213 1
a1213 3
  if (!SANITIZER_MAC || s) {  // `fputs(NULL, file)` is supported on Darwin.
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
  }
d1226 1
a1226 3
  if (!SANITIZER_MAC || s) {  // `puts(NULL)` is supported on Darwin.
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
  }
d1235 3
a1237 2
INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
            unsigned long arg4, unsigned long arg5) {
d1669 2
a1670 2
INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
d1674 2
a1675 2
            const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
d1683 2
a1684 2
            SIZE_T size_to, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
d1809 4
a1812 2
#if SANITIZER_POSIX
UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
d1816 2
a1817 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
                                     REAL(strlen)(pwd->pw_name) + 1);
d1819 2
a1820 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
                                     REAL(strlen)(pwd->pw_passwd) + 1);
d1823 2
a1824 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
                                     REAL(strlen)(pwd->pw_gecos) + 1);
d1826 1
a1826 1
#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
d1828 2
a1829 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
                                     REAL(strlen)(pwd->pw_class) + 1);
d1832 2
a1833 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
                                     REAL(strlen)(pwd->pw_dir) + 1);
d1835 2
a1836 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
                                     REAL(strlen)(pwd->pw_shell) + 1);
d1840 1
a1840 1
UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
d1844 2
a1845 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
                                     REAL(strlen)(grp->gr_name) + 1);
d1847 2
a1848 2
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
                                     REAL(strlen)(grp->gr_passwd) + 1);
d1851 1
a1851 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
d1853 2
a1854 2
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
                                   (p - grp->gr_mem + 1) * sizeof(*p));
d1857 4
a1860 1
#endif  // SANITIZER_POSIX
d1869 1
a1869 1
  unpoison_passwd(ctx, res);
d1876 1
a1876 1
  unpoison_passwd(ctx, res);
d1884 1
a1884 1
  unpoison_group(ctx, res);
d1891 1
a1891 1
  unpoison_group(ctx, res);
d1913 4
a1916 2
  if (!res && result)
    unpoison_passwd(ctx, *result);
d1928 4
a1931 2
  if (!res && result)
    unpoison_passwd(ctx, *result);
d1944 4
a1947 2
  if (!res && result)
    unpoison_group(ctx, *result);
d1959 4
a1962 2
  if (!res && result)
    unpoison_group(ctx, *result);
d1980 1
a1980 1
  unpoison_passwd(ctx, res);
d1987 1
a1987 1
  unpoison_group(ctx, res);
d2002 1
a2002 1
  unpoison_passwd(ctx, res);
d2009 1
a2009 1
  unpoison_group(ctx, res);
d2028 4
a2031 2
  if (!res && pwbufp)
    unpoison_passwd(ctx, *pwbufp);
d2035 2
a2036 2
INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
            __sanitizer_group **pwbufp) {
d2038 1
a2038 1
  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
d2042 5
a2046 3
  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
  if (!res && pwbufp)
    unpoison_group(ctx, *pwbufp);
d2050 2
a2051 10
#define INIT_GETPWENT_R                   \
  COMMON_INTERCEPT_FUNCTION(getpwent_r);  \
  COMMON_INTERCEPT_FUNCTION(getgrent_r);
#else
#define INIT_GETPWENT_R
#endif

#if SANITIZER_INTERCEPT_FGETPWENT_R
INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
            SIZE_T buflen, __sanitizer_passwd **pwbufp) {
d2053 1
a2053 1
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
d2057 5
a2061 3
  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
  if (!res && pwbufp)
    unpoison_passwd(ctx, *pwbufp);
a2064 7
#define INIT_FGETPWENT_R                  \
  COMMON_INTERCEPT_FUNCTION(fgetpwent_r);
#else
#define INIT_FGETPWENT_R
#endif

#if SANITIZER_INTERCEPT_FGETGRENT_R
d2073 4
a2076 2
  if (!res && pwbufp)
    unpoison_group(ctx, *pwbufp);
d2080 4
a2083 1
#define INIT_FGETGRENT_R                  \
d2086 1
a2086 1
#define INIT_FGETGRENT_R
a2149 2
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_clock_gettime(clk_id, tp);
d3046 1
a3046 1
  if (res >= 0 && msgvec) {
a3052 1
  }
d3183 1
a3183 1
    if (request == ptrace_setregs) {
d3185 1
a3185 1
    } else if (request == ptrace_setfpregs) {
d3187 1
a3187 1
    } else if (request == ptrace_setfpxregs) {
d3189 1
a3189 1
    } else if (request == ptrace_setvfpregs) {
d3191 1
a3191 1
    } else if (request == ptrace_setsiginfo) {
a3192 1

d3196 1
a3196 1
    } else if (request == ptrace_setregset || request == ptrace_getregset) {
d3213 1
a3213 1
    if (request == ptrace_getregs) {
d3215 1
a3215 1
    } else if (request == ptrace_getfpregs) {
d3217 1
a3217 1
    } else if (request == ptrace_getfpxregs) {
d3219 1
a3219 1
    } else if (request == ptrace_getvfpregs) {
d3221 1
a3221 1
    } else if (request == ptrace_getsiginfo) {
d3223 1
a3223 1
    } else if (request == ptrace_geteventmsg) {
d3225 1
a3225 1
    } else if (request == ptrace_getregset) {
d3503 7
a3509 10

  if (!dest)
    return REAL(wcrtomb)(dest, src, ps);

  char local_dest[32];
  SIZE_T res = REAL(wcrtomb)(local_dest, src, ps);
  if (res != ((SIZE_T)-1)) {
    CHECK_LE(res, sizeof(local_dest));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
    REAL(memcpy)(dest, local_dest, res);
a3518 22
#if SANITIZER_INTERCEPT_WCTOMB
INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src);
  if (!dest)
    return REAL(wctomb)(dest, src);

  char local_dest[32];
  int res = REAL(wctomb)(local_dest, src);
  if (res != -1) {
    CHECK_LE(res, sizeof(local_dest));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
    REAL(memcpy)(dest, local_dest, res);
  }
  return res;
}

#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb);
#else
#define INIT_WCTOMB
#endif

a3625 1
  COMMON_INTERCEPTOR_STRERROR();
a4014 19
#if SANITIZER_INTERCEPT_PTHREAD_SIGMASK
INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
            __sanitizer_sigset_t *oldset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
  if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_sigmask)(how, set, oldset);
  if (!res && oldset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
  return res;
}
#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask);
#else
#define INIT_PTHREAD_SIGMASK
#endif

a4254 1
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
d4259 1
a4259 5
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
    if (fd >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
a4692 14
#if SANITIZER_INTERCEPT_TTYNAME
INTERCEPTOR(char *, ttyname, int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
  char *res = REAL(ttyname)(fd);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
  return res;
}
#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
#else
#define INIT_TTYNAME
#endif

a4819 8
#define INIT_REMQUO                   \
  COMMON_INTERCEPT_FUNCTION(remquo);  \
  COMMON_INTERCEPT_FUNCTION(remquof);
#else
#define INIT_REMQUO
#endif

#if SANITIZER_INTERCEPT_REMQUOL
d4830 3
a4832 1
#define INIT_REMQUOL                  \
d4835 1
a4835 1
#define INIT_REMQUOL
a4853 8
#define INIT_LGAMMA                   \
  COMMON_INTERCEPT_FUNCTION(lgamma);  \
  COMMON_INTERCEPT_FUNCTION(lgammaf);
#else
#define INIT_LGAMMA
#endif

#if SANITIZER_INTERCEPT_LGAMMAL
d4861 3
a4863 1
#define INIT_LGAMMAL                  \
d4866 1
a4866 1
#define INIT_LGAMMAL
d5458 1
a5463 10
#if SANITIZER_INTERCEPT_BZERO
INTERCEPTOR(void *, bzero, void *block, uptr size) {
  void *ctx;
  COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
}
#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
#else
#define INIT_BZERO
#endif  // SANITIZER_INTERCEPT_BZERO

a5651 5
#if SANITIZER_NETBSD
  if (fp->_bf._base && fp->_bf._size > 0)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base,
                                        fp->_bf._size);
#else
a5654 1
#endif
a6523 10
INTERCEPTOR(void *, pututxline, const void *ut) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut);
  if (ut)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz);
  void *res = REAL(pututxline)(ut);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz);
  return res;
}
d6527 1
a6527 2
  COMMON_INTERCEPT_FUNCTION(getutxline); \
  COMMON_INTERCEPT_FUNCTION(pututxline);
d6590 1
a6590 1
  return REAL(wcscat)(dst, src);
d6603 1
a6603 1
  return REAL(wcsncat)(dst, src, n);
a6611 17
#if SANITIZER_INTERCEPT_WCSDUP
INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
  SIZE_T len = REAL(wcslen)(s);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
  wchar_t *result = REAL(wcsdup)(s);
  if (result)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(wchar_t) * (len + 1));
  return result;
}

#define INIT_WCSDUP COMMON_INTERCEPT_FUNCTION(wcsdup);
#else
#define INIT_WCSDUP
#endif

d7019 1
a7019 9
#if SANITIZER_NETBSD
#define DEVNAME_R_RETTYPE int
#define DEVNAME_R_SUCCESS(x) (!(x))
#else
#define DEVNAME_R_RETTYPE char*
#define DEVNAME_R_SUCCESS(x) (x)
#endif
INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
            uptr len) {
d7021 1
d7023 2
a7024 2
  DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
  if (DEVNAME_R_SUCCESS(res))
d7236 3
a7238 2235
#if SANITIZER_INTERCEPT_GETMNTINFO
INTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags);
  int cnt = REAL(getmntinfo)(mntbufp, flags);
  if (cnt > 0 && mntbufp) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
    if (*mntbufp)
#if SANITIZER_NETBSD
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz);
#else
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz);
#endif
  }
  return cnt;
}
#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo)
#else
#define INIT_GETMNTINFO
#endif

#if SANITIZER_INTERCEPT_MI_VECTOR_HASH
INTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed,
            u32 hashes[3]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes);
  if (key)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len);
  REAL(mi_vector_hash)(key, len, seed, hashes);
  if (hashes)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3);
}
#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash)
#else
#define INIT_MI_VECTOR_HASH
#endif

#if SANITIZER_INTERCEPT_SETVBUF
INTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode,
  SIZE_T size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size);
  int ret = REAL(setvbuf)(stream, buf, mode, size);
  if (buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
  if (stream)
      unpoison_file(stream);
  return ret;
}

INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf);
  REAL(setbuf)(stream, buf);
  if (buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
  }
  if (stream)
      unpoison_file(stream);
}

INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, int mode) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, mode);
  REAL(setbuffer)(stream, buf, mode);
  if (buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
  }
  if (stream)
    unpoison_file(stream);
}

INTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream);
  REAL(setlinebuf)(stream);
  if (stream)
    unpoison_file(stream);
}
#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \
    COMMON_INTERCEPT_FUNCTION(setbuf); \
    COMMON_INTERCEPT_FUNCTION(setbuffer); \
    COMMON_INTERCEPT_FUNCTION(setlinebuf)
#else
#define INIT_SETVBUF
#endif

#if SANITIZER_INTERCEPT_GETVFSSTAT
INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
  int ret = REAL(getvfsstat)(buf, bufsize, flags);
  if (buf && ret > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz);
  return ret;
}
#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat)
#else
#define INIT_GETVFSSTAT
#endif

#if SANITIZER_INTERCEPT_REGEX
INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
  if (pattern)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1);
  int res = REAL(regcomp)(preg, pattern, cflags);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
  return res;
}
INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
            struct __sanitizer_regmatch *pmatch[], int eflags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  if (string)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1);
  int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
  if (!res && pmatch)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
  return res;
}
INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
            SIZE_T errbuf_size) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
  if (errbuf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1);
  return res;
}
INTERCEPTOR(void, regfree, const void *preg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg);
  if (preg)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
  REAL(regfree)(preg);
}
#define INIT_REGEX                                                             \
  COMMON_INTERCEPT_FUNCTION(regcomp);                                          \
  COMMON_INTERCEPT_FUNCTION(regexec);                                          \
  COMMON_INTERCEPT_FUNCTION(regerror);                                         \
  COMMON_INTERCEPT_FUNCTION(regfree);
#else
#define INIT_REGEX
#endif

#if SANITIZER_INTERCEPT_REGEXSUB
INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
            const struct __sanitizer_regmatch *rm, const char *str) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
  if (sub)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
  // The implementation demands and hardcodes 10 elements
  if (rm)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
  if (str)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
  SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
  if (res > 0 && buf)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
  return res;
}
INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
            const struct __sanitizer_regmatch *rm, const char *sstr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
  if (sub)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
  // Hardcode 10 elements as this is hardcoded size
  if (rm)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
  if (sstr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1);
  SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
  if (res > 0 && buf) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1);
  }
  return res;
}

#define INIT_REGEXSUB                                                          \
  COMMON_INTERCEPT_FUNCTION(regnsub);                                          \
  COMMON_INTERCEPT_FUNCTION(regasub);
#else
#define INIT_REGEXSUB
#endif

#if SANITIZER_INTERCEPT_FTS
INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
            int (*compar)(void **, void **)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar);
  if (path_argv) {
    for (char *const *pa = path_argv; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
    }
  }
  // TODO(kamil): handle compar callback
  void *fts = REAL(fts_open)(path_argv, options, compar);
  if (fts)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz);
  return fts;
}

INTERCEPTOR(void *, fts_read, void *ftsp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  void *ftsent = REAL(fts_read)(ftsp);
  if (ftsent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
  return ftsent;
}

INTERCEPTOR(void *, fts_children, void *ftsp, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  void *ftsent = REAL(fts_children)(ftsp, options);
  if (ftsent)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
  return ftsent;
}

INTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  if (f)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz);
  return REAL(fts_set)(ftsp, f, options);
}

INTERCEPTOR(int, fts_close, void *ftsp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp);
  if (ftsp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
  return REAL(fts_close)(ftsp);
}
#define INIT_FTS                                                               \
  COMMON_INTERCEPT_FUNCTION(fts_open);                                         \
  COMMON_INTERCEPT_FUNCTION(fts_read);                                         \
  COMMON_INTERCEPT_FUNCTION(fts_children);                                     \
  COMMON_INTERCEPT_FUNCTION(fts_set);                                          \
  COMMON_INTERCEPT_FUNCTION(fts_close);
#else
#define INIT_FTS
#endif

#if SANITIZER_INTERCEPT_SYSCTL
INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
            SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
  COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
                           newlen);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
  if (oldlenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
  if (newp && newlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
  int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
  if (!res) {
    if (oldlenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
      if (oldp)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
    }
  }
  return res;
}

INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
            void *newp, SIZE_T newlen) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen);
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
                           newlen);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  if (oldlenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
  if (newp && newlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
  int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
  if (!res) {
    if (oldlenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
      if (oldp)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
    }
  }
  return res;
}

INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
            SIZE_T *namelenp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  if (namelenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
  int res = REAL(sysctlnametomib)(sname, name, namelenp);
  if (!res) {
    if (namelenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
      if (name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
    }
  }
  return res;
}

#define INIT_SYSCTL                        \
  COMMON_INTERCEPT_FUNCTION(sysctl);       \
  COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
  COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
#else
#define INIT_SYSCTL
#endif

#if SANITIZER_INTERCEPT_ASYSCTL
INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
  void *res = REAL(asysctl)(name, namelen, len);
  if (res && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
  }
  return res;
}

INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  void *res = REAL(asysctlbyname)(sname, len);
  if (res && len) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
  }
  return res;
}
#define INIT_ASYSCTL                           \
  COMMON_INTERCEPT_FUNCTION(asysctl);          \
  COMMON_INTERCEPT_FUNCTION(asysctlbyname);
#else
#define INIT_ASYSCTL
#endif

#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
            unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
            int v) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
                           csz, rnode, v);
  if (sname)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
  if (namelenp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
  if (csz)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
  // Skip rnode, it's rarely used and not trivial to sanitize
  // It's also used mostly internally
  int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
  if (!res) {
    if (namelenp) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
      if (name)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
    }
    if (csz) {
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
      if (cname)
        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
    }
  }
  return res;
}
#define INIT_SYSCTLGETMIBINFO                  \
  COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
#else
#define INIT_SYSCTLGETMIBINFO
#endif

#if SANITIZER_INTERCEPT_NL_LANGINFO
INTERCEPTOR(char *, nl_langinfo, long item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
  char *ret = REAL(nl_langinfo)(item);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
  return ret;
}
#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
#else
#define INIT_NL_LANGINFO
#endif

#if SANITIZER_INTERCEPT_MODCTL
INTERCEPTOR(int, modctl, int operation, void *argp) {
  void *ctx;
  int ret;
  COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp);

  if (operation == modctl_load) {
    if (argp) {
      __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
      if (ml->ml_filename)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
                                      REAL(strlen)(ml->ml_filename) + 1);
      if (ml->ml_props)
        COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
    }
    ret = REAL(modctl)(operation, argp);
  } else if (operation == modctl_unload) {
    if (argp) {
      const char *name = (const char *)argp;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
    }
    ret = REAL(modctl)(operation, argp);
  } else if (operation == modctl_stat) {
    uptr iov_len;
    struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp;
    if (iov) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov));
      iov_len = iov->iov_len;
    }
    ret = REAL(modctl)(operation, argp);
    if (iov)
      COMMON_INTERCEPTOR_WRITE_RANGE(
          ctx, iov->iov_base, Min(iov_len,  iov->iov_len));
  } else if (operation == modctl_exists) {
    ret = REAL(modctl)(operation, argp);
  } else {
    ret = REAL(modctl)(operation, argp);
  }

  return ret;
}
#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl)
#else
#define INIT_MODCTL
#endif

#if SANITIZER_INTERCEPT_STRTONUM
INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
            long long maxval, const char **errstr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);

  // TODO(kamil): Implement strtoll as a common inteceptor
  char *real_endptr;
  long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
  StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);

  ret = REAL(strtonum)(nptr, minval, maxval, errstr);
  if (errstr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
     if (*errstr)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
  }
  return ret;
}
#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
#else
#define INIT_STRTONUM
#endif

#if SANITIZER_INTERCEPT_FPARSELN
INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
            SIZE_T *lineno, const char delim[3], int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags);
  if (lineno)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno));
  if (delim)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
  char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
  if (ret) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
    if (len)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
    if (lineno)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno));
  }
  return ret;
}
#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln)
#else
#define INIT_FPARSELN
#endif

#if SANITIZER_INTERCEPT_STATVFS1
INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  int res = REAL(statvfs1)(path, buf, flags);
  if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
  return res;
}
INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  int res = REAL(fstatvfs1)(fd, buf, flags);
  if (!res) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
    if (fd >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return res;
}
#define INIT_STATVFS1                  \
  COMMON_INTERCEPT_FUNCTION(statvfs1);  \
  COMMON_INTERCEPT_FUNCTION(fstatvfs1);
#else
#define INIT_STATVFS1
#endif

#if SANITIZER_INTERCEPT_STRTOI
INTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base,
            INTMAX_T low, INTMAX_T high, int *rstatus) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus);
  char *real_endptr;
  INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  if (rstatus)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
  return ret;
}

INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base,
            UINTMAX_T low, UINTMAX_T high, int *rstatus) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus);
  char *real_endptr;
  UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus);
  StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
  if (rstatus)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
  return ret;
}
#define INIT_STRTOI                                                            \
  COMMON_INTERCEPT_FUNCTION(strtoi);                                           \
  COMMON_INTERCEPT_FUNCTION(strtou)
#else
#define INIT_STRTOI
#endif

#if SANITIZER_INTERCEPT_CAPSICUM
#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...)          \
  {                                                                        \
    void *ctx;                                                             \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \
    if (rights)                                                            \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));         \
    __sanitizer_cap_rights_t *ret =                                        \
        REAL(cap_rights_init)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                               \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));              \
    return ret;                                                            \
  }

#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...)           \
  {                                                                       \
    void *ctx;                                                            \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \
    if (rights)                                                           \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));        \
    __sanitizer_cap_rights_t *ret =                                       \
        REAL(cap_rights_set)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                              \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));             \
    return ret;                                                           \
  }

#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...)         \
  {                                                                         \
    void *ctx;                                                              \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \
    if (rights)                                                             \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));          \
    __sanitizer_cap_rights_t *ret =                                         \
        REAL(cap_rights_clear)(rights, ##__VA_ARGS__);                      \
    if (ret)                                                                \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));               \
    return ret;                                                             \
  }

#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...)        \
  {                                                                          \
    void *ctx;                                                               \
    COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \
    if (rights)                                                              \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));           \
    return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__);                   \
  }

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights);
}

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights);
}

INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights);
}

INTERCEPTOR(bool, cap_rights_is_set,
            __sanitizer_cap_rights_t *rights) {
  CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights);
}

INTERCEPTOR(int, cap_rights_limit, int fd,
            const __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights);
  if (rights)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));

  return REAL(cap_rights_limit)(fd, rights);
}

INTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights);
  int ret = REAL(cap_rights_get)(fd, rights);
  if (!ret && rights)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights));

  return ret;
}

INTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights);
  if (rights)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));

  return REAL(cap_rights_is_valid(rights));
}

INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge,
  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));

  __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));

  return ret;
}

INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove,
  __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));

  __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));

  return ret;
}

INTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big,
  const __sanitizer_cap_rights *little) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little);
  if (little)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little));
  if (big)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big));

  return REAL(cap_rights_contains)(big, little);
}

INTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds);
  if (cmds)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds);

  return REAL(cap_ioctls_limit)(fd, cmds, ncmds);
}

INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds);
  int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds);
  if (!ret && cmds)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds);

  return ret;
}
#define INIT_CAPSICUM                          \
  COMMON_INTERCEPT_FUNCTION(cap_rights_init); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_set); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_get);   \
  COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \
  COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \
  COMMON_INTERCEPT_FUNCTION(cap_ioctls_get);   \
  COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit)
#else
#define INIT_CAPSICUM
#endif

#if SANITIZER_INTERCEPT_SHA1
INTERCEPTOR(void, SHA1Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context);
  REAL(SHA1Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
}
INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  REAL(SHA1Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
}
INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  REAL(SHA1Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
}
INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer);
  if (state)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
  if (buffer)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64);
  REAL(SHA1Transform)(state, buffer);
  if (state)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
}
INTERCEPTOR(char *, SHA1End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
  char *ret = REAL(SHA1End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(SHA1File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
  OFF_T length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf);
  if (data)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(SHA1Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
  return ret;
}
#define INIT_SHA1                                                              \
  COMMON_INTERCEPT_FUNCTION(SHA1Init);                                         \
  COMMON_INTERCEPT_FUNCTION(SHA1Update);                                       \
  COMMON_INTERCEPT_FUNCTION(SHA1Final);                                        \
  COMMON_INTERCEPT_FUNCTION(SHA1Transform);                                    \
  COMMON_INTERCEPT_FUNCTION(SHA1End);                                          \
  COMMON_INTERCEPT_FUNCTION(SHA1File);                                         \
  COMMON_INTERCEPT_FUNCTION(SHA1FileChunk);                                    \
  COMMON_INTERCEPT_FUNCTION(SHA1Data)
#else
#define INIT_SHA1
#endif

#if SANITIZER_INTERCEPT_MD4
INTERCEPTOR(void, MD4Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context);
  REAL(MD4Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
}

INTERCEPTOR(void, MD4Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  REAL(MD4Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
}

INTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  REAL(MD4Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD4End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
  char *ret = REAL(MD4End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(MD4File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

INTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD4Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
  return ret;
}

#define INIT_MD4                                                               \
  COMMON_INTERCEPT_FUNCTION(MD4Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD4Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD4Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD4End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD4File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD4Data)
#else
#define INIT_MD4
#endif

#if SANITIZER_INTERCEPT_RMD160
INTERCEPTOR(void, RMD160Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context);
  REAL(RMD160Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
}
INTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  REAL(RMD160Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
}
INTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  REAL(RMD160Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
}
INTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer);
  if (state)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
  if (buffer)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16);
  REAL(RMD160Transform)(state, buffer);
  if (state)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
}
INTERCEPTOR(char *, RMD160End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
  char *ret = REAL(RMD160End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(RMD160File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
  OFF_T length) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(RMD160Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
  return ret;
}
#define INIT_RMD160                                                            \
  COMMON_INTERCEPT_FUNCTION(RMD160Init);                                       \
  COMMON_INTERCEPT_FUNCTION(RMD160Update);                                     \
  COMMON_INTERCEPT_FUNCTION(RMD160Final);                                      \
  COMMON_INTERCEPT_FUNCTION(RMD160Transform);                                  \
  COMMON_INTERCEPT_FUNCTION(RMD160End);                                        \
  COMMON_INTERCEPT_FUNCTION(RMD160File);                                       \
  COMMON_INTERCEPT_FUNCTION(RMD160FileChunk);                                  \
  COMMON_INTERCEPT_FUNCTION(RMD160Data)
#else
#define INIT_RMD160
#endif

#if SANITIZER_INTERCEPT_MD5
INTERCEPTOR(void, MD5Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
  REAL(MD5Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
}

INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  REAL(MD5Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
}

INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  REAL(MD5Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD5End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
  char *ret = REAL(MD5End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(MD5File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD5Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
  return ret;
}

#define INIT_MD5                                                               \
  COMMON_INTERCEPT_FUNCTION(MD5Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD5Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD5Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD5End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD5File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD5Data)
#else
#define INIT_MD5
#endif

#if SANITIZER_INTERCEPT_FSEEK
INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence);
  return REAL(fseek)(stream, offset, whence);
}
INTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence);
  return REAL(fseeko)(stream, offset, whence);
}
INTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream);
  return REAL(ftell)(stream);
}
INTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream);
  return REAL(ftello)(stream);
}
INTERCEPTOR(void, rewind, __sanitizer_FILE *stream) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream);
  return REAL(rewind)(stream);
}
INTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos);
  int ret = REAL(fgetpos)(stream, pos);
  if (pos && !ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz);
  return ret;
}
INTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos);
  if (pos)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz);
  return REAL(fsetpos)(stream, pos);
}
#define INIT_FSEEK \
  COMMON_INTERCEPT_FUNCTION(fseek); \
  COMMON_INTERCEPT_FUNCTION(fseeko); \
  COMMON_INTERCEPT_FUNCTION(ftell); \
  COMMON_INTERCEPT_FUNCTION(ftello); \
  COMMON_INTERCEPT_FUNCTION(rewind); \
  COMMON_INTERCEPT_FUNCTION(fgetpos); \
  COMMON_INTERCEPT_FUNCTION(fsetpos)
#else
#define INIT_FSEEK
#endif

#if SANITIZER_INTERCEPT_MD2
INTERCEPTOR(void, MD2Init, void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context);
  REAL(MD2Init)(context);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
}

INTERCEPTOR(void, MD2Update, void *context, const unsigned char *data,
            unsigned int len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  REAL(MD2Update)(context, data, len);
  if (context)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
}

INTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  REAL(MD2Final)(digest, context);
  if (digest)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
}

INTERCEPTOR(char *, MD2End, void *context, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf);
  if (context)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
  char *ret = REAL(MD2End)(context, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
  if (filename)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
  char *ret = REAL(MD2File)(filename, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
            char *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf);
  if (data && len > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
  char *ret = REAL(MD2Data)(data, len, buf);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
  return ret;
}

#define INIT_MD2                                                               \
  COMMON_INTERCEPT_FUNCTION(MD2Init);                                          \
  COMMON_INTERCEPT_FUNCTION(MD2Update);                                        \
  COMMON_INTERCEPT_FUNCTION(MD2Final);                                         \
  COMMON_INTERCEPT_FUNCTION(MD2End);                                           \
  COMMON_INTERCEPT_FUNCTION(MD2File);                                          \
  COMMON_INTERCEPT_FUNCTION(MD2Data)
#else
#define INIT_MD2
#endif

#if SANITIZER_INTERCEPT_SHA2
#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
  INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
    REAL(SHA##LEN##_Init)(context); \
    if (context) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
  } \
  INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
              const u8 *data, SIZE_T len) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
    if (data && len > 0) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    REAL(SHA##LEN##_Update)(context, data, len); \
    if (context) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
  } \
  INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
  void *context) { \
    void *ctx; \
    CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    REAL(SHA##LEN##_Final)(digest, context); \
    if (digest) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
                                     sizeof(digest[0]) * \
  SHA##LEN##_digest_length); \
  } \
  INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
    if (context) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
    char *ret = REAL(SHA##LEN##_End)(context, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
    if (filename) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
    char *ret = REAL(SHA##LEN##_File)(filename, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
              OFF_T offset, OFF_T length) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
  length); \
    if (filename) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
    char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  } \
  INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
    void *ctx; \
    COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
    if (data && len > 0) \
      COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
    char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
    if (ret) \
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
    return ret; \
  }

SHA2_INTERCEPTORS(224, u32);
SHA2_INTERCEPTORS(256, u32);
SHA2_INTERCEPTORS(384, u64);
SHA2_INTERCEPTORS(512, u64);

#define INIT_SHA2_INTECEPTORS(LEN) \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
  COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)

#define INIT_SHA2 \
  INIT_SHA2_INTECEPTORS(224); \
  INIT_SHA2_INTECEPTORS(256); \
  INIT_SHA2_INTECEPTORS(384); \
  INIT_SHA2_INTECEPTORS(512)
#undef SHA2_INTERCEPTORS
#else
#define INIT_SHA2
#endif

#if SANITIZER_INTERCEPT_VIS
INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
  char *end = REAL(vis)(dst, c, flag, nextc);
  // dst is NULL terminated and end points to the NULL char
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
  char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
  // nvis cannot make sure the dst is NULL terminated
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int len = REAL(strvis)(dst, src, flag);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int len = REAL(stravis)(dst, src, flag);
  if (dst) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
    if (*dst)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
  }
  return len;
}
INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int len = REAL(strnvis)(dst, dlen, src, flag);
  // The interface will be valid even if there is no space for NULL char
  if (dst && len > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  int ret = REAL(strvisx)(dst, src, len, flag);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag, int *cerr_ptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
  // according to the implementation
  if (cerr_ptr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
  int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  if (cerr_ptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
  return ret;
}
INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  char *end = REAL(svis)(dst, c, flag, nextc, extra);
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
  return end;
}
INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
  if (dst && end)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
                                   Min((SIZE_T)(end - dst + 1), dlen));
  return end;
}
INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int len = REAL(strsvis)(dst, src, flag, extra);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
  // The interface will be valid even if there is no space for NULL char
  if (dst && len >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
  return len;
}
INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
            const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int ret = REAL(strsvisx)(dst, src, len, flag, extra);
  if (dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
            int flag, const char *extra) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
            SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
                           cerr_ptr);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
  if (extra)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
  // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
  // according to the implementation
  if (cerr_ptr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
  int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
  if (dst && ret >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  if (cerr_ptr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
  return ret;
}
INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
  if (astate)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
  int ret = REAL(unvis)(cp, c, astate, flag);
  if (ret == unvis_valid || ret == unvis_validpush) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
  }
  return ret;
}
INTERCEPTOR(int, strunvis, char *dst, const char *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strunvis)(dst, src);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strnunvis)(dst, dlen, src);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strunvisx)(dst, src, flag);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
            int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
  if (src)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
  int ret = REAL(strnunvisx)(dst, dlen, src, flag);
  if (ret != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
  return ret;
}
#define INIT_VIS                                                               \
  COMMON_INTERCEPT_FUNCTION(vis);                                              \
  COMMON_INTERCEPT_FUNCTION(nvis);                                             \
  COMMON_INTERCEPT_FUNCTION(strvis);                                           \
  COMMON_INTERCEPT_FUNCTION(stravis);                                          \
  COMMON_INTERCEPT_FUNCTION(strnvis);                                          \
  COMMON_INTERCEPT_FUNCTION(strvisx);                                          \
  COMMON_INTERCEPT_FUNCTION(strnvisx);                                         \
  COMMON_INTERCEPT_FUNCTION(strenvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(svis);                                             \
  COMMON_INTERCEPT_FUNCTION(snvis);                                            \
  COMMON_INTERCEPT_FUNCTION(strsvis);                                          \
  COMMON_INTERCEPT_FUNCTION(strsnvis);                                         \
  COMMON_INTERCEPT_FUNCTION(strsvisx);                                         \
  COMMON_INTERCEPT_FUNCTION(strsnvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(strsenvisx);                                       \
  COMMON_INTERCEPT_FUNCTION(unvis);                                            \
  COMMON_INTERCEPT_FUNCTION(strunvis);                                         \
  COMMON_INTERCEPT_FUNCTION(strnunvis);                                        \
  COMMON_INTERCEPT_FUNCTION(strunvisx);                                        \
  COMMON_INTERCEPT_FUNCTION(strnunvisx)
#else
#define INIT_VIS
#endif

#if SANITIZER_INTERCEPT_CDB
INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
  if (cdbr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
  return cdbr;
}

INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
  int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
    cookie);
  if (base && size)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
  struct __sanitizer_cdbr *cdbr =
    REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
  if (cdbr)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
  return cdbr;
}

INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  return REAL(cdbr_entries)(cdbr);
}

INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
            const void **data, SIZE_T *datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
  if (!ret) {
    if (data)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
    if (datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
    if (data && datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
  }
  return ret;
}

INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
            SIZE_T keylen, const void **data, SIZE_T *datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  if (key)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
  if (!ret) {
    if (data)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
    if (datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
    if (data && datalen)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
  }
  return ret;
}

INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
  if (cdbr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
  REAL(cdbr_close)(cdbr);
}

INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
  struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
  return ret;
}

INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
  SIZE_T keylen, const void *data, SIZE_T datalen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (data && datalen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
  if (key && keylen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
  if (!ret && cdbw)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  return ret;
}

INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
  SIZE_T datalen, u32 *index) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (data && datalen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
  int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
  if (!ret) {
    if (index)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
    if (cdbw)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  }
  return ret;
}

INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
  SIZE_T keylen, u32 index) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (key && keylen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
  int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
  if (!ret && cdbw)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
  return ret;
}

INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
  const char descr[16], u32 (*seedgen)(void)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  if (descr)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
  if (seedgen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
  int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
  if (!ret) {
    if (cdbw)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
    if (output >= 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
  }
  return ret;
}

INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
  if (cdbw)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
  REAL(cdbw_close)(cdbw);
}

#define INIT_CDB \
  COMMON_INTERCEPT_FUNCTION(cdbr_open); \
  COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
  COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
  COMMON_INTERCEPT_FUNCTION(cdbr_get); \
  COMMON_INTERCEPT_FUNCTION(cdbr_find); \
  COMMON_INTERCEPT_FUNCTION(cdbr_close); \
  COMMON_INTERCEPT_FUNCTION(cdbw_open); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
  COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
  COMMON_INTERCEPT_FUNCTION(cdbw_output); \
  COMMON_INTERCEPT_FUNCTION(cdbw_close)
#else
#define INIT_CDB
#endif

#if SANITIZER_INTERCEPT_GETFSENT
INTERCEPTOR(void *, getfsent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsent);
  void *ret = REAL(getfsent)();
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

INTERCEPTOR(void *, getfsspec, const char *spec) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
  if (spec)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1);
  void *ret = REAL(getfsspec)(spec);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

INTERCEPTOR(void *, getfsfile, const char *file) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
  if (file)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
  void *ret = REAL(getfsfile)(file);
  if (ret)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
  return ret;
}

#define INIT_GETFSENT \
  COMMON_INTERCEPT_FUNCTION(getfsent); \
  COMMON_INTERCEPT_FUNCTION(getfsspec); \
  COMMON_INTERCEPT_FUNCTION(getfsfile);
#else
#define INIT_GETFSENT
#endif

#if SANITIZER_INTERCEPT_ARC4RANDOM
INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len);
  REAL(arc4random_buf)(buf, len);
  if (buf && len)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len);
}

INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen);
  if (dat && datlen)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen);
  REAL(arc4random_addrandom)(dat, datlen);
}

#define INIT_ARC4RANDOM \
  COMMON_INTERCEPT_FUNCTION(arc4random_buf); \
  COMMON_INTERCEPT_FUNCTION(arc4random_addrandom);
#else
#define INIT_ARC4RANDOM
#endif

#if SANITIZER_INTERCEPT_POPEN
INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
  if (command)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
  if (type)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
  __sanitizer_FILE *res = REAL(popen)(command, type);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
#else
#define INIT_POPEN
#endif

#if SANITIZER_INTERCEPT_POPENVE
INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
            char *const *argv, char *const *envp, const char *type) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
  if (path)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
  if (argv) {
    for (char *const *pa = argv; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
    }
  }
  if (envp) {
    for (char *const *pa = envp; ; ++pa) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
      if (!*pa)
        break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
    }
  }
  if (type)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
  __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
  COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
  if (res) unpoison_file(res);
  return res;
}
#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
#else
#define INIT_POPENVE
#endif

#if SANITIZER_INTERCEPT_PCLOSE
INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
  COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
  const FileMetadata *m = GetInterceptorMetadata(fp);
  int res = REAL(pclose)(fp);
  if (m) {
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
    DeleteInterceptorMetadata(fp);
  }
  return res;
}
#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
#else
#define INIT_PCLOSE
#endif

#if SANITIZER_INTERCEPT_FUNOPEN
typedef int (*funopen_readfn)(void *cookie, char *buf, int len);
typedef int (*funopen_writefn)(void *cookie, const char *buf, int len);
typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence);
typedef int (*funopen_closefn)(void *cookie);

struct WrappedFunopenCookie {
  void *real_cookie;
  funopen_readfn real_read;
  funopen_writefn real_write;
  funopen_seekfn real_seek;
  funopen_closefn real_close;
};

static int wrapped_funopen_read(void *cookie, char *buf, int len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_readfn real_read = wrapped_cookie->real_read;
  return real_read(wrapped_cookie->real_cookie, buf, len);
}

static int wrapped_funopen_write(void *cookie, const char *buf, int len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_writefn real_write = wrapped_cookie->real_write;
  return real_write(wrapped_cookie->real_cookie, buf, len);
}

static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_seekfn real_seek = wrapped_cookie->real_seek;
  return real_seek(wrapped_cookie->real_cookie, offset, whence);
}

static int wrapped_funopen_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
  funopen_closefn real_close = wrapped_cookie->real_close;
  int res = real_close(wrapped_cookie->real_cookie);
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn,
            funopen_writefn writefn, funopen_seekfn seekfn,
            funopen_closefn closefn) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn,
                           closefn);

  WrappedFunopenCookie *wrapped_cookie =
      (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_read = readfn;
  wrapped_cookie->real_write = writefn;
  wrapped_cookie->real_seek = seekfn;
  wrapped_cookie->real_close = closefn;

  __sanitizer_FILE *res =
      REAL(funopen)(wrapped_cookie,
                    readfn  ? wrapped_funopen_read  : nullptr,
                    writefn ? wrapped_funopen_write : nullptr,
                    seekfn  ? wrapped_funopen_seek  : nullptr,
                    closefn ? wrapped_funopen_close : nullptr);
  if (res)
    unpoison_file(res);
  return res;
}
#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen)
#else
#define INIT_FUNOPEN
#endif

#if SANITIZER_INTERCEPT_FUNOPEN2
typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len);
typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len);
typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence);
typedef int (*funopen2_flushfn)(void *cookie);
typedef int (*funopen2_closefn)(void *cookie);

struct WrappedFunopen2Cookie {
  void *real_cookie;
  funopen2_readfn real_read;
  funopen2_writefn real_write;
  funopen2_seekfn real_seek;
  funopen2_flushfn real_flush;
  funopen2_closefn real_close;
};

static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_readfn real_read = wrapped_cookie->real_read;
  return real_read(wrapped_cookie->real_cookie, buf, len);
}

static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf,
                                      SIZE_T len) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_writefn real_write = wrapped_cookie->real_write;
  return real_write(wrapped_cookie->real_cookie, buf, len);
}

static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_seekfn real_seek = wrapped_cookie->real_seek;
  return real_seek(wrapped_cookie->real_cookie, offset, whence);
}

static int wrapped_funopen2_flush(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_flushfn real_flush = wrapped_cookie->real_flush;
  return real_flush(wrapped_cookie->real_cookie);
}

static int wrapped_funopen2_close(void *cookie) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
  WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
  funopen2_closefn real_close = wrapped_cookie->real_close;
  int res = real_close(wrapped_cookie->real_cookie);
  InternalFree(wrapped_cookie);
  return res;
}

INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn,
            funopen2_writefn writefn, funopen2_seekfn seekfn,
            funopen2_flushfn flushfn, funopen2_closefn closefn) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn,
                           flushfn, closefn);

  WrappedFunopen2Cookie *wrapped_cookie =
      (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie));
  wrapped_cookie->real_cookie = cookie;
  wrapped_cookie->real_read = readfn;
  wrapped_cookie->real_write = writefn;
  wrapped_cookie->real_seek = seekfn;
  wrapped_cookie->real_flush = flushfn;
  wrapped_cookie->real_close = closefn;

  __sanitizer_FILE *res =
      REAL(funopen2)(wrapped_cookie,
                     readfn  ? wrapped_funopen2_read  : nullptr,
                     writefn ? wrapped_funopen2_write : nullptr,
                     seekfn  ? wrapped_funopen2_seek  : nullptr,
                     flushfn ? wrapped_funopen2_flush : nullptr,
                     closefn ? wrapped_funopen2_close : nullptr);
  if (res)
    unpoison_file(res);
  return res;
}
#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2)
#else
#define INIT_FUNOPEN2
#endif

#if SANITIZER_INTERCEPT_FDEVNAME
INTERCEPTOR(char *, fdevname,  int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  char *name = REAL(fdevname)(fd);
  if (name) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
    if (fd > 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return name;
}

INTERCEPTOR(char *, fdevname_r,  int fd, char *buf, SIZE_T len) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len);
  COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
  char *name = REAL(fdevname_r)(fd, buf, len);
  if (name && buf && len > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
    if (fd > 0)
      COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  }
  return name;
}

#define INIT_FDEVNAME \
  COMMON_INTERCEPT_FUNCTION(fdevname); \
  COMMON_INTERCEPT_FUNCTION(fdevname_r);
#else
#define INIT_FDEVNAME
#endif

#if SANITIZER_INTERCEPT_GETUSERSHELL
INTERCEPTOR(char *, getusershell) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
  char *res = REAL(getusershell)();
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}

#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell);
#else
#define INIT_GETUSERSHELL
#endif

#if SANITIZER_INTERCEPT_SL_INIT
INTERCEPTOR(void *, sl_init) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_init);
  void *res = REAL(sl_init)();
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz);
  return res;
}

INTERCEPTOR(int, sl_add, void *sl, char *item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  if (item)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
  int res = REAL(sl_add)(sl, item);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  return res;
}

INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  if (item)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
  char *res = REAL(sl_find)(sl, item);
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  return res;
}

INTERCEPTOR(void, sl_free, void *sl, int freeall) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall);
  if (sl)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
  REAL(sl_free)(sl, freeall);
}

#define INIT_SL_INIT                  \
  COMMON_INTERCEPT_FUNCTION(sl_init); \
  COMMON_INTERCEPT_FUNCTION(sl_add);  \
  COMMON_INTERCEPT_FUNCTION(sl_find); \
  COMMON_INTERCEPT_FUNCTION(sl_free);
#else
#define INIT_SL_INIT
#endif

#if SANITIZER_INTERCEPT_GETRANDOM
INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
  SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
  if (n > 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
  }
  return n;
}
#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom)
#else
#define INIT_GETRANDOM
#endif

#if SANITIZER_INTERCEPT_CRYPT
INTERCEPTOR(char *, crypt, char *key, char *salt) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
  char *res = REAL(crypt)(key, salt);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
#else
#define INIT_CRYPT
#endif

#if SANITIZER_INTERCEPT_CRYPT_R
INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
  char *res = REAL(crypt_r)(key, salt, data);
  if (res != nullptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
                                   __sanitizer::struct_crypt_data_sz);
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  }
  return res;
}
#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
#else
#define INIT_CRYPT_R
#endif

#if SANITIZER_INTERCEPT_GETENTROPY
INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
  int r = REAL(getentropy)(buf, buflen);
  if (r == 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
  }
  return r;
}
#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
#else
#define INIT_GETENTROPY
#endif

static void InitializeCommonInterceptors() {
#if SI_POSIX
  static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
  interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
#endif
a7265 1
  INIT_BCMP;
a7299 2
  INIT_FGETPWENT_R;
  INIT_FGETGRENT_R;
a7343 1
  INIT_WCTOMB;
a7364 1
  INIT_PTHREAD_SIGMASK;
a7402 1
  INIT_TTYNAME;
a7408 1
  INIT_REMQUOL;
a7409 1
  INIT_LGAMMAL;
a7425 1
  INIT_BZERO;
a7461 1
  INIT_WCSDUP;
a7484 40
  INIT_GETMNTINFO;
  INIT_MI_VECTOR_HASH;
  INIT_SETVBUF;
  INIT_GETVFSSTAT;
  INIT_REGEX;
  INIT_REGEXSUB;
  INIT_FTS;
  INIT_SYSCTL;
  INIT_ASYSCTL;
  INIT_SYSCTLGETMIBINFO;
  INIT_NL_LANGINFO;
  INIT_MODCTL;
  INIT_STRTONUM;
  INIT_FPARSELN;
  INIT_STATVFS1;
  INIT_STRTOI;
  INIT_CAPSICUM;
  INIT_SHA1;
  INIT_MD4;
  INIT_RMD160;
  INIT_MD5;
  INIT_FSEEK;
  INIT_MD2;
  INIT_SHA2;
  INIT_VIS;
  INIT_CDB;
  INIT_GETFSENT;
  INIT_ARC4RANDOM;
  INIT_POPEN;
  INIT_POPENVE;
  INIT_PCLOSE;
  INIT_FUNOPEN;
  INIT_FUNOPEN2;
  INIT_FDEVNAME;
  INIT_GETUSERSHELL;
  INIT_SL_INIT;
  INIT_GETRANDOM;
  INIT_CRYPT;
  INIT_CRYPT_R;
  INIT_GETENTROPY;
@


1.1.1.11
log
@initial import of GCC 12.3.0.

major changes in GCC 11 included:

- The default mode for C++ is now -std=gnu++17 instead of -std=gnu++14.
- When building GCC itself, the host compiler must now support C++11,
  rather than C++98.
- Some short options of the gcov tool have been renamed: -i to -j and
  -j to -H.
- ThreadSanitizer improvements.
- Introduce Hardware-assisted AddressSanitizer support.
- For targets that produce DWARF debugging information GCC now defaults
  to DWARF version 5. This can produce up to 25% more compact debug
  information compared to earlier versions.
- Many optimisations.
- The existing malloc attribute has been extended so that it can be
  used to identify allocator/deallocator API pairs. A pair of new
  -Wmismatched-dealloc and -Wmismatched-new-delete warnings are added.
- Other new warnings:
  -Wsizeof-array-div, enabled by -Wall, warns about divisions of two
    sizeof operators when the first one is applied to an array and the
    divisor does not equal the size of the array element.
  -Wstringop-overread, enabled by default, warns about calls to string
    functions reading past the end of the arrays passed to them as
    arguments.
  -Wtsan, enabled by default, warns about unsupported features in
    ThreadSanitizer (currently std::atomic_thread_fence).
- Enchanced warnings:
  -Wfree-nonheap-object detects many more instances of calls to
    deallocation functions with pointers not returned from a dynamic
    memory allocation function.
  -Wmaybe-uninitialized diagnoses passing pointers or references to
    uninitialized memory to functions taking const-qualified arguments.
  -Wuninitialized detects reads from uninitialized dynamically
    allocated memory.
  -Warray-parameter warns about functions with inconsistent array forms.
  -Wvla-parameter warns about functions with inconsistent VLA forms.
- Several new features from the upcoming C2X revision of the ISO C
  standard are supported with -std=c2x and -std=gnu2x.
- Several C++20 features have been implemented.
- The C++ front end has experimental support for some of the upcoming
  C++23 draft.
- Several new C++ warnings.
- Enhanced Arm, AArch64, x86, and RISC-V CPU support.
- The implementation of how program state is tracked within
  -fanalyzer has been completely rewritten with many enhancements.

see https://gcc.gnu.org/gcc-11/changes.html for a full list.

major changes in GCC 12 include:

- An ABI incompatibility between C and C++ when passing or returning
  by value certain aggregates containing zero width bit-fields has
  been discovered on various targets. x86-64, ARM and AArch64
  will always ignore them (so there is a C ABI incompatibility
  between GCC 11 and earlier with GCC 12 or later), PowerPC64 ELFv2
  always take them into account (so there is a C++ ABI
  incompatibility, GCC 4.4 and earlier compatible with GCC 12 or
  later, incompatible with GCC 4.5 through GCC 11). RISC-V has
  changed the handling of these already starting with GCC 10. As
  the ABI requires, MIPS takes them into account handling function
  return values so there is a C++ ABI incompatibility with GCC 4.5
  through 11.
- STABS: Support for emitting the STABS debugging format is
  deprecated and will be removed in the next release. All ports now
  default to emit DWARF (version 2 or later) debugging info or are
  obsoleted.
- Vectorization is enabled at -O2 which is now equivalent to the
  original -O2 -ftree-vectorize -fvect-cost-model=very-cheap.
- GCC now supports the ShadowCallStack sanitizer.
- Support for __builtin_shufflevector compatible with the clang
  language extension was added.
- Support for attribute unavailable was added.
- Support for __builtin_dynamic_object_size compatible with the
  clang language extension was added.
- New warnings:
  -Wbidi-chars warns about potentially misleading UTF-8
    bidirectional control characters.
  -Warray-compare warns about comparisons between two operands of
    array type.
- Some new features from the upcoming C2X revision of the ISO C
  standard are supported with -std=c2x and -std=gnu2x.
- Several C++23 features have been implemented.
- Many C++ enhancements across warnings and -f options.

see https://gcc.gnu.org/gcc-12/changes.html for a full list.
@
text
@a81 2
#define fstatvfs __fstatvfs90
#define fstatvfs1 __fstatvfs190
d88 1
a88 1
#define getmntinfo __getmntinfo90
a97 1
#define getvfsstat __getvfsstat90
a112 1
#define sigaltstack __sigaltstack14
a118 2
#define statvfs __statvfs90
#define statvfs1 __statvfs190
d131 5
a135 1
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
d137 1
a137 1
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
d139 1
a139 1
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
d205 1
a205 1
      common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )
a239 17
#if SANITIZER_GLIBC
// If we could not find the versioned symbol, fall back to an unversioned
// lookup. This is needed to work around a GLibc bug that causes dlsym
// with RTLD_NEXT to return the oldest versioned symbol.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=14932.
// For certain symbols (e.g. regexec) we have to perform a versioned lookup,
// but that versioned symbol will only exist for architectures where the
// oldest Glibc version pre-dates support for that architecture.
// For example, regexec@@GLIBC_2.3.4 exists on x86_64, but not RISC-V.
// See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920.
#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
  COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver)
#else
#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
  COMMON_INTERCEPT_FUNCTION(fn)
#endif

d419 1
a419 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, internal_strlen(domain) + 1);
d446 2
a447 4
  if (common_flags()->intercept_strcmp) {
    COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
    COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
  }
d557 2
a558 2
    uptr len1 = internal_strlen(s1);
    uptr len2 = internal_strlen(s2);
d622 1
a622 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
d625 1
a625 1
                                  internal_strlen(delimiters) + 1);
d639 1
a639 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, result, internal_strlen(result) + 1);
d643 1
a643 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
d688 1
a688 1
      (result ? result - s : internal_strlen(s)) + 1);
d719 1
a719 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
d733 1
a733 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
d744 1
a744 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
d763 1
a763 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
d765 1
a765 1
        r ? r - s1 + 1 : internal_strlen(s1) + 1);
d805 1
a805 1
#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
d807 1
a807 1
#else
d809 1
a809 1
#endif
a938 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
d951 4
a955 2
  float res = REAL(frexpf)(x, exp);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
d962 4
a966 2
  long double res = REAL(frexpl)(x, exp);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
d1236 1
a1236 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
d1250 1
a1250 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
d1265 1
a1265 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
d1319 1
a1319 1
                                        internal_strlen(tm->tm_zone) + 1);
d1372 1
a1372 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d1385 1
a1385 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d1398 1
a1398 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d1411 1
a1411 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d1448 1
a1448 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
d1828 1
a1828 1
    VPrintf(2, "Decoding unknown ioctl 0x%lx\n", request);
d1830 1
a1830 1
      Printf("WARNING: failed decoding unknown ioctl 0x%lx\n", request);
d1854 1
a1854 1
                                     internal_strlen(pwd->pw_name) + 1);
d1857 1
a1857 1
                                     internal_strlen(pwd->pw_passwd) + 1);
d1861 1
a1861 1
                                     internal_strlen(pwd->pw_gecos) + 1);
d1863 1
a1863 1
#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD
d1866 1
a1866 1
                                     internal_strlen(pwd->pw_class) + 1);
d1870 1
a1870 1
                                     internal_strlen(pwd->pw_dir) + 1);
d1873 1
a1873 1
                                     internal_strlen(pwd->pw_shell) + 1);
d1882 1
a1882 1
                                     internal_strlen(grp->gr_name) + 1);
d1885 1
a1885 1
                                     internal_strlen(grp->gr_passwd) + 1);
d1888 1
a1888 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
d1901 1
a1901 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d1916 1
a1916 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d1942 1
a1942 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d1969 1
a1969 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
a2176 1
#if SANITIZER_GLIBC
a2185 1
#endif
a2199 30
#if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
            __sanitizer_clockid_t *clockid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid);
  int res = REAL(clock_getcpuclockid)(pid, clockid);
  if (!res && clockid) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
  }
  return res;
}

INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
            __sanitizer_clockid_t *clockid) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getcpuclockid, thread, clockid);
  int res = REAL(pthread_getcpuclockid)(thread, clockid);
  if (!res && clockid) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
  }
  return res;
}

#define INIT_CLOCK_GETCPUCLOCKID                   \
  COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);  \
  COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
#else
#define INIT_CLOCK_GETCPUCLOCKID
#endif

d2254 1
a2254 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
d2284 1
a2284 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
d2290 1
a2290 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
d2296 1
a2296 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
a2374 54
#if SANITIZER_INTERCEPT_POSIX_SPAWN

template <class RealSpawnPtr>
static int PosixSpawnImpl(void *ctx, RealSpawnPtr *real_posix_spawn, pid_t *pid,
                          const char *file_or_path, const void *file_actions,
                          const void *attrp, char *const argv[],
                          char *const envp[]) {
  COMMON_INTERCEPTOR_READ_RANGE(ctx, file_or_path,
                                internal_strlen(file_or_path) + 1);
  if (argv) {
    for (char *const *s = argv; ; ++s) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
      if (!*s) break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
    }
  }
  if (envp) {
    for (char *const *s = envp; ; ++s) {
      COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
      if (!*s) break;
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
    }
  }
  int res =
      real_posix_spawn(pid, file_or_path, file_actions, attrp, argv, envp);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pid, sizeof(*pid));
  return res;
}
INTERCEPTOR(int, posix_spawn, pid_t *pid, const char *path,
            const void *file_actions, const void *attrp, char *const argv[],
            char *const envp[]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, posix_spawn, pid, path, file_actions, attrp,
                           argv, envp);
  return PosixSpawnImpl(ctx, REAL(posix_spawn), pid, path, file_actions, attrp,
                        argv, envp);
}
INTERCEPTOR(int, posix_spawnp, pid_t *pid, const char *file,
            const void *file_actions, const void *attrp, char *const argv[],
            char *const envp[]) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, posix_spawnp, pid, file, file_actions, attrp,
                           argv, envp);
  return PosixSpawnImpl(ctx, REAL(posix_spawnp), pid, file, file_actions, attrp,
                        argv, envp);
}
#  define INIT_POSIX_SPAWN                  \
    COMMON_INTERCEPT_FUNCTION(posix_spawn); \
    COMMON_INTERCEPT_FUNCTION(posix_spawnp);
#else  // SANITIZER_INTERCEPT_POSIX_SPAWN
#  define INIT_POSIX_SPAWN
#endif  // SANITIZER_INTERCEPT_POSIX_SPAWN

d2484 1
a2484 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d2513 1
a2513 1
  if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, internal_strlen(cp) + 1);
d2555 1
a2555 1
  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, internal_strlen(node) + 1);
d2557 1
a2557 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, internal_strlen(service) + 1);
d2573 1
a2573 1
                                       internal_strlen(p->ai_canonname) + 1);
d2599 1
a2599 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, internal_strlen(host) + 1);
d2601 1
a2601 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, internal_strlen(serv) + 1);
d2611 1
a2611 1
INTERCEPTOR(int, getsockname, int sock_fd, void *addr, unsigned *addrlen) {
d2614 2
a2615 5
  unsigned addr_sz;
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addr_sz = *addrlen;
  }
d2620 2
a2621 2
  if (!res && addr && addrlen) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
d2634 1
a2634 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, internal_strlen(h->h_name) + 1);
d2637 1
a2637 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
a3092 28
#if SANITIZER_INTERCEPT_SYSMSG
INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz,
            int msgflg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg);
  if (msgp)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz);
  int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
  return res;
}

INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz,
            long msgtyp, int msgflg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
  SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
  if (len != -1)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len);
  return len;
}

#define INIT_SYSMSG                  \
  COMMON_INTERCEPT_FUNCTION(msgsnd); \
  COMMON_INTERCEPT_FUNCTION(msgrcv);
#else
#define INIT_SYSMSG
#endif

d3098 1
a3098 4
  if (addrlen) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
    addr_sz = *addrlen;
  }
d3103 1
a3103 1
  if (!res && addr && addrlen) {
a3104 1
  }
d3133 1
a3133 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d3288 1
a3288 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, internal_strlen(locale) + 1);
d3291 1
a3291 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d3310 1
a3310 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d3326 1
a3326 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d3600 1
a3600 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d3611 2
a3612 3
  if (allocated_path && !res)
    WRAP(free)(allocated_path);
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d3615 1
a3615 1
#  define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
d3624 1
a3624 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d3626 1
a3626 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d3687 1
a3687 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d3703 1
a3703 1
    SANITIZER_FREEBSD
d3729 1
a3729 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d3731 1
a3731 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d3751 1
a3751 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
d3787 1
a3787 1
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
d3840 1
a3840 1
  if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
d3936 1
a3936 1
  if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
d3943 4
a3946 5
    uptr we_wordc =
        ((flags & wordexp_wrde_dooffs) ? p->we_offs : 0) + p->we_wordc;
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
                                   sizeof(*p->we_wordv) * (we_wordc + 1));
    for (uptr i = 0; i < we_wordc; ++i) {
d3948 1
a3948 1
      if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1);
d3966 1
a3966 1
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwait)(set, sig);
d3983 1
a3983 1
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwaitinfo)(set, info);
d4002 1
a4002 1
  int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigtimedwait)(set, info, timeout);
a4039 35
#if SANITIZER_INTERCEPT_SIGSET_LOGICOPS
INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst,
            __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigandset, dst, src1, src2);
  if (src1)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
  if (src2)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
  int res = REAL(sigandset)(dst, src1, src2);
  if (!res && dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
  return res;
}

INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst,
            __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigorset, dst, src1, src2);
  if (src1)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
  if (src2)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
  int res = REAL(sigorset)(dst, src1, src2);
  if (!res && dst)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
  return res;
}
#define INIT_SIGSET_LOGICOPS                    \
  COMMON_INTERCEPT_FUNCTION(sigandset);   \
  COMMON_INTERCEPT_FUNCTION(sigorset);
#else
#define INIT_SIGSET_LOGICOPS
#endif

d4119 1
a4119 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], internal_strlen(res[i]) + 1);
d4180 1
a4180 11
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m);
  COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
  int res = REAL(__pthread_mutex_lock)(m);
  if (res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
  if (res == 0 || res == errno_EOWNERDEAD)
    COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
d4184 1
a4184 7
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m);
  COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
  int res = REAL(__pthread_mutex_unlock)(m);
  if (res == errno_EINVAL)
    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
  return res;
d4221 1
a4221 1
                                   internal_strlen(mnt->mnt_fsname) + 1);
d4224 1
a4224 1
                                   internal_strlen(mnt->mnt_dir) + 1);
d4227 1
a4227 1
                                   internal_strlen(mnt->mnt_type) + 1);
d4230 1
a4230 1
                                   internal_strlen(mnt->mnt_opts) + 1);
d4265 1
a4265 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d4294 1
a4294 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d4323 1
a4323 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d4357 1
a4357 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d4386 1
a4386 1
  if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, internal_strlen(user) + 1);
d4401 1
a4401 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d4407 1
a4407 1
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
d4429 1
a4429 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
d4436 1
a4436 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
d4448 1
a4448 1
  if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, internal_strlen(line) + 1);
d4456 1
a4456 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
d4477 1
a4477 1
  if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d4484 1
a4484 1
  if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
d4750 1
a4750 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
d4752 1
a4752 1
      COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d4769 1
a4769 1
  if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
a4776 28
#if SANITIZER_INTERCEPT_PTSNAME
INTERCEPTOR(char *, ptsname, int fd) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd);
  char *res = REAL(ptsname)(fd);
  if (res != nullptr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
  return res;
}
#define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname);
#else
#define INIT_PTSNAME
#endif

#if SANITIZER_INTERCEPT_PTSNAME_R
INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize);
  int res = REAL(ptsname_r)(fd, name, namesize);
  if (res == 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
  return res;
}
#define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r);
#else
#define INIT_PTSNAME_R
#endif

d4783 1
a4783 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d4797 1
a4797 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
d4809 2
a4810 2
  if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, internal_strlen(dir) + 1);
  if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, internal_strlen(pfx) + 1);
d4812 1
a4812 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
a5157 6
#if SANITIZER_S390 && \
    (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
#endif

d5197 1
d5199 3
a5216 9
#endif // SANITIZER_S390
#else
#define INIT_TLS_GET_ADDR
#endif

#if SANITIZER_S390 && \
    (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
d5255 3
d5264 1
a5264 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d5277 1
a5277 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d5308 2
a5309 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d5321 2
a5322 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d5334 1
a5334 1
  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d5404 1
a5404 1
                                       internal_strlen(p->ifa_name) + 1);
d5434 1
a5434 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
d5441 1
a5441 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
d5699 1
a5699 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, internal_strlen(*p) + 1);
d5708 1
a5708 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
a5747 73
#if SANITIZER_INTERCEPT_XDRREC
typedef int (*xdrrec_cb)(char*, char*, int);
struct XdrRecWrapper {
  char *handle;
  xdrrec_cb rd, wr;
};
typedef AddrHashMap<XdrRecWrapper *, 11> XdrRecWrapMap;
static XdrRecWrapMap *xdrrec_wrap_map;

static int xdrrec_wr_wrap(char *handle, char *buf, int count) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(buf, count);
  XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
  return wrap->wr(wrap->handle, buf, count);
}

static int xdrrec_rd_wrap(char *handle, char *buf, int count) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
  return wrap->rd(wrap->handle, buf, count);
}

// This doesn't apply to the solaris version as it has a different function
// signature.
INTERCEPTOR(void, xdrrec_create, __sanitizer_XDR *xdr, unsigned sndsize,
            unsigned rcvsize, char *handle, int (*rd)(char*, char*, int),
            int (*wr)(char*, char*, int)) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdrrec_create, xdr, sndsize, rcvsize,
                           handle, rd, wr);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, &xdr->x_op, sizeof xdr->x_op);

  // We can't allocate a wrapper on the stack, as the handle is used outside
  // this stack frame. So we put it on the heap, and keep track of it with
  // the HashMap (keyed by x_private). When we later need to xdr_destroy,
  // we can index the map, free the wrapper, and then clean the map entry.
  XdrRecWrapper *wrap_data =
      (XdrRecWrapper *)InternalAlloc(sizeof(XdrRecWrapper));
  wrap_data->handle = handle;
  wrap_data->rd = rd;
  wrap_data->wr = wr;
  if (wr)
    wr = xdrrec_wr_wrap;
  if (rd)
    rd = xdrrec_rd_wrap;
  handle = (char *)wrap_data;

  REAL(xdrrec_create)(xdr, sndsize, rcvsize, handle, rd, wr);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdr, sizeof *xdr);

  XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, false, true);
  *wrap = wrap_data;
}

// We have to intercept this to be able to free wrapper memory;
// otherwise it's not necessary.
INTERCEPTOR(void, xdr_destroy, __sanitizer_XDR *xdr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, xdr_destroy, xdr);

  XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, true);
  InternalFree(*wrap);
  REAL(xdr_destroy)(xdr);
}
#define INIT_XDRREC_LINUX \
  static u64 xdrrec_wrap_mem[sizeof(XdrRecWrapMap) / sizeof(u64) + 1]; \
  xdrrec_wrap_map = new ((void *)&xdrrec_wrap_mem) XdrRecWrapMap(); \
  COMMON_INTERCEPT_FUNCTION(xdrrec_create); \
  COMMON_INTERCEPT_FUNCTION(xdr_destroy);
#else
#define INIT_XDRREC_LINUX
#endif

a5778 3
  if (fp->_IO_write_base && fp->_IO_write_base < fp->_IO_write_end)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_write_base,
                                        fp->_IO_write_end - fp->_IO_write_base);
d5843 2
a5844 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
d5853 1
a5853 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
d5862 2
a5863 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
a5877 34
#if SANITIZER_INTERCEPT_FLOPEN
INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
  void *ctx;
  va_list ap;
  va_start(ap, flags);
  u16 mode = static_cast<u16>(va_arg(ap, u32));
  va_end(ap);
  COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
  if (path) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  }
  return REAL(flopen)(path, flags, mode);
}

INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
  void *ctx;
  va_list ap;
  va_start(ap, flags);
  u16 mode = static_cast<u16>(va_arg(ap, u32));
  va_end(ap);
  COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
  if (path) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  }
  return REAL(flopenat)(dirfd, path, flags, mode);
}

#define INIT_FLOPEN    \
  COMMON_INTERCEPT_FUNCTION(flopen); \
  COMMON_INTERCEPT_FUNCTION(flopenat);
#else
#define INIT_FLOPEN
#endif

d5882 2
a5883 2
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
d5893 2
a5894 2
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
a6004 2
  if (fp)
    unpoison_file(fp);
a6023 2
  if (fp)
    unpoison_file(fp);
d6068 1
a6068 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, internal_strlen(prompt)+1);
d6070 1
a6070 1
  if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res)+1);
d6238 1
a6238 1
  int res = REAL(sem_trywait)(s);
d6274 8
a6281 33

INTERCEPTOR(__sanitizer_sem_t *, sem_open, const char *name, int oflag, ...) {
  void *ctx;
  va_list ap;
  va_start(ap, oflag);
  u32 mode = va_arg(ap, u32);
  u32 value = va_arg(ap, u32);
  COMMON_INTERCEPTOR_ENTER(ctx, sem_open, name, oflag, mode, value);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  __sanitizer_sem_t *s = REAL(sem_open)(name, oflag, mode, value);
  if (s)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, sizeof(*s));
  va_end(ap);
  return s;
}

INTERCEPTOR(int, sem_unlink, const char *name) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sem_unlink, name);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  return REAL(sem_unlink)(name);
}

#  define INIT_SEM                            \
    COMMON_INTERCEPT_FUNCTION(sem_init);      \
    COMMON_INTERCEPT_FUNCTION(sem_destroy);   \
    COMMON_INTERCEPT_FUNCTION(sem_wait);      \
    COMMON_INTERCEPT_FUNCTION(sem_trywait);   \
    COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
    COMMON_INTERCEPT_FUNCTION(sem_post);      \
    COMMON_INTERCEPT_FUNCTION(sem_getvalue);  \
    COMMON_INTERCEPT_FUNCTION(sem_open);      \
    COMMON_INTERCEPT_FUNCTION(sem_unlink);
d6283 2
a6284 2
#  define INIT_SEM
#endif  // SANITIZER_INTERCEPT_SEM
d6367 1
a6367 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d6382 1
a6382 1
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
d6414 1
a6414 1
  if (res > 0)
d6416 4
a6419 3
  if (res >= 0 && srcaddr)
    COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
                                        Min((SIZE_T)*addrlen, srcaddr_sz));
d6720 2
a6721 2
  SIZE_T src_size = internal_wcslen(src);
  SIZE_T dst_size = internal_wcslen(dst);
d6732 2
a6733 2
  SIZE_T src_size = internal_wcsnlen(src, n);
  SIZE_T dst_size = internal_wcslen(dst);
d6752 1
a6752 1
  SIZE_T len = internal_wcslen(s);
d6766 1
a6766 1
static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }
d6768 1
a6768 1
static SIZE_T RealStrLen(const wchar_t *str) { return internal_wcslen(str); }
d6842 1
a6842 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
d6857 1
a6857 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, internal_strlen(user) + 1);
d6871 1
a6871 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d6889 1
a6889 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, internal_strlen(group) + 1);
d6903 1
a6903 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, group, internal_strlen(group) + 1);
d6919 1
a6919 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d6932 1
a6932 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d6947 1
a6947 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d6971 1
a6971 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d6989 1
a6989 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d7006 1
a7006 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d7024 1
a7024 1
  COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, internal_strlen(pathname) + 1);
d7088 1
a7088 1
  COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, internal_strlen(dst) + 1);
d7116 1
a7116 1
    ReportMmapWriteExec(prot, flags);
d7126 1
a7126 1
    ReportMmapWriteExec(prot, 0);
d7145 1
a7145 1
    ReportMmapWriteExec(prot, flags);
d7163 1
a7163 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
d7185 1
a7185 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, internal_strlen(path) + 1);
d7215 1
a7215 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, internal_strlen(bp) + 1);
d7235 1
a7235 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
a7240 8
#define INIT_TTYENT \
  COMMON_INTERCEPT_FUNCTION(getttyent); \
  COMMON_INTERCEPT_FUNCTION(getttynam);
#else
#define INIT_TTYENT
#endif

#if SANITIZER_INTERCEPT_TTYENTPATH
d7245 1
a7245 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d7248 4
a7251 1
#define INIT_TTYENTPATH COMMON_INTERCEPT_FUNCTION(setttyentpath);
d7253 1
a7253 1
#define INIT_TTYENTPATH
d7257 6
a7262 2
static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
d7264 1
a7264 1
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, internal_strlen(p->p_name) + 1);
d7266 1
a7266 1
  SIZE_T pp_size = 1; // One handles the trailing \0
d7268 2
a7269 2
  for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);
d7271 3
a7273 10
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
                                  pp_size * sizeof(char **));
}

INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
  struct __sanitizer_protoent *p = REAL(getprotoent)();
  if (p)
    write_protoent(ctx, p);
d7281 1
a7281 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d7283 13
a7295 2
  if (p)
    write_protoent(ctx, p);
d7303 13
a7315 2
  if (p)
    write_protoent(ctx, p);
a7325 52
#if SANITIZER_INTERCEPT_PROTOENT_R
INTERCEPTOR(int, getprotoent_r, struct __sanitizer_protoent *result_buf,
            char *buf, SIZE_T buflen, struct __sanitizer_protoent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotoent_r, result_buf, buf, buflen,
                           result);
  int res = REAL(getprotoent_r)(result_buf, buf, buflen, result);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
  if (!res && *result)
    write_protoent(ctx, *result);
  return res;
}

INTERCEPTOR(int, getprotobyname_r, const char *name,
            struct __sanitizer_protoent *result_buf, char *buf, SIZE_T buflen,
            struct __sanitizer_protoent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
                           buflen, result);
  if (name)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
  if (!res && *result)
    write_protoent(ctx, *result);
  return res;
}

INTERCEPTOR(int, getprotobynumber_r, int num,
            struct __sanitizer_protoent *result_buf, char *buf,
            SIZE_T buflen, struct __sanitizer_protoent **result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber_r, num, result_buf, buf,
                           buflen, result);
  int res = REAL(getprotobynumber_r)(num, result_buf, buf, buflen, result);

  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
  if (!res && *result)
    write_protoent(ctx, *result);
  return res;
}

#define INIT_PROTOENT_R \
  COMMON_INTERCEPT_FUNCTION(getprotoent_r); \
  COMMON_INTERCEPT_FUNCTION(getprotobyname_r); \
  COMMON_INTERCEPT_FUNCTION(getprotobynumber_r);
#else
#define INIT_PROTOENT_R
#endif

d7334 1
a7334 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
d7339 1
a7339 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
d7351 1
a7351 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d7356 1
a7356 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
d7361 1
a7361 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
d7376 1
a7376 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
d7381 1
a7381 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
d7502 1
a7502 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, internal_strlen(pattern) + 1);
d7515 1
a7515 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, string, internal_strlen(string) + 1);
d7529 1
a7529 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, internal_strlen(errbuf) + 1);
d7541 1
a7541 1
  COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4");             \
d7554 1
a7554 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
d7559 1
a7559 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
d7562 1
a7562 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
d7570 1
a7570 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
d7575 1
a7575 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, internal_strlen(sstr) + 1);
d7579 1
a7579 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, internal_strlen(*buf) + 1);
d7601 1
a7601 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
d7693 1
a7693 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
d7714 1
a7714 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
d7754 1
a7754 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
d7777 1
a7777 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
d7811 1
a7811 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
d7831 1
a7831 1
                                      internal_strlen(ml->ml_filename) + 1);
d7839 1
a7839 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
d7881 1
a7881 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, internal_strlen(*errstr) + 1);
d7901 1
a7901 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
d7918 1
a7918 1
  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d8199 1
a8199 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8210 1
a8210 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8286 1
a8286 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8369 1
a8369 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8380 1
a8380 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8456 1
a8456 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8586 1
a8586 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
d8664 1
a8664 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
d8676 1
a8676 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
d8693 4
a8696 4
SHA2_INTERCEPTORS(224, u32)
SHA2_INTERCEPTORS(256, u32)
SHA2_INTERCEPTORS(384, u64)
SHA2_INTERCEPTORS(512, u64)
d8740 1
a8740 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8750 1
a8750 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8763 1
a8763 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8813 1
a8813 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8824 1
a8824 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8836 1
a8836 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8838 1
a8838 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8849 1
a8849 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8851 1
a8851 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8865 1
a8865 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8878 1
a8878 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8892 1
a8892 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
d8919 1
a8919 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8929 1
a8929 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8939 1
a8939 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8950 1
a8950 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
d8986 1
a8986 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d9178 1
a9178 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, internal_strlen(spec) + 1);
d9189 1
a9189 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
d9233 1
a9233 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, command, internal_strlen(command) + 1);
d9235 1
a9235 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
d9252 1
a9252 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
d9258 1
a9258 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
d9266 1
a9266 1
      COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
d9270 1
a9270 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
d9466 1
a9466 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
d9479 1
a9479 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
d9499 1
a9499 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
d9524 1
a9524 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
d9537 1
a9537 1
    COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
d9540 1
a9540 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
a9625 187
#if SANITIZER_INTERCEPT_QSORT_R
typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
struct qsort_r_compar_params {
  SIZE_T size;
  qsort_r_compar_f compar;
  void *arg;
};
static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
  qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
  COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size);
  return params->compar(a, b, params->arg);
}

INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_r_compar_f compar, void *arg) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
  // Run the comparator over all array elements to detect any memory issues.
  if (nmemb > 1) {
    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
      void *p = (void *)((char *)base + i * size);
      void *q = (void *)((char *)base + (i + 1) * size);
      COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
      compar(p, q, arg);
    }
  }
  qsort_r_compar_params params = {size, compar, arg};
  REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, &params);
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
}
#  define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
#else
#  define INIT_QSORT_R
#endif

#if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_r_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
  WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
}
#  define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
#elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
// Poisoned memory from there may get copied into the comparator arguments,
// where it needs to be dealt with. But even that is not enough - the results of
// the sort may be copied into the input/output array based on the results of
// the comparator calls, but directly from the temp memory, bypassing the
// unpoisoning done in wrapped_qsort_compar. We deal with this by, again,
// unpoisoning the entire array after the sort is done.
//
// We can not check that the entire array is initialized at the beginning. IMHO,
// it's fine for parts of the sorted objects to contain uninitialized memory,
// ex. as padding in structs.
typedef int (*qsort_compar_f)(const void *, const void *);
static THREADLOCAL qsort_compar_f qsort_compar;
static THREADLOCAL SIZE_T qsort_size;
static int wrapped_qsort_compar(const void *a, const void *b) {
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
  return qsort_compar(a, b);
}

INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
            qsort_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
  // Run the comparator over all array elements to detect any memory issues.
  if (nmemb > 1) {
    for (SIZE_T i = 0; i < nmemb - 1; ++i) {
      void *p = (void *)((char *)base + i * size);
      void *q = (void *)((char *)base + (i + 1) * size);
      COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
      compar(p, q);
    }
  }
  qsort_compar_f old_compar = qsort_compar;
  SIZE_T old_size = qsort_size;
  // Handle qsort() implementations that recurse using an
  // interposable function call:
  bool already_wrapped = compar == wrapped_qsort_compar;
  if (already_wrapped) {
    // This case should only happen if the qsort() implementation calls itself
    // using a preemptible function call (e.g. the FreeBSD libc version).
    // Check that the size and comparator arguments are as expected.
    CHECK_NE(compar, qsort_compar);
    CHECK_EQ(qsort_size, size);
  } else {
    qsort_compar = compar;
    qsort_size = size;
  }
  REAL(qsort)(base, nmemb, size, wrapped_qsort_compar);
  if (!already_wrapped) {
    qsort_compar = old_compar;
    qsort_size = old_size;
  }
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
}
#  define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
#else
#  define INIT_QSORT
#endif

#if SANITIZER_INTERCEPT_BSEARCH
typedef int (*bsearch_compar_f)(const void *, const void *);
struct bsearch_compar_params {
  const void *key;
  bsearch_compar_f compar;
};

static int wrapped_bsearch_compar(const void *key, const void *b) {
  const bsearch_compar_params *params = (const bsearch_compar_params *)key;
  COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
  return params->compar(params->key, b);
}

INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
            SIZE_T size, bsearch_compar_f compar) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
  bsearch_compar_params params = {key, compar};
  return REAL(bsearch)(&params, base, nmemb, size, wrapped_bsearch_compar);
}
#  define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
#else
#  define INIT_BSEARCH
#endif

#if SANITIZER_INTERCEPT_SIGALTSTACK
INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss);
  int r = REAL(sigaltstack)(ss, oss);
  if (r == 0 && oss != nullptr) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz);
  }
  return r;
}
#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack)
#else
#define INIT_SIGALTSTACK
#endif

#if SANITIZER_INTERCEPT_UNAME
INTERCEPTOR(int, uname, struct utsname *utsname) {
#if SANITIZER_LINUX
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return internal_uname(utsname);
#endif
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, uname, utsname);
  int res = REAL(uname)(utsname);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
                                   __sanitizer::struct_utsname_sz);
  return res;
}
#define INIT_UNAME COMMON_INTERCEPT_FUNCTION(uname)
#else
#define INIT_UNAME
#endif

#if SANITIZER_INTERCEPT___XUNAME
// FreeBSD's <sys/utsname.h> define uname() as
// static __inline int uname(struct utsname *name) {
//   return __xuname(SYS_NMLN, (void*)name);
// }
INTERCEPTOR(int, __xuname, int size, void *utsname) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __xuname, size, utsname);
  int res = REAL(__xuname)(size, utsname);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
                                   __sanitizer::struct_utsname_sz);
  return res;
}
#define INIT___XUNAME COMMON_INTERCEPT_FUNCTION(__xuname)
#else
#define INIT___XUNAME
#endif

#include "sanitizer_common_interceptors_netbsd_compat.inc"

a9696 1
  INIT_CLOCK_GETCPUCLOCKID;
a9700 1
  INIT_POSIX_SPAWN;
a9722 1
  INIT_SYSMSG;
a9758 1
  INIT_SIGSET_LOGICOPS;
a9799 2
  INIT_PTSNAME;
  INIT_PTSNAME_R;
a9828 1
  INIT_XDRREC_LINUX;
a9832 1
  INIT_FLOPEN;
a9885 1
  INIT_PROTOENT_R;
a9926 6
  INIT_QSORT;
  INIT_QSORT_R;
  INIT_BSEARCH;
  INIT_SIGALTSTACK;
  INIT_UNAME;
  INIT___XUNAME;
@


1.1.1.12
log
@initial import of GCC 14.3.0.

major changes in GCC 13:
- improved sanitizer
- zstd debug info compression
- LTO improvements
- SARIF based diagnostic support
- new warnings: -Wxor-used-as-pow, -Wenum-int-mismatch, -Wself-move,
  -Wdangling-reference
- many new -Wanalyzer* specific warnings
- enhanced warnings: -Wpessimizing-move, -Wredundant-move
- new attributes to mark file descriptors, c++23 "assume"
- several C23 features added
- several C++23 features added
- many new features for Arm, x86, RISC-V

major changes in GCC 14:
- more strict C99 or newer support
- ia64* marked deprecated (but seemingly still in GCC 15.)
- several new hardening features
- support for "hardbool", which can have user supplied values of true/false
- explicit support for stack scrubbing upon function exit
- better auto-vectorisation support
- added clang-compatible __has_feature and __has_extension
- more C23, including -std=c23
- several C++26 features added
- better diagnostics in C++ templates
- new warnings: -Wnrvo, Welaborated-enum-base
- many new features for Arm, x86, RISC-V
- possible ABI breaking change for SPARC64 and small structures with arrays
  of floats.
@
text
@d24 1
a24 1
//   COMMON_INTERCEPTOR_DLOPEN
d26 4
d33 3
a36 1
//   COMMON_INTERCEPTOR_MUNMAP_IMPL
a41 2
#include <stdarg.h>

a43 1
#include "sanitizer_dl.h"
d50 2
d135 8
a142 69
#if SANITIZER_MUSL && \
  (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
// time-related functions that take 64-bit time_t values.  See
// https://musl.libc.org/time64.html
#define adjtime __adjtime64
#define adjtimex __adjtimex_time64
#define aio_suspend __aio_suspend_time64
#define clock_adjtime __clock_adjtime64
#define clock_getres __clock_getres_time64
#define clock_gettime __clock_gettime64
#define clock_nanosleep __clock_nanosleep_time64
#define clock_settime __clock_settime64
#define cnd_timedwait __cnd_timedwait_time64
#define ctime __ctime64
#define ctime_r __ctime64_r
#define difftime __difftime64
#define dlsym __dlsym_time64
#define fstatat __fstatat_time64
#define fstat __fstat_time64
#define ftime __ftime64
#define futimens __futimens_time64
#define futimesat __futimesat_time64
#define futimes __futimes_time64
#define getitimer __getitimer_time64
#define getrusage __getrusage_time64
#define gettimeofday __gettimeofday_time64
#define gmtime __gmtime64
#define gmtime_r __gmtime64_r
#define localtime __localtime64
#define localtime_r __localtime64_r
#define lstat __lstat_time64
#define lutimes __lutimes_time64
#define mktime __mktime64
#define mq_timedreceive __mq_timedreceive_time64
#define mq_timedsend __mq_timedsend_time64
#define mtx_timedlock __mtx_timedlock_time64
#define nanosleep __nanosleep_time64
#define ppoll __ppoll_time64
#define pselect __pselect_time64
#define pthread_cond_timedwait __pthread_cond_timedwait_time64
#define pthread_mutex_timedlock __pthread_mutex_timedlock_time64
#define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_time64
#define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_time64
#define pthread_timedjoin_np __pthread_timedjoin_np_time64
#define recvmmsg __recvmmsg_time64
#define sched_rr_get_interval __sched_rr_get_interval_time64
#define select __select_time64
#define semtimedop __semtimedop_time64
#define sem_timedwait __sem_timedwait_time64
#define setitimer __setitimer_time64
#define settimeofday __settimeofday_time64
#define sigtimedwait __sigtimedwait_time64
#define stat __stat_time64
#define stime __stime64
#define thrd_sleep __thrd_sleep_time64
#define timegm __timegm_time64
#define timerfd_gettime __timerfd_gettime64
#define timerfd_settime __timerfd_settime64
#define timer_gettime __timer_gettime64
#define timer_settime __timer_settime64
#define timespec_get __timespec_get_time64
#define time __time64
#define utimensat __utimensat_time64
#define utimes __utimes_time64
#define utime __utime64
#define wait3 __wait3_time64
#define wait4 __wait4_time64
#endif
d156 20
d209 3
a211 3
#ifndef COMMON_INTERCEPTOR_DLOPEN
#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
  ({ CheckNoDeepBind(filename, flag); REAL(dlopen)(filename, flag); })
d259 41
a305 5
#ifndef COMMON_INTERCEPTOR_MUNMAP_IMPL
#define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz) \
  { return REAL(munmap)(addr, sz); }
#endif

d318 3
a320 5
  if (new_mem) {                                                              \
    COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length);             \
    internal_memcpy(new_mem, s, copy_length);                                 \
    new_mem[copy_length] = '\0';                                              \
  }                                                                           \
d447 1
a447 1
#if SANITIZER_INTERCEPT_STRCMP || SANITIZER_INTERCEPT_MEMCMP
a450 1
#endif
a451 1
#if SANITIZER_INTERCEPT_STRCMP
d796 51
d1267 1
a1267 1
  if (!SANITIZER_APPLE || s) {  // `fputs(NULL, file)` is supported on Darwin.
d1282 1
a1282 1
  if (!SANITIZER_APPLE || s) {  // `puts(NULL)` is supported on Darwin.
d1298 1
a1298 8
  static const int PR_SET_VMA = 0x53564d41;
  static const int PR_SCHED_CORE = 62;
  static const int PR_SCHED_CORE_GET = 0;
  if (option == PR_SET_VMA && arg2 == 0UL) {
    char *name = (char *)arg5;
    COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
  }
  int res = REAL(prctl)(option, arg2, arg3, arg4, arg5);
a1303 2
  } else if (res != -1 && option == PR_SCHED_CORE && arg2 == PR_SCHED_CORE_GET) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));
a1534 10

INTERCEPTOR(int, __isoc23_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vscanf, false, format, ap)

INTERCEPTOR(int, __isoc23_vsscanf, const char *str, const char *format,
            va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc23_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vfscanf, false, stream, format, ap)
a1554 9

INTERCEPTOR(int, __isoc23_scanf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_scanf, __isoc23_vscanf, format)

INTERCEPTOR(int, __isoc23_fscanf, void *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_fscanf, __isoc23_vfscanf, stream, format)

INTERCEPTOR(int, __isoc23_sscanf, const char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_sscanf, __isoc23_vsscanf, str, format)
d1578 1
a1578 7
  COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); \
  COMMON_INTERCEPT_FUNCTION(__isoc23_scanf);   \
  COMMON_INTERCEPT_FUNCTION(__isoc23_sscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc23_fscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc23_vscanf);  \
  COMMON_INTERCEPT_FUNCTION(__isoc23_vsscanf); \
  COMMON_INTERCEPT_FUNCTION(__isoc23_vfscanf);
d1881 1
a1881 1
#if SANITIZER_APPLE || SANITIZER_FREEBSD || SANITIZER_NETBSD
a2424 76
#if SANITIZER_INTERCEPT___B64_TO
INTERCEPTOR(int, __b64_ntop, unsigned char const *src, SIZE_T srclength,
            char *target, SIZE_T targsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __b64_ntop, src, srclength, target, targsize);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclength);
  int res = REAL(__b64_ntop)(src, srclength, target, targsize);
  if (res >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res + 1);
  return res;
}
INTERCEPTOR(int, __b64_pton, char const *src, char *target, SIZE_T targsize) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __b64_pton, src, target, targsize);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
  int res = REAL(__b64_pton)(src, target, targsize);
  if (res >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res);
  return res;
}
#define INIT___B64_TO                      \
    COMMON_INTERCEPT_FUNCTION(__b64_ntop); \
    COMMON_INTERCEPT_FUNCTION(__b64_pton);
#else  // SANITIZER_INTERCEPT___B64_TO
#define INIT___B64_TO
#endif  // SANITIZER_INTERCEPT___B64_TO

#if SANITIZER_INTERCEPT_DN_COMP_EXPAND
#  if __GLIBC_PREREQ(2, 34)
// Changed with https://sourceware.org/git/?p=glibc.git;h=640bbdf
#    define DN_COMP_INTERCEPTOR_NAME dn_comp
#    define DN_EXPAND_INTERCEPTOR_NAME dn_expand
#  else
#    define DN_COMP_INTERCEPTOR_NAME __dn_comp
#    define DN_EXPAND_INTERCEPTOR_NAME __dn_expand
#  endif
INTERCEPTOR(int, DN_COMP_INTERCEPTOR_NAME, unsigned char *exp_dn,
            unsigned char *comp_dn, int length, unsigned char **dnptrs,
            unsigned char **lastdnptr) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, DN_COMP_INTERCEPTOR_NAME, exp_dn, comp_dn,
                           length, dnptrs, lastdnptr);
  int res = REAL(DN_COMP_INTERCEPTOR_NAME)(exp_dn, comp_dn, length, dnptrs,
                                           lastdnptr);
  if (res >= 0) {
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, comp_dn, res);
    if (dnptrs && lastdnptr) {
      unsigned char **p = dnptrs;
      for (; p != lastdnptr && *p; ++p)
        ;
      if (p != lastdnptr)
        ++p;
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dnptrs, (p - dnptrs) * sizeof(*p));
    }
  }
  return res;
}
INTERCEPTOR(int, DN_EXPAND_INTERCEPTOR_NAME, unsigned char const *base,
            unsigned char const *end, unsigned char const *src, char *dest,
            int space) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, DN_EXPAND_INTERCEPTOR_NAME, base, end, src,
                           dest, space);
  // TODO: add read check if __dn_comp intercept added
  int res = REAL(DN_EXPAND_INTERCEPTOR_NAME)(base, end, src, dest, space);
  if (res >= 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, internal_strlen(dest) + 1);
  return res;
}
#  define INIT_DN_COMP_EXPAND                            \
    COMMON_INTERCEPT_FUNCTION(DN_COMP_INTERCEPTOR_NAME); \
    COMMON_INTERCEPT_FUNCTION(DN_EXPAND_INTERCEPTOR_NAME);
#else  // SANITIZER_INTERCEPT_DN_COMP_EXPAND
#  define INIT_DN_COMP_EXPAND
#endif  // SANITIZER_INTERCEPT_DN_COMP_EXPAND

d3286 1
a3286 2
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer_dirsiz(res));
d3301 1
a3301 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, __sanitizer_dirsiz(*result));
d3322 1
a3322 2
  if (res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer_dirsiz(res));
d3337 1
a3337 1
      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, __sanitizer_dirsiz(*result));
d3505 1
d3507 6
a3512 4
template <typename Fn>
static ALWAYS_INLINE auto StrtoimaxImpl(void *ctx, Fn real, const char *nptr,
                                        char **endptr, int base)
    -> decltype(real(nullptr, nullptr, 0)) {
d3514 1
a3514 1
  auto res = real(nptr, &real_endptr, base);
a3518 5
INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(strtoimax), nptr, endptr, base);
}
d3522 7
a3528 1
  return StrtoimaxImpl(ctx, REAL(strtoumax), nptr, endptr, base);
a3537 19
#if SANITIZER_INTERCEPT_STRTOIMAX && SANITIZER_GLIBC
INTERCEPTOR(INTMAX_T, __isoc23_strtoimax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoimax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(__isoc23_strtoimax), nptr, endptr, base);
}
INTERCEPTOR(UINTMAX_T, __isoc23_strtoumax, const char *nptr, char **endptr, int base) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoumax, nptr, endptr, base);
  return StrtoimaxImpl(ctx, REAL(__isoc23_strtoumax), nptr, endptr, base);
}

#  define INIT_STRTOIMAX_C23                       \
    COMMON_INTERCEPT_FUNCTION(__isoc23_strtoimax); \
    COMMON_INTERCEPT_FUNCTION(__isoc23_strtoumax);
#else
#  define INIT_STRTOIMAX_C23
#endif

d3842 1
a3842 1
    SANITIZER_APPLE || SANITIZER_ANDROID || SANITIZER_NETBSD ||                 \
d3875 1
a3875 1
       //SANITIZER_APPLE
d3909 1
a3909 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, __sanitizer_dirsiz(dir));
d3917 1
a3917 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, __sanitizer_dirsiz(*a));
d3919 1
a3919 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, __sanitizer_dirsiz(*b));
d3943 1
a3943 1
                                     __sanitizer_dirsiz((*namelist)[i]));
d3962 1
a3962 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, __sanitizer_dirsiz(dir));
d3970 1
a3970 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, __sanitizer_dirsiz(*a));
d3972 1
a3972 1
  COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, __sanitizer_dirsiz(*b));
d3997 1
a3997 1
                                     __sanitizer_dirsiz((*namelist)[i]));
d4274 5
a4278 6
  // 'buffer' might be freed memory, hence it is unsafe to directly call
  // REAL(backtrace)(buffer, size). Instead, we use our own known-good
  // scratch buffer.
  void **scratch = (void**)InternalAlloc(sizeof(void*) * size);
  int res = REAL(backtrace)(scratch, size);
  if (res && buffer) {
a4279 3
    internal_memcpy(buffer, scratch, res * sizeof(*buffer));
  }
  InternalFree(scratch);
d4288 3
a4290 2
  // The COMMON_INTERCEPTOR_READ_RANGE above ensures that 'buffer' is
  // valid for reading.
d4321 67
d4389 6
d4396 1
a4396 1
ALIAS(WRAP(pthread_setcancelstate));
d4398 2
d4403 2
a4843 21
#if SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP
INTERCEPTOR(int, pthread_getaffinity_np, void *attr, SIZE_T cpusetsize,
            void *cpuset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pthread_getaffinity_np, attr, cpusetsize,
                           cpuset);
  // FIXME: under ASan the call below may write to freed memory and corrupt
  // its metadata. See
  // https://github.com/google/sanitizers/issues/321.
  int res = REAL(pthread_getaffinity_np)(attr, cpusetsize, cpuset);
  if (!res && cpusetsize && cpuset)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
  return res;
}

#define INIT_PTHREAD_GETAFFINITY_NP \
  COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np);
#else
#define INIT_PTHREAD_GETAFFINITY_NP
#endif

d5410 3
a5412 1
INTERCEPTOR(void *, __tls_get_addr_opt, void *arg) ALIAS(WRAP(__tls_get_addr));
d5446 2
d5450 3
a5452 5
extern "C" __attribute__((visibility("hidden"))) uptr __tls_get_addr_hidden(
    void *arg) ALIAS(WRAP(__tls_get_addr_internal));
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr TRAMPOLINE(__tls_get_offset)(void *arg);
extern "C" uptr WRAP(__tls_get_offset)(void *arg);
d5459 2
a5460 1
  ".set __tls_get_offset, __interceptor___tls_get_offset\n"
d5689 2
a5690 4
  if (res == 0 && datap) {
    unsigned datasz = __user_cap_data_struct_sz(hdrp);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, datasz);
  }
d5701 2
a5702 4
  if (datap) {
    unsigned datasz = __user_cap_data_struct_sz(hdrp);
    COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, datasz);
  }
d5712 99
d6382 3
a6384 31

  if (filename) {
    COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);

#  if !SANITIZER_DYNAMIC
    // We care about a very specific use-case: dladdr on
    // statically-linked ASan may return <main program>
    // instead of the library.
    // We therefore only take effect if the sanitizer is statically
    // linked, and we don't bother canonicalizing paths because
    // dladdr should return the same address both times (we assume
    // the user did not canonicalize the result from dladdr).
    if (common_flags()->test_only_replace_dlopen_main_program) {
      VPrintf(1, "dlopen interceptor: filename: %s\n", filename);

      const char *SelfFName = DladdrSelfFName();
      VPrintf(1, "dlopen interceptor: DladdrSelfFName: %p %s\n",
              (void *)SelfFName, SelfFName);

      if (internal_strcmp(SelfFName, filename) == 0) {
        // It's possible they copied the string from dladdr, so
        // we do a string comparison rather than pointer comparison.
        VPrintf(1, "dlopen interceptor: replacing %s because it matches %s\n",
                filename, SelfFName);
        filename = (char *)0;  // RTLD_DEFAULT
      }
    }
#  endif  // !SANITIZER_DYNAMIC
  }

  void *res = COMMON_INTERCEPTOR_DLOPEN(filename, flag);
d6553 1
a6553 1
  // interceptors bind to the lowest version before glibc 2.36, hitting the
a6874 17
#if SANITIZER_INTERCEPT_STAT64
INTERCEPTOR(int, stat64, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, stat64, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(stat64)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT_STAT64 COMMON_INTERCEPT_FUNCTION(stat64)
#else
#define INIT_STAT64
#endif


a6890 16
#if SANITIZER_INTERCEPT_STAT64
INTERCEPTOR(int, lstat64, const char *path, void *buf) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, lstat64, path, buf);
  if (common_flags()->intercept_stat)
    COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
  int res = REAL(lstat64)(path, buf);
  if (!res)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
  return res;
}
#define INIT_LSTAT64 COMMON_INTERCEPT_FUNCTION(lstat64)
#else
#define INIT_LSTAT64
#endif

a7062 1
#if SANITIZER_INTERCEPT_WCSLEN
a7080 3
#else
#define INIT_WCSLEN
#endif
a7488 8
INTERCEPTOR(int, munmap, void *addr, SIZE_T sz) {
  void *ctx;
  if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
    return (int)internal_munmap(addr, sz);
  COMMON_INTERCEPTOR_ENTER(ctx, munmap, addr, sz);
  COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, sz);
}

a7500 1
  COMMON_INTERCEPT_FUNCTION(munmap);                                           \
d7638 2
a7639 1
  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *));
d7745 2
a7746 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
d7767 2
a7768 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
d7787 2
a7788 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, nn_size * sizeof(char *));
d7861 1
a7861 1
INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, SIZE_T size) {
d7863 2
a7864 2
  COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, size);
  REAL(setbuffer)(stream, buf, size);
d7866 1
a7866 1
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
d7908 1
a7908 1
  if (preg)
d9980 35
a10176 36
#if SANITIZER_INTERCEPT_PROCCTL
INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data);
   static const int PROC_REAP_ACQUIRE = 2;
   static const int PROC_REAP_RELEASE = 3;
   static const int PROC_REAP_STATUS = 4;
   static const int PROC_REAP_GETPIDS = 5;
   static const int PROC_REAP_KILL = 6;
   if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) {
     COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int));
   } else {
     // reap_acquire/reap_release bears no arguments.
     if (cmd > PROC_REAP_RELEASE) {
       unsigned int reapsz;
       switch (cmd) {
       case PROC_REAP_STATUS:
         reapsz = struct_procctl_reaper_status_sz;
         break;
       case PROC_REAP_GETPIDS:
         reapsz = struct_procctl_reaper_pids_sz;
         break;
       case PROC_REAP_KILL:
         reapsz = struct_procctl_reaper_kill_sz;
         break;
       }
       COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz);
     }
   }
   return REAL(procctl)(idtype, id, cmd, data);
}
#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl)
#else
#define INIT_PROCCTL
#endif

a10214 46
#if SANITIZER_INTERCEPT_HEXDUMP
INTERCEPTOR(void, hexdump, const void *ptr, int length, const char *header, int flags) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, hexdump, ptr, length, header, flags);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, length);
  COMMON_INTERCEPTOR_READ_RANGE(ctx, header, internal_strlen(header) + 1);
  REAL(hexdump)(ptr, length, header, flags);
}

#define INIT_HEXDUMP COMMON_INTERCEPT_FUNCTION(hexdump);
#else
#define INIT_HEXDUMP
#endif

#if SANITIZER_INTERCEPT_ARGP_PARSE
INTERCEPTOR(int, argp_parse, const struct argp *argp, int argc, char **argv,
            unsigned flags, int *arg_index, void *input) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, argp_parse, argp, argc, argv, flags, arg_index,
                           input);
  for (int i = 0; i < argc; i++)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, argv[i], internal_strlen(argv[i]) + 1);
  int res = REAL(argp_parse)(argp, argc, argv, flags, arg_index, input);
  if (!res && arg_index)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg_index, sizeof(int));
  return res;
}

#define INIT_ARGP_PARSE COMMON_INTERCEPT_FUNCTION(argp_parse);
#else
#define INIT_ARGP_PARSE
#endif

#if SANITIZER_INTERCEPT_CPUSET_GETAFFINITY
INTERCEPTOR(int, cpuset_getaffinity, int level, int which, __int64_t id, SIZE_T cpusetsize, __sanitizer_cpuset_t *mask) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, cpuset_getaffinity, level, which, id, cpusetsize, mask);
  int res = REAL(cpuset_getaffinity)(level, which, id, cpusetsize, mask);
  if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
  return res;
}
#define INIT_CPUSET_GETAFFINITY COMMON_INTERCEPT_FUNCTION(cpuset_getaffinity);
#else
#define INIT_CPUSET_GETAFFINITY
#endif

a10216 4
namespace __sanitizer {
void InitializeMemintrinsicInterceptors();
}  // namespace __sanitizer

a10222 2
  __sanitizer::InitializeMemintrinsicInterceptors();

d10244 3
a10292 2
  INIT___B64_TO;
  INIT_DN_COMP_EXPAND;
a10327 1
  INIT_STRTOIMAX_C23;
d10359 6
a10381 1
  INIT_PTHREAD_GETAFFINITY_NP;
d10421 3
a10449 1
  INIT_STAT64;
a10451 1
  INIT_LSTAT64;
d10524 2
a10530 1
  INIT_PROCCTL
a10532 3
  INIT_HEXDUMP;
  INIT_ARGP_PARSE;
  INIT_CPUSET_GETAFFINITY;
@


1.1.1.1.6.1
log
@Sync gcc with -current, requested by skrll in ticket #448:

tools/gcc/Makefile                              up to 1.74
tools/gcc/gcc-version.mk                        up to 1.3
external/gpl3/gcc/dist/config/mh-alpha-linux    up to 1.1.1.1
external/gpl3/gcc/dist/gcc/config/or1k/constraints.md up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/elf.h    up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/linux-elf.h up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/linux-gas.h up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/netbsd.h up to 1.2
external/gpl3/gcc/dist/gcc/config/or1k/or1k-modes.def up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/or1k-opts.h up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/or1k-protos.h up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/or1k.c   up to 1.2
external/gpl3/gcc/dist/gcc/config/or1k/or1k.h   up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/or1k.md  up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/or1k.opt up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/predicates.md up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/t-linux  up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/t-or1k   up to 1.1
external/gpl3/gcc/dist/gcc/config/or1k/t-or1knd up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/constraints.md up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/crti.asm up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/crtn.asm up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/div.S   up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/elf.h   up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/generic.md up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/linux-unwind.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/linux.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/linux64.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/netbsd.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/peephole.md up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/predicates.md up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv-fp.c up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv-ftypes.def up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv-modes.def up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv.c up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv.h up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv.md up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/sync.md up to 1.2
external/gpl3/gcc/dist/gcc/config/riscv/t-elf   up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/t-linux64 up to 1.1
external/gpl3/gcc/dist/gcc/config/riscv/t-netbsd64 up to 1.1
external/gpl3/gcc/dist/gcc/common/config/or1k/or1k-common.c up to 1.1
external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/or1k-asm.h up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/crti.S up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/crtn.S up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/linux-unwind.h up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/or1k.S up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/sfp-machine.h up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/t-crtstuff up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/t-linux up to 1.1
external/gpl3/gcc/dist/libgcc/config/or1k/t-or1k up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/riscv-fp.c up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/crti.S up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/crtn.S up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/t-dpbit up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/t-elf up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/t-fpbit up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/t-linux up to 1.1
external/gpl3/gcc/dist/libgcc/config/riscv/t-tpbit up to 1.1
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_netbsd.cc up to 1.3
external/gpl3/gcc/lib/libstdc++-v3/include/bits/arch/powerpc/Makefile up to 1.1
external/gpl3/gcc/lib/libstdc++-v3/include/bits/arch/powerpc64/Makefile up to 1.1
external/gpl3/gcc/lib/libstdc++-v3/include/bits/arch/riscv32/Makefile up to 1.1
external/gpl3/gcc/lib/libstdc++-v3/include/bits/arch/riscv64/Makefile up to 1.1
external/gpl3/gcc/lib/libtsan/Makefile          up to 1.2
external/gpl3/gcc/lib/libtsan/shlib_version     up to 1.1
external/gpl3/gcc/lib/libasan/Makefile          up to 1.9
external/gpl3/gcc/lib/libasan/shlib_version     up to 1.1
external/gpl3/gcc/usr.bin/lto-wrapper/Makefile  up to 1.1
external/gpl3/gcc/usr.bin/lto1/Makefile         up to 1.2
external/gpl3/gcc/Makefile                      up to 1.2
external/gpl3/gcc/README.gcc48                  up to 1.6
external/gpl3/gcc/dist/ChangeLog                up to 1.1.1.6
external/gpl3/gcc/dist/LAST_UPDATED             up to 1.5
external/gpl3/gcc/dist/MD5SUMS                  up to 1.5
external/gpl3/gcc/dist/Makefile.def             up to 1.1.1.4
external/gpl3/gcc/dist/Makefile.in              up to 1.1.1.4
external/gpl3/gcc/dist/configure                up to 1.8
external/gpl3/gcc/dist/configure.ac             up to 1.7
external/gpl3/gcc/dist/config/ChangeLog         up to 1.1.1.6
external/gpl3/gcc/dist/contrib/ChangeLog        up to 1.1.1.6
external/gpl3/gcc/dist/contrib/reghunt/ChangeLog up to 1.1.1.5
external/gpl3/gcc/dist/contrib/regression/ChangeLog up to 1.1.1.5
external/gpl3/gcc/dist/fixincludes/ChangeLog    up to 1.1.1.5
external/gpl3/gcc/dist/fixincludes/fixincl.x    up to 1.1.1.3
external/gpl3/gcc/dist/fixincludes/inclhack.def up to 1.1.1.3
external/gpl3/gcc/dist/fixincludes/tests/base/assert.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/ChangeLog            up to 1.11
external/gpl3/gcc/dist/gcc/DATESTAMP            up to 1.1.1.7
external/gpl3/gcc/dist/gcc/DEV-PHASE            up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config.gcc           up to 1.32
external/gpl3/gcc/dist/gcc/config.in            up to 1.1.1.4
external/gpl3/gcc/dist/gcc/configure            up to 1.11
external/gpl3/gcc/dist/gcc/configure.ac         up to 1.9
external/gpl3/gcc/dist/gcc/convert.c            up to 1.1.1.4
external/gpl3/gcc/dist/gcc/expr.c               up to 1.7
external/gpl3/gcc/dist/gcc/fold-const.c         up to 1.1.1.7
external/gpl3/gcc/dist/gcc/graphite-clast-to-gimple.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/graphite-interchange.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/graphite-optimize-isl.c up to 1.1.1.2
external/gpl3/gcc/dist/gcc/graphite-poly.c      up to 1.1.1.3
external/gpl3/gcc/dist/gcc/graphite-sese-to-poly.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/ipa-pure-const.c     up to 1.1.1.3
external/gpl3/gcc/dist/gcc/omp-low.c            up to 1.1.1.4
external/gpl3/gcc/dist/gcc/ree.c                up to 1.1.1.2
external/gpl3/gcc/dist/gcc/rtlanal.c            up to 1.2
external/gpl3/gcc/dist/gcc/stor-layout.c        up to 1.1.1.3
external/gpl3/gcc/dist/gcc/tree-data-ref.c      up to 1.1.1.3
external/gpl3/gcc/dist/gcc/tree-data-ref.h      up to 1.1.1.3
external/gpl3/gcc/dist/gcc/tree-nrv.c           up to 1.1.1.3
external/gpl3/gcc/dist/gcc/tree-ssa-forwprop.c  up to 1.1.1.3
external/gpl3/gcc/dist/gcc/tree-ssa-reassoc.c   up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree-ssa-strlen.c    up to 1.1.1.2
external/gpl3/gcc/dist/gcc/tree-ssa-tail-merge.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/tree-vect-slp.c      up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tree.c               up to 1.1.1.4
external/gpl3/gcc/dist/gcc/tsan.c               up to 1.1.1.2
external/gpl3/gcc/dist/gcc/c/ChangeLog          up to 1.1.1.4
external/gpl3/gcc/dist/gcc/c-family/ChangeLog   up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/darwin-c.c    up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/darwin-driver.c up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/netbsd.h      up to 1.14
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64-elf-raw.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64-linux.h up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64-protos.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64.c up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64.h up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/aarch64/aarch64.opt up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/arm/arm.h     up to 1.10
external/gpl3/gcc/dist/gcc/config/arm/arm.md    up to 1.8
external/gpl3/gcc/dist/gcc/config/i386/i386.c   up to 1.9
external/gpl3/gcc/dist/gcc/config/pa/pa.md      up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/rs6000/altivec.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/rs6000/altivec.md up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/rs6000/netbsd.h up to 1.8
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000-builtin.def up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000-c.c up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000-protos.h up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/rs6000/rs6000.c up to 1.10
external/gpl3/gcc/dist/gcc/config/rs6000/vsx.md up to 1.1.1.6
external/gpl3/gcc/dist/gcc/config/rs6000/xcoff.h up to 1.1.1.3
external/gpl3/gcc/dist/gcc/config/sh/sh.c       up to 1.7
external/gpl3/gcc/dist/gcc/config/sh/sh.md      up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/sparc/leon.md up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/sparc/sparc-opts.h up to 1.1.1.2
external/gpl3/gcc/dist/gcc/config/sparc/sparc.c up to 1.1.1.5
external/gpl3/gcc/dist/gcc/config/sparc/sparc.h up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/sparc/sparc.md up to 1.4
external/gpl3/gcc/dist/gcc/config/sparc/sparc.opt up to 1.1.1.4
external/gpl3/gcc/dist/gcc/config/sparc/t-rtems up to 1.1.1.2
external/gpl3/gcc/dist/gcc/cp/ChangeLog         up to 1.1.1.7
external/gpl3/gcc/dist/gcc/cp/parser.c          up to 1.1.1.6
external/gpl3/gcc/dist/gcc/cp/pt.c              up to 1.1.1.5
external/gpl3/gcc/dist/gcc/cp/semantics.c       up to 1.1.1.5
external/gpl3/gcc/dist/gcc/doc/extend.texi      up to 1.1.1.5
external/gpl3/gcc/dist/gcc/doc/install.texi     up to 1.1.1.5
external/gpl3/gcc/dist/gcc/doc/invoke.texi      up to 1.7
external/gpl3/gcc/dist/gcc/doc/md.texi          up to 1.1.1.6
external/gpl3/gcc/dist/gcc/doc/tm.texi          up to 1.1.1.4
external/gpl3/gcc/dist/gcc/doc/tm.texi.in       up to 1.1.1.3
external/gpl3/gcc/dist/gcc/lto/ChangeLog        up to 1.1.1.5
external/gpl3/gcc/dist/gcc/objc/ChangeLog       up to 1.1.1.5
external/gpl3/gcc/dist/gcc/objcp/ChangeLog      up to 1.1.1.5
external/gpl3/gcc/dist/gnattools/ChangeLog      up to 1.1.1.3
external/gpl3/gcc/dist/include/ChangeLog        up to 1.1.1.5
external/gpl3/gcc/dist/intl/ChangeLog           up to 1.1.1.5
external/gpl3/gcc/dist/libbacktrace/ChangeLog   up to 1.1.1.4
external/gpl3/gcc/dist/libcpp/ChangeLog         up to 1.1.1.5
external/gpl3/gcc/dist/libcpp/lex.c             up to 1.5
external/gpl3/gcc/dist/libcpp/line-map.c        up to 1.1.1.4
external/gpl3/gcc/dist/libdecnumber/ChangeLog   up to 1.1.1.5
external/gpl3/gcc/dist/libgcc/ChangeLog         up to 1.1.1.7
external/gpl3/gcc/dist/libgcc/config/libbid/ChangeLog up to 1.1.1.5
external/gpl3/gcc/dist/libgcc/config/pa/linux-unwind.h up to 1.1.1.2
external/gpl3/gcc/dist/libgcc/config/sh/lib1funcs.S up to 1.1.1.2
external/gpl3/gcc/dist/libgomp/ChangeLog        up to 1.1.1.5
external/gpl3/gcc/dist/libgomp/configure.tgt    up to 1.1.1.3
external/gpl3/gcc/dist/libiberty/ChangeLog      up to 1.1.1.5
external/gpl3/gcc/dist/libitm/ChangeLog         up to 1.1.1.3
external/gpl3/gcc/dist/libitm/configure.tgt     up to 1.1.1.3
external/gpl3/gcc/dist/libitm/libitm.info       up to 1.1.1.2
external/gpl3/gcc/dist/libmudflap/ChangeLog     up to 1.1.1.5
external/gpl3/gcc/dist/libobjc/ChangeLog        up to 1.1.1.6
external/gpl3/gcc/dist/libsanitizer/ChangeLog   up to 1.1.1.3
external/gpl3/gcc/dist/libsanitizer/configure.tgt up to 1.3
external/gpl3/gcc/dist/libsanitizer/asan/asan_intercepted_functions.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/asan/asan_internal.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/asan/asan_linux.cc up to 1.5
external/gpl3/gcc/dist/libsanitizer/asan/asan_malloc_linux.cc up to 1.2
external/gpl3/gcc/dist/libsanitizer/asan/asan_posix.cc up to 1.2
external/gpl3/gcc/dist/libsanitizer/interception/interception.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/interception/interception_linux.cc up to 1.3
external/gpl3/gcc/dist/libsanitizer/interception/interception_linux.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/interception/interception_type_test.cc up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_internal_defs.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_placement_new.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_posix.cc up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_procmaps.h up to 1.2
external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc up to 1.2
external/gpl3/gcc/dist/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc up to 1.2
external/gpl3/gcc/dist/libssp/ChangeLog         up to 1.1.1.5
external/gpl3/gcc/dist/libstdc++-v3/ChangeLog   up to 1.1.1.7
external/gpl3/gcc/dist/libstdc++-v3/configure.host up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/config/os/mingw32/os_defines.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/config/os/mingw32-w64/os_defines.h up to 1.1.1.2
external/gpl3/gcc/dist/libstdc++-v3/doc/html/manual/status.html up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_algo.h up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/include/std/functional up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/std/tuple up to 1.1.1.4
external/gpl3/gcc/dist/libstdc++-v3/include/tr1/functional up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/libsupc++/dyncast.cc up to 1.1.1.3
external/gpl3/gcc/dist/libstdc++-v3/libsupc++/eh_personality.cc up to 1.1.1.3
external/gpl3/gcc/dist/lto-plugin/ChangeLog     up to 1.1.1.5
external/gpl3/gcc/dist/maintainer-scripts/ChangeLog up to 1.1.1.6
external/gpl3/gcc/lib/Makefile                  up to 1.8
external/gpl3/gcc/lib/crtstuff/arch/coldfire.mk up to 1.3
external/gpl3/gcc/lib/crtstuff/arch/m68000.mk   up to 1.6
external/gpl3/gcc/lib/libbacktrace/arch/alpha/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/alpha/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/arm/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/arm/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/armeb/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/armeb/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/coldfire/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/coldfire/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/hppa/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/hppa/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/i386/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/i386/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/m68000/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/m68000/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/m68k/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/m68k/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/mips64eb/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/mips64eb/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/mips64el/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/mips64el/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/mipseb/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/mipseb/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/mipsel/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/mipsel/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/powerpc/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/powerpc/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/powerpc64/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/powerpc64/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/sh3eb/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/sh3eb/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/sh3el/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/sh3el/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/sparc/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/sparc/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/sparc64/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/sparc64/config.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/vax/backtrace-supported.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/vax/config.h up to 1.3
external/gpl3/gcc/lib/libbacktrace/arch/x86_64/backtrace-supported.h up to 1.2
external/gpl3/gcc/lib/libbacktrace/arch/x86_64/config.h up to 1.2
external/gpl3/gcc/lib/libgcc/Makefile.inc       up to 1.29
external/gpl3/gcc/lib/libgcc/arch/m68000/defs.mk up to 1.2
external/gpl3/gcc/lib/libgcc/arch/powerpc64/defs.mk up to 1.3
external/gpl3/gcc/lib/libgcc/libgcc_s/Makefile  up to 1.11
external/gpl3/gcc/lib/libgcc/libgcov/arch/alpha/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/arm/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/armeb/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/coldfire/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earm/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmeb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmhf/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmhfeb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv4/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv4eb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6eb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6hf/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv6hfeb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7eb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7hf/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/earmv7hfeb/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/hppa/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/i386/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/m68000/gcov-iov.h up to 1.5
external/gpl3/gcc/lib/libgcc/libgcov/arch/m68k/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/mips64eb/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/mips64el/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/mipseb/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/mipsel/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/powerpc/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/powerpc64/gcov-iov.h up to 1.4
external/gpl3/gcc/lib/libgcc/libgcov/arch/sh3eb/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/sh3el/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/sparc/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/sparc64/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/vax/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgcc/libgcov/arch/x86_64/gcov-iov.h up to 1.6
external/gpl3/gcc/lib/libgomp/arch/m68000/config.h up to 1.3
external/gpl3/gcc/lib/libgomp/arch/m68000/libgomp.spec up to 1.3
external/gpl3/gcc/lib/libiberty/arch/coldfire/config.h up to 1.3
external/gpl3/gcc/lib/libiberty/arch/m68000/config.h up to 1.3
external/gpl3/gcc/lib/liblto_plugin/Makefile    up to 1.3
external/gpl3/gcc/lib/libmudflap/Makefile       up to 1.6
external/gpl3/gcc/lib/libobjc/arch/m68000/config.h up to 1.3
external/gpl3/gcc/lib/libstdc++-v3/Makefile     up to 1.19
external/gpl3/gcc/lib/libstdc++-v3/arch/alpha/c++config.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/alpha/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/arm/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/arm/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/armeb/c++config.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/armeb/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/coldfire/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/coldfire/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earm/c++config.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/earm/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmeb/c++config.h up to 1.11
external/gpl3/gcc/lib/libstdc++-v3/arch/earmeb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhf/c++config.h up to 1.11
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhf/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhfeb/c++config.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/earmhfeb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4eb/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv4eb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6eb/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6eb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hf/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hfeb/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv6hfeb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7eb/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7eb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hf/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hf/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hfeb/c++config.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/earmv7hfeb/gstdint.h up to 1.7
external/gpl3/gcc/lib/libstdc++-v3/arch/hppa/c++config.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/hppa/gstdint.h up to 1.10
external/gpl3/gcc/lib/libstdc++-v3/arch/i386/c++config.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/i386/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/m68000/c++config.h up to 1.10
external/gpl3/gcc/lib/libstdc++-v3/arch/m68000/gstdint.h up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/m68k/c++config.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/m68k/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64eb/c++config.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64eb/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64el/c++config.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/mips64el/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/mipseb/c++config.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/mipseb/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/mipsel/c++config.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/mipsel/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc/c++config.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc64/c++config.h up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc64/defs.mk up to 1.3
external/gpl3/gcc/lib/libstdc++-v3/arch/powerpc64/gstdint.h up to 1.5
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3eb/c++config.h up to 1.13
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3eb/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3el/c++config.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/sh3el/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc/c++config.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc64/c++config.h up to 1.14
external/gpl3/gcc/lib/libstdc++-v3/arch/sparc64/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/vax/c++config.h up to 1.16
external/gpl3/gcc/lib/libstdc++-v3/arch/vax/gstdint.h up to 1.8
external/gpl3/gcc/lib/libstdc++-v3/arch/x86_64/c++config.h up to 1.15
external/gpl3/gcc/lib/libstdc++-v3/arch/x86_64/gstdint.h up to 1.9
external/gpl3/gcc/lib/libstdc++-v3/include/bits/arch/Makefile up to 1.3
external/gpl3/gcc/usr.bin/Makefile              up to 1.7
external/gpl3/gcc/usr.bin/backend/Makefile      up to 1.23
external/gpl3/gcc/usr.bin/frontend/Makefile     up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/alpha/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/alpha/configargs.h up to 1.15
external/gpl3/gcc/usr.bin/gcc/arch/alpha/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/arm/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/arm/configargs.h up to 1.17
external/gpl3/gcc/usr.bin/gcc/arch/arm/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/armeb/auto-host.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/armeb/configargs.h up to 1.17
external/gpl3/gcc/usr.bin/gcc/arch/armeb/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/coldfire/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/coldfire/bversion.h up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/coldfire/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/coldfire/defs.mk up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/coldfire/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/coldfire/tm.h up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/earm/auto-host.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earm/configargs.h up to 1.15
external/gpl3/gcc/usr.bin/gcc/arch/earm/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/configargs.h up to 1.11
external/gpl3/gcc/usr.bin/gcc/arch/earmeb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/auto-host.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/configargs.h up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/earmhf/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/configargs.h up to 1.10
external/gpl3/gcc/usr.bin/gcc/arch/earmhfeb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv4/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv4eb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6eb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hf/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv6hfeb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7eb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hf/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/configargs.h up to 1.9
external/gpl3/gcc/usr.bin/gcc/arch/earmv7hfeb/plugin-version.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/hppa/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/hppa/configargs.h up to 1.17
external/gpl3/gcc/usr.bin/gcc/arch/hppa/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/i386/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/i386/configargs.h up to 1.19
external/gpl3/gcc/usr.bin/gcc/arch/i386/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/m68000/auto-host.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/m68000/bversion.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/m68000/configargs.h up to 1.12
external/gpl3/gcc/usr.bin/gcc/arch/m68000/defs.mk up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/m68000/plugin-version.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/m68000/tm.h  up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/m68k/auto-host.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/m68k/configargs.h up to 1.14
external/gpl3/gcc/usr.bin/gcc/arch/m68k/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/configargs.h up to 1.15
external/gpl3/gcc/usr.bin/gcc/arch/mips64eb/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/auto-host.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/configargs.h up to 1.16
external/gpl3/gcc/usr.bin/gcc/arch/mips64el/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/configargs.h up to 1.15
external/gpl3/gcc/usr.bin/gcc/arch/mipseb/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/configargs.h up to 1.16
external/gpl3/gcc/usr.bin/gcc/arch/mipsel/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/configargs.h up to 1.21
external/gpl3/gcc/usr.bin/gcc/arch/powerpc/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/auto-host.h up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/bversion.h up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/configargs.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/defs.mk up to 1.4
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/gtyp-input.list up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/multilib.h up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/plugin-version.h up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/powerpc64/tm.h up to 1.3
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/configargs.h up to 1.16
external/gpl3/gcc/usr.bin/gcc/arch/sh3eb/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/configargs.h up to 1.18
external/gpl3/gcc/usr.bin/gcc/arch/sh3el/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/sparc/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/sparc/configargs.h up to 1.16
external/gpl3/gcc/usr.bin/gcc/arch/sparc/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/auto-host.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/configargs.h up to 1.17
external/gpl3/gcc/usr.bin/gcc/arch/sparc64/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/vax/auto-host.h up to 1.6
external/gpl3/gcc/usr.bin/gcc/arch/vax/configargs.h up to 1.17
external/gpl3/gcc/usr.bin/gcc/arch/vax/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/auto-host.h up to 1.5
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/configargs.h up to 1.20
external/gpl3/gcc/usr.bin/gcc/arch/x86_64/plugin-version.h up to 1.7
external/gpl3/gcc/usr.bin/libcpp/arch/alpha/config.h up to 1.3
external/gpl3/gcc/usr.bin/libcpp/arch/armeb/config.h up to 1.2
external/gpl3/gcc/usr.bin/libcpp/arch/x86_64/config.h up to 1.3
distrib/sets/lists/base/ad.arm			1.58
distrib/sets/lists/base/ad.arm			1.61
distrib/sets/lists/base/ad.mips			1.53
distrib/sets/lists/base/ad.mips			1.56
distrib/sets/lists/base/ad.powerpc		1.22
distrib/sets/lists/base/ad.powerpc		1.25
distrib/sets/lists/base/ad.powerpc		1.26
distrib/sets/lists/base/md.amd64		1.249
distrib/sets/lists/base/md.amd64		1.252
distrib/sets/lists/base/md.sparc64		1.237
distrib/sets/lists/base/md.sparc64		1.240
distrib/sets/lists/base/shl.mi			1.718
distrib/sets/lists/base/shl.mi			1.721
distrib/sets/lists/base/shl.mi			1.722
distrib/sets/lists/comp/ad.arm			1.62
distrib/sets/lists/comp/ad.mips			1.52
distrib/sets/lists/comp/ad.powerpc		1.74
distrib/sets/lists/comp/ad.powerpc		1.75
distrib/sets/lists/comp/md.amd64		1.226
distrib/sets/lists/comp/md.sparc64		1.189
distrib/sets/lists/comp/mi			1.1918
distrib/sets/lists/comp/mi			1.1919
distrib/sets/lists/comp/mi			1.1937
distrib/sets/lists/comp/mi			1.1937
distrib/sets/lists/comp/shl.mi			1.268
distrib/sets/lists/comp/shl.mi			1.268
distrib/sets/lists/comp/shl.mi			1.269
distrib/sets/lists/debug/ad.arm			1.47
distrib/sets/lists/debug/ad.arm			1.50
distrib/sets/lists/debug/ad.mips		1.43
distrib/sets/lists/debug/ad.mips		1.46
distrib/sets/lists/debug/ad.powerpc		1.23
distrib/sets/lists/debug/ad.powerpc		1.26
distrib/sets/lists/debug/md.amd64		1.67
distrib/sets/lists/debug/md.amd64		1.70
distrib/sets/lists/debug/md.evbmips		1.5
distrib/sets/lists/debug/md.sparc64		1.66
distrib/sets/lists/debug/md.sparc64		1.69
distrib/sets/lists/debug/mi			1.101
distrib/sets/lists/debug/mi			1.101
distrib/sets/lists/debug/mi			1.90
distrib/sets/lists/debug/mi			1.91
distrib/sets/lists/debug/shl.mi			1.77
distrib/sets/lists/debug/shl.mi			1.80
distrib/sets/lists/debug/shl.mi			1.81
lib/Makefile					1.216
lib/Makefile					1.217
lib/Makefile					1.218
lib/libexecinfo/Makefile			1.6
lib/libexecinfo/Makefile			1.7
lib/libexecinfo/Makefile			1.8
lib/libexecinfo/unwind.h			1.3
sys/lib/libunwind/Makefile.inc			1.10

Sync gcc and its libraries with -current, including the import
of gcc 4.8.4, fixes to the use of cpu specific string instructions
on powerpc and a branch delay slot fix for SH from upstream.
@
text
@a298 8
#define INIT_SCANF_NORMAL                                                      \
  INTERCEPT_FUNCTION(scanf);                                                   \
  INTERCEPT_FUNCTION(sscanf);                                                  \
  INTERCEPT_FUNCTION(fscanf);                                                  \
  INTERCEPT_FUNCTION(vscanf);                                                  \
  INTERCEPT_FUNCTION(vsscanf);                                                 \
  INTERCEPT_FUNCTION(vfscanf);                                                 \

d308 1
d310 7
a316 2

#define INIT_SCANF_ISOC99						       \
a322 7
#else
#define INIT_SCANF_ISOC99
#endif

#define INIT_SCANF							       \
  INIT_SCANF_NORMAL							       \
  INIT_SCANF_ISOC99
@


1.1.1.1.8.1
log
@file sanitizer_common_interceptors.inc was added on branch tls-maxphys on 2014-08-19 23:54:37 +0000
@
text
@d1 337
@


1.1.1.1.8.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 337
//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Common function interceptors for tools like AddressSanitizer,
// ThreadSanitizer, MemorySanitizer, etc.
//
// This file should be included into the tool's interceptor file,
// which has to define it's own macros:
//   COMMON_INTERCEPTOR_ENTER
//   COMMON_INTERCEPTOR_READ_RANGE
//   COMMON_INTERCEPTOR_WRITE_RANGE
//   COMMON_INTERCEPTOR_FD_ACQUIRE
//   COMMON_INTERCEPTOR_FD_RELEASE
//   COMMON_INTERCEPTOR_SET_THREAD_NAME
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
#include "sanitizer_platform_interceptors.h"

#include <stdarg.h>

#ifdef _WIN32
#define va_copy(dst, src) ((dst) = (src))
#endif // _WIN32

#if SANITIZER_INTERCEPT_READ
INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
  SSIZE_T res = REAL(read)(fd, ptr, count);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_READ INTERCEPT_FUNCTION(read)
#else
#define INIT_READ
#endif

#if SANITIZER_INTERCEPT_PREAD
INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREAD INTERCEPT_FUNCTION(pread)
#else
#define INIT_PREAD
#endif

#if SANITIZER_INTERCEPT_PREAD64
INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
#else
#define INIT_PREAD64
#endif

#if SANITIZER_INTERCEPT_WRITE
INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(write)(fd, ptr, count);
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_WRITE INTERCEPT_FUNCTION(write)
#else
#define INIT_WRITE
#endif

#if SANITIZER_INTERCEPT_PWRITE
INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
#else
#define INIT_PWRITE
#endif

#if SANITIZER_INTERCEPT_PWRITE64
INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
#else
#define INIT_PWRITE64
#endif

#if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option,
            unsigned long arg2, unsigned long arg3,   // NOLINT
            unsigned long arg4, unsigned long arg5) { // NOLINT
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
  static const int PR_SET_NAME = 15;
  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
  if (option == PR_SET_NAME) {
    char buff[16];
    internal_strncpy(buff, (char *)arg2, 15);
    buff[15] = 0;
    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
  }
  return res;
}
#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
#else
#define INIT_PRCTL
#endif // SANITIZER_INTERCEPT_PRCTL

#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
INTERCEPTOR(void *, localtime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
  void *res = REAL(localtime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
  void *res = REAL(localtime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(void *, gmtime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
  void *res = REAL(gmtime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
  void *res = REAL(gmtime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(char *, ctime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
  char *res = REAL(ctime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
  char *res = REAL(ctime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, asctime, void *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
  char *res = REAL(asctime)(tm);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, asctime_r, void *tm, char *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
  char *res = REAL(asctime_r)(tm, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_LOCALTIME_AND_FRIENDS               \
  INTERCEPT_FUNCTION(localtime);                 \
  INTERCEPT_FUNCTION(localtime_r);               \
  INTERCEPT_FUNCTION(gmtime);                    \
  INTERCEPT_FUNCTION(gmtime_r);                  \
  INTERCEPT_FUNCTION(ctime);                     \
  INTERCEPT_FUNCTION(ctime_r);                   \
  INTERCEPT_FUNCTION(asctime);                   \
  INTERCEPT_FUNCTION(asctime_r);
#else
#define INIT_LOCALTIME_AND_FRIENDS
#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS

#if SANITIZER_INTERCEPT_SCANF

#include "sanitizer_common_interceptors_scanf.inc"

#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
    va_list aq;                                                                \
    va_copy(aq, ap);                                                           \
    int res = REAL(vname)(__VA_ARGS__);                                        \
    if (res > 0)                                                               \
      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
    va_end(aq);                                                                \
    return res;                                                                \
  }

INTERCEPTOR(int, vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)

INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)

INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)

#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)

INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
            va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF

#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__);                          \
    va_list ap;                                                                \
    va_start(ap, format);                                                      \
    int res = vname(__VA_ARGS__, ap);                                          \
    va_end(ap);                                                                \
    return res;                                                                \
  }

INTERCEPTOR(int, scanf, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)

INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)

INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)

#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)

INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)

INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
#endif

#define INIT_SCANF                                                             \
  INTERCEPT_FUNCTION(scanf);                                                   \
  INTERCEPT_FUNCTION(sscanf);                                                  \
  INTERCEPT_FUNCTION(fscanf);                                                  \
  INTERCEPT_FUNCTION(vscanf);                                                  \
  INTERCEPT_FUNCTION(vsscanf);                                                 \
  INTERCEPT_FUNCTION(vfscanf);                                                 \
  INTERCEPT_FUNCTION(__isoc99_scanf);                                          \
  INTERCEPT_FUNCTION(__isoc99_sscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_fscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_vscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_vsscanf);                                        \
  INTERCEPT_FUNCTION(__isoc99_vfscanf);

#else
#define INIT_SCANF
#endif

#define SANITIZER_COMMON_INTERCEPTORS_INIT                                     \
  INIT_READ;                                                                   \
  INIT_PREAD;                                                                  \
  INIT_PREAD64;                                                                \
  INIT_PRCTL;                                                                  \
  INIT_WRITE;                                                                  \
  INIT_PWRITE;                                                                 \
  INIT_PWRITE64;                                                               \
  INIT_LOCALTIME_AND_FRIENDS;                                                  \
  INIT_SCANF;
@


1.1.1.1.4.1
log
@file sanitizer_common_interceptors.inc was added on branch yamt-pagecache on 2014-05-22 16:37:02 +0000
@
text
@d1 337
@


1.1.1.1.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 337
//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Common function interceptors for tools like AddressSanitizer,
// ThreadSanitizer, MemorySanitizer, etc.
//
// This file should be included into the tool's interceptor file,
// which has to define it's own macros:
//   COMMON_INTERCEPTOR_ENTER
//   COMMON_INTERCEPTOR_READ_RANGE
//   COMMON_INTERCEPTOR_WRITE_RANGE
//   COMMON_INTERCEPTOR_FD_ACQUIRE
//   COMMON_INTERCEPTOR_FD_RELEASE
//   COMMON_INTERCEPTOR_SET_THREAD_NAME
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
#include "sanitizer_platform_interceptors.h"

#include <stdarg.h>

#ifdef _WIN32
#define va_copy(dst, src) ((dst) = (src))
#endif // _WIN32

#if SANITIZER_INTERCEPT_READ
INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
  SSIZE_T res = REAL(read)(fd, ptr, count);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_READ INTERCEPT_FUNCTION(read)
#else
#define INIT_READ
#endif

#if SANITIZER_INTERCEPT_PREAD
INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
  SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREAD INTERCEPT_FUNCTION(pread)
#else
#define INIT_PREAD
#endif

#if SANITIZER_INTERCEPT_PREAD64
INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
  SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
  if (res >= 0 && fd >= 0)
    COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
  return res;
}
#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
#else
#define INIT_PREAD64
#endif

#if SANITIZER_INTERCEPT_WRITE
INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(write)(fd, ptr, count);
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_WRITE INTERCEPT_FUNCTION(write)
#else
#define INIT_WRITE
#endif

#if SANITIZER_INTERCEPT_PWRITE
INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
#else
#define INIT_PWRITE
#endif

#if SANITIZER_INTERCEPT_PWRITE64
INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
            OFF64_T offset) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
  if (fd >= 0)
    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
  SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
  if (res > 0)
    COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
  return res;
}
#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
#else
#define INIT_PWRITE64
#endif

#if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option,
            unsigned long arg2, unsigned long arg3,   // NOLINT
            unsigned long arg4, unsigned long arg5) { // NOLINT
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
  static const int PR_SET_NAME = 15;
  int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
  if (option == PR_SET_NAME) {
    char buff[16];
    internal_strncpy(buff, (char *)arg2, 15);
    buff[15] = 0;
    COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
  }
  return res;
}
#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
#else
#define INIT_PRCTL
#endif // SANITIZER_INTERCEPT_PRCTL

#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
INTERCEPTOR(void *, localtime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
  void *res = REAL(localtime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
  void *res = REAL(localtime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(void *, gmtime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
  void *res = REAL(gmtime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
  void *res = REAL(gmtime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz);
  }
  return res;
}
INTERCEPTOR(char *, ctime, unsigned long *timep) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
  char *res = REAL(ctime)(timep);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
  char *res = REAL(ctime_r)(timep, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, asctime, void *tm) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
  char *res = REAL(asctime)(tm);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
INTERCEPTOR(char *, asctime_r, void *tm, char *result) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
  char *res = REAL(asctime_r)(tm, result);
  if (res) {
    COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz);
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
  }
  return res;
}
#define INIT_LOCALTIME_AND_FRIENDS               \
  INTERCEPT_FUNCTION(localtime);                 \
  INTERCEPT_FUNCTION(localtime_r);               \
  INTERCEPT_FUNCTION(gmtime);                    \
  INTERCEPT_FUNCTION(gmtime_r);                  \
  INTERCEPT_FUNCTION(ctime);                     \
  INTERCEPT_FUNCTION(ctime_r);                   \
  INTERCEPT_FUNCTION(asctime);                   \
  INTERCEPT_FUNCTION(asctime_r);
#else
#define INIT_LOCALTIME_AND_FRIENDS
#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS

#if SANITIZER_INTERCEPT_SCANF

#include "sanitizer_common_interceptors_scanf.inc"

#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...)                    \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__);                         \
    va_list aq;                                                                \
    va_copy(aq, ap);                                                           \
    int res = REAL(vname)(__VA_ARGS__);                                        \
    if (res > 0)                                                               \
      scanf_common(ctx, res, allowGnuMalloc, format, aq);                      \
    va_end(aq);                                                                \
    return res;                                                                \
  }

INTERCEPTOR(int, vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)

INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)

INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)

#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)

INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
            va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
#endif  // SANITIZER_INTERCEPT_ISOC99_SCANF

#define SCANF_INTERCEPTOR_IMPL(name, vname, ...)                               \
  {                                                                            \
    void *ctx;                                                                 \
    COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__);                          \
    va_list ap;                                                                \
    va_start(ap, format);                                                      \
    int res = vname(__VA_ARGS__, ap);                                          \
    va_end(ap);                                                                \
    return res;                                                                \
  }

INTERCEPTOR(int, scanf, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)

INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)

INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)

#if SANITIZER_INTERCEPT_ISOC99_SCANF
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)

INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)

INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
#endif

#define INIT_SCANF                                                             \
  INTERCEPT_FUNCTION(scanf);                                                   \
  INTERCEPT_FUNCTION(sscanf);                                                  \
  INTERCEPT_FUNCTION(fscanf);                                                  \
  INTERCEPT_FUNCTION(vscanf);                                                  \
  INTERCEPT_FUNCTION(vsscanf);                                                 \
  INTERCEPT_FUNCTION(vfscanf);                                                 \
  INTERCEPT_FUNCTION(__isoc99_scanf);                                          \
  INTERCEPT_FUNCTION(__isoc99_sscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_fscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_vscanf);                                         \
  INTERCEPT_FUNCTION(__isoc99_vsscanf);                                        \
  INTERCEPT_FUNCTION(__isoc99_vfscanf);

#else
#define INIT_SCANF
#endif

#define SANITIZER_COMMON_INTERCEPTORS_INIT                                     \
  INIT_READ;                                                                   \
  INIT_PREAD;                                                                  \
  INIT_PREAD64;                                                                \
  INIT_PRCTL;                                                                  \
  INIT_WRITE;                                                                  \
  INIT_PWRITE;                                                                 \
  INIT_PWRITE64;                                                               \
  INIT_LOCALTIME_AND_FRIENDS;                                                  \
  INIT_SCANF;
@


