blob: 0dfc9f0a70fb0b9a6fa330022ebff435b452a448 [file] [log] [blame]
Alexey Samsonove5f58952012-06-04 13:50:10 +00001//===-- asan_interceptors.cc ----------------------------------------------===//
Kostya Serebryany1e172b42011-11-30 01:07:02 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
Kostya Serebryanyd47189c2012-01-11 02:32:40 +000012// Intercept various libc functions.
Kostya Serebryany1e172b42011-11-30 01:07:02 +000013//===----------------------------------------------------------------------===//
14#include "asan_interceptors.h"
15
16#include "asan_allocator.h"
Alexander Potapenko05bf9a52012-08-15 15:24:48 +000017#include "asan_intercepted_functions.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000018#include "asan_internal.h"
19#include "asan_mapping.h"
Alexey Samsonov7e843492013-03-28 15:42:43 +000020#include "asan_poisoning.h"
Alexey Samsonov487fee72012-08-09 08:32:33 +000021#include "asan_report.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000022#include "asan_stack.h"
23#include "asan_stats.h"
Alexey Samsonov5b290182012-02-08 19:52:01 +000024#include "interception/interception.h"
Alexey Samsonovc0d78c12012-06-04 13:27:49 +000025#include "sanitizer_common/sanitizer_libc.h"
26
Kostya Serebryany1e172b42011-11-30 01:07:02 +000027namespace __asan {
28
Kostya Serebryanya84805f2013-02-21 07:07:39 +000029// Return true if we can quickly decide that the region is unpoisoned.
30static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
31 if (size == 0) return true;
32 if (size <= 32)
33 return !AddressIsPoisoned(beg) &&
34 !AddressIsPoisoned(beg + size - 1) &&
35 !AddressIsPoisoned(beg + size / 2);
36 return false;
37}
38
Kostya Serebryany1e172b42011-11-30 01:07:02 +000039// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
40// and ASAN_WRITE_RANGE as macro instead of function so
41// that no extra frames are created, and stack trace contains
42// relevant information only.
Kostya Serebryanyeb280932012-12-28 15:24:16 +000043// We check all shadow bytes.
Evgeniy Stepanov589dcda2013-02-05 14:32:03 +000044#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
45 uptr __offset = (uptr)(offset); \
46 uptr __size = (uptr)(size); \
Kostya Serebryany1b057b22013-02-26 07:25:18 +000047 uptr __bad = 0; \
Kostya Serebryanya84805f2013-02-21 07:07:39 +000048 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
Kostya Serebryany1b057b22013-02-26 07:25:18 +000049 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
Evgeniy Stepanov589dcda2013-02-05 14:32:03 +000050 GET_CURRENT_PC_BP_SP; \
Kostya Serebryany1b057b22013-02-26 07:25:18 +000051 __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
Evgeniy Stepanov589dcda2013-02-05 14:32:03 +000052 } \
53 } while (0)
Kostya Serebryany1e172b42011-11-30 01:07:02 +000054
Kostya Serebryanyeb280932012-12-28 15:24:16 +000055#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
Evgeniy Stepanov341b9e62013-06-28 11:02:43 +000056#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
Kostya Serebryany1e172b42011-11-30 01:07:02 +000057
58// Behavior of functions like "memcpy" or "strcpy" is undefined
59// if memory intervals overlap. We report error in this case.
60// Macro is used to avoid creation of new frames.
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000061static inline bool RangesOverlap(const char *offset1, uptr length1,
62 const char *offset2, uptr length2) {
Kostya Serebryany0985ca22011-12-28 19:08:49 +000063 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
Kostya Serebryany1e172b42011-11-30 01:07:02 +000064}
Kostya Serebryanyc5e72a32011-12-28 19:24:31 +000065#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
Kostya Serebryany1e172b42011-11-30 01:07:02 +000066 const char *offset1 = (const char*)_offset1; \
67 const char *offset2 = (const char*)_offset2; \
Kostya Serebryany0985ca22011-12-28 19:08:49 +000068 if (RangesOverlap(offset1, length1, offset2, length2)) { \
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000069 GET_STACK_TRACE_FATAL_HERE; \
Alexey Samsonov487fee72012-08-09 08:32:33 +000070 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
71 offset2, length2, &stack); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +000072 } \
Kostya Serebryanye1301912011-12-05 18:56:29 +000073} while (0)
Kostya Serebryany1e172b42011-11-30 01:07:02 +000074
Kostya Serebryanye1301912011-12-05 18:56:29 +000075#define ENSURE_ASAN_INITED() do { \
76 CHECK(!asan_init_is_running); \
77 if (!asan_inited) { \
78 __asan_init(); \
79 } \
80} while (0)
Kostya Serebryany1e172b42011-11-30 01:07:02 +000081
Alexey Samsonovc9256972012-06-15 13:09:52 +000082static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
Alexey Samsonov81a7a4a2012-03-24 09:10:50 +000083#if ASAN_INTERCEPT_STRNLEN
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000084 if (REAL(strnlen) != 0) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +000085 return REAL(strnlen)(s, maxlen);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000086 }
Alexey Samsonovf2598fc2012-02-02 10:39:40 +000087#endif
Alexey Samsonovc9256972012-06-15 13:09:52 +000088 return internal_strnlen(s, maxlen);
Kostya Serebryanya4ccf872012-01-09 22:20:49 +000089}
Kostya Serebryany1e172b42011-11-30 01:07:02 +000090
Kostya Serebryanyc20b3212013-01-18 06:43:13 +000091void SetThreadName(const char *name) {
Alexey Samsonov89c13842013-03-20 09:23:28 +000092 AsanThread *t = GetCurrentThread();
Kostya Serebryanyc20b3212013-01-18 06:43:13 +000093 if (t)
Alexey Samsonovdef1be92013-03-21 11:23:41 +000094 asanThreadRegistry().SetThreadName(t->tid(), name);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +000095}
96
Dmitry Vyukov8cde99f2013-10-03 15:43:59 +000097int OnExit() {
Dmitry Vyukov14dd9802013-10-03 15:22:29 +000098 // FIXME: ask frontend whether we need to return failure.
99 return 0;
100}
101
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000102} // namespace __asan
103
104// ---------------------- Wrappers ---------------- {{{1
105using namespace __asan; // NOLINT
106
Evgeniy Stepanov12eb79d2013-07-09 09:53:37 +0000107DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
108DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
109
Evgeniy Stepanov3fa122e2013-07-09 12:07:59 +0000110#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
111 do { \
112 } while (false)
Evgeniy Stepanov82a90802013-01-18 13:12:56 +0000113#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
114 ASAN_WRITE_RANGE(ptr, size)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000115#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
Evgeniy Stepanov9d1525e2013-05-29 09:09:58 +0000116#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
117 do { \
118 if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \
119 ctx = 0; \
120 (void) ctx; \
121 ENSURE_ASAN_INITED(); \
Evgeniy Stepanov82a90802013-01-18 13:12:56 +0000122 } while (false)
Evgeniy Stepanov9d1525e2013-05-29 09:09:58 +0000123#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
124 do { \
125 } while (false)
126#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
127 do { \
128 } while (false)
129#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
130 do { \
131 } while (false)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000132#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
Dmitry Vyukov5cf2c462013-10-29 10:30:39 +0000133#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
134 asanThreadRegistry().SetThreadNameByUserId(thread, name)
Evgeniy Stepanove18e3f02013-08-12 13:19:53 +0000135#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
Dmitry Vyukov14dd9802013-10-03 15:22:29 +0000136#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
Evgeniy Stepanov4f32c0b2013-01-18 13:01:18 +0000137#include "sanitizer_common/sanitizer_common_interceptors.inc"
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000138
Evgeniy Stepanov881b6772013-04-12 14:57:03 +0000139#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
140#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
Evgeniy Stepanovae4e6fd2013-07-09 09:29:19 +0000141#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
142 do { \
Evgeniy Stepanovdfab31b2013-10-29 18:29:39 +0000143 (void)(p); \
144 (void)(s); \
Evgeniy Stepanovae4e6fd2013-07-09 09:29:19 +0000145 } while (false)
146#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
147 do { \
Evgeniy Stepanovdfab31b2013-10-29 18:29:39 +0000148 (void)(p); \
149 (void)(s); \
Evgeniy Stepanovae4e6fd2013-07-09 09:29:19 +0000150 } while (false)
Evgeniy Stepanov881b6772013-04-12 14:57:03 +0000151#include "sanitizer_common/sanitizer_common_syscalls.inc"
152
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000153static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000154 AsanThread *t = (AsanThread*)arg;
Alexey Samsonov89c13842013-03-20 09:23:28 +0000155 SetCurrentThread(t);
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000156 return t->ThreadStart(GetTid());
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000157}
158
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000159#if ASAN_INTERCEPT_PTHREAD_CREATE
Evgeniy Stepanovb8ef9252012-02-22 12:31:25 +0000160INTERCEPTOR(int, pthread_create, void *thread,
161 void *attr, void *(*start_routine)(void*), void *arg) {
Sergey Matveevc6ac98d2013-07-08 12:57:24 +0000162 EnsureMainThreadIDIsCorrect();
Alexey Samsonovbdd09662013-04-23 13:57:35 +0000163 // Strict init-order checking in thread-hostile.
Alexey Samsonov9465cbd2013-07-01 16:16:41 +0000164 if (flags()->strict_init_order)
165 StopInitOrderChecking();
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000166 GET_STACK_TRACE_THREAD;
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000167 int detached = 0;
168 if (attr != 0)
169 pthread_attr_getdetachstate(attr, &detached);
170
Alexey Samsonov89c13842013-03-20 09:23:28 +0000171 u32 current_tid = GetCurrentTidOrInvalid();
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000172 AsanThread *t = AsanThread::Create(start_routine, arg);
173 CreateThreadContextArgs args = { t, &stack };
174 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000175 return REAL(pthread_create)(thread, attr, asan_thread_start, t);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000176}
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000177#endif // ASAN_INTERCEPT_PTHREAD_CREATE
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000178
Alexey Samsonov34a32022012-03-26 09:07:29 +0000179#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000180INTERCEPTOR(void*, signal, int signum, void *handler) {
Alexey Samsonov332bf332013-04-25 10:52:15 +0000181 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
Alexander Potapenko034bda52012-04-16 08:33:01 +0000182 return REAL(signal)(signum, handler);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000183 }
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000184 return 0;
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000185}
186
Alexey Samsonovda13ba82012-02-16 17:00:45 +0000187INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
188 struct sigaction *oldact) {
Alexey Samsonov332bf332013-04-25 10:52:15 +0000189 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
Alexander Potapenko034bda52012-04-16 08:33:01 +0000190 return REAL(sigaction)(signum, act, oldact);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000191 }
Alexander Potapenko034bda52012-04-16 08:33:01 +0000192 return 0;
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000193}
Evgeniy Stepanove1ba0002013-03-19 15:26:41 +0000194#elif SANITIZER_POSIX
Alexey Samsonov34a32022012-03-26 09:07:29 +0000195// We need to have defined REAL(sigaction) on posix systems.
196DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
Alexey Samsonovfdde5a92013-06-10 14:17:08 +0000197 struct sigaction *oldact)
Alexey Samsonov34a32022012-03-26 09:07:29 +0000198#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000199
Alexey Samsonov08700282012-11-23 09:46:34 +0000200#if ASAN_INTERCEPT_SWAPCONTEXT
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000201static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
202 // Align to page size.
203 uptr PageSize = GetPageSizeCached();
204 uptr bottom = stack & ~(PageSize - 1);
205 ssize += stack - bottom;
206 ssize = RoundUpTo(ssize, PageSize);
207 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
Kostya Serebryany541cfb12013-01-18 11:30:36 +0000208 if (ssize && ssize <= kMaxSaneContextStackSize) {
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000209 PoisonShadow(bottom, ssize, 0);
210 }
211}
212
Alexey Samsonov08700282012-11-23 09:46:34 +0000213INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
214 struct ucontext_t *ucp) {
215 static bool reported_warning = false;
216 if (!reported_warning) {
217 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
218 "functions and may produce false positives in some cases!\n");
219 reported_warning = true;
220 }
221 // Clear shadow memory for new context (it may share stack
222 // with current context).
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000223 uptr stack, ssize;
224 ReadContextStack(ucp, &stack, &ssize);
225 ClearShadowMemoryForContextStack(stack, ssize);
Alexey Samsonov08700282012-11-23 09:46:34 +0000226 int res = REAL(swapcontext)(oucp, ucp);
227 // swapcontext technically does not return, but program may swap context to
228 // "oucp" later, that would look as if swapcontext() returned 0.
229 // We need to clear shadow for ucp once again, as it may be in arbitrary
230 // state.
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000231 ClearShadowMemoryForContextStack(stack, ssize);
Alexey Samsonov08700282012-11-23 09:46:34 +0000232 return res;
233}
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000234#endif // ASAN_INTERCEPT_SWAPCONTEXT
Alexey Samsonov08700282012-11-23 09:46:34 +0000235
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000236INTERCEPTOR(void, longjmp, void *env, int val) {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000237 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000238 REAL(longjmp)(env, val);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000239}
240
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000241#if ASAN_INTERCEPT__LONGJMP
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000242INTERCEPTOR(void, _longjmp, void *env, int val) {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000243 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000244 REAL(_longjmp)(env, val);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000245}
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000246#endif
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000247
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000248#if ASAN_INTERCEPT_SIGLONGJMP
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000249INTERCEPTOR(void, siglongjmp, void *env, int val) {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000250 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000251 REAL(siglongjmp)(env, val);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000252}
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000253#endif
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000254
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000255#if ASAN_INTERCEPT___CXA_THROW
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000256INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000257 CHECK(REAL(__cxa_throw));
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000258 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000259 REAL(__cxa_throw)(a, b, c);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000260}
261#endif
262
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000263// intercept mlock and friends.
264// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
265// All functions return 0 (success).
266static void MlockIsUnsupported() {
Timur Iskhodzhanov8d2438a2013-05-29 17:26:25 +0000267 static bool printed = false;
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000268 if (printed) return;
269 printed = true;
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000270 if (common_flags()->verbosity > 0) {
Timur Iskhodzhanoveaca82c2013-07-15 16:11:39 +0000271 Printf("INFO: AddressSanitizer ignores "
272 "mlock/mlockall/munlock/munlockall\n");
273 }
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000274}
Alexey Samsonov3389b8e2012-01-30 13:42:44 +0000275
Alexander Potapenko00f1c092012-08-15 09:22:57 +0000276INTERCEPTOR(int, mlock, const void *addr, uptr len) {
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000277 MlockIsUnsupported();
278 return 0;
279}
Alexey Samsonov3389b8e2012-01-30 13:42:44 +0000280
Alexander Potapenko00f1c092012-08-15 09:22:57 +0000281INTERCEPTOR(int, munlock, const void *addr, uptr len) {
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000282 MlockIsUnsupported();
283 return 0;
284}
Alexey Samsonov3389b8e2012-01-30 13:42:44 +0000285
Alexander Potapenko00f1c092012-08-15 09:22:57 +0000286INTERCEPTOR(int, mlockall, int flags) {
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000287 MlockIsUnsupported();
288 return 0;
289}
Alexey Samsonov3389b8e2012-01-30 13:42:44 +0000290
Alexander Potapenko00f1c092012-08-15 09:22:57 +0000291INTERCEPTOR(int, munlockall, void) {
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000292 MlockIsUnsupported();
293 return 0;
294}
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000295
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000296static inline int CharCmp(unsigned char c1, unsigned char c2) {
297 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
298}
299
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000300INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
Alexander Potapenko50f2e302012-10-05 12:11:06 +0000301 if (!asan_inited) return internal_memcmp(a1, a2, size);
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000302 ENSURE_ASAN_INITED();
Kostya Serebryany1b057b22013-02-26 07:25:18 +0000303 if (flags()->replace_intrin) {
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000304 if (flags()->strict_memcmp) {
305 // Check the entire regions even if the first bytes of the buffers are
306 // different.
307 ASAN_READ_RANGE(a1, size);
308 ASAN_READ_RANGE(a2, size);
309 // Fallthrough to REAL(memcmp) below.
310 } else {
311 unsigned char c1 = 0, c2 = 0;
312 const unsigned char *s1 = (const unsigned char*)a1;
313 const unsigned char *s2 = (const unsigned char*)a2;
314 uptr i;
315 for (i = 0; i < size; i++) {
316 c1 = s1[i];
317 c2 = s2[i];
318 if (c1 != c2) break;
319 }
320 ASAN_READ_RANGE(s1, Min(i + 1, size));
321 ASAN_READ_RANGE(s2, Min(i + 1, size));
322 return CharCmp(c1, c2);
323 }
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000324 }
Kostya Serebryany1b057b22013-02-26 07:25:18 +0000325 return REAL(memcmp(a1, a2, size));
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000326}
327
Alexander Potapenkod4d70402013-09-20 10:56:34 +0000328#define MEMMOVE_BODY { \
329 if (!asan_inited) return internal_memmove(to, from, size); \
330 if (asan_init_is_running) { \
331 return REAL(memmove)(to, from, size); \
332 } \
333 ENSURE_ASAN_INITED(); \
334 if (flags()->replace_intrin) { \
335 ASAN_READ_RANGE(from, size); \
336 ASAN_WRITE_RANGE(to, size); \
337 } \
Alexander Potapenkod4d70402013-09-20 10:56:34 +0000338 return internal_memmove(to, from, size); \
339}
340
341INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) MEMMOVE_BODY
342
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000343INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
Alexander Potapenkod4d70402013-09-20 10:56:34 +0000344#if !SANITIZER_MAC
Alexander Potapenko50f2e302012-10-05 12:11:06 +0000345 if (!asan_inited) return internal_memcpy(to, from, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000346 // memcpy is called during __asan_init() from the internals
347 // of printf(...).
348 if (asan_init_is_running) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000349 return REAL(memcpy)(to, from, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000350 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000351 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000352 if (flags()->replace_intrin) {
Kostya Serebryanyc655cfa2012-01-17 18:43:52 +0000353 if (to != from) {
354 // We do not treat memcpy with to==from as a bug.
355 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
356 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
357 }
Alexander Potapenkoc75d8482012-12-10 16:02:13 +0000358 ASAN_READ_RANGE(from, size);
359 ASAN_WRITE_RANGE(to, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000360 }
Alexander Potapenkod4d70402013-09-20 10:56:34 +0000361 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8, so
362 // calling REAL(memcpy) here leads to infinite recursion.
Alexander Potapenkof1673e62012-10-15 15:34:41 +0000363 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
364 return internal_memcpy(to, from, size);
Alexander Potapenkod4d70402013-09-20 10:56:34 +0000365#else
366 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
367 // with WRAP(memcpy). As a result, false positives are reported for memmove()
368 // calls. If we just disable error reporting with
369 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
370 // internal_memcpy(), which may lead to crashes, see
371 // http://llvm.org/bugs/show_bug.cgi?id=16362.
372 MEMMOVE_BODY
373#endif // !SANITIZER_MAC
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000374}
375
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000376INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
Alexander Potapenko50f2e302012-10-05 12:11:06 +0000377 if (!asan_inited) return internal_memset(block, c, size);
Alexander Potapenkoebb97022012-03-29 12:20:47 +0000378 // memset is called inside Printf.
Kostya Serebryanye1301912011-12-05 18:56:29 +0000379 if (asan_init_is_running) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000380 return REAL(memset)(block, c, size);
Kostya Serebryanye1301912011-12-05 18:56:29 +0000381 }
382 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000383 if (flags()->replace_intrin) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000384 ASAN_WRITE_RANGE(block, size);
385 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000386 return REAL(memset)(block, c, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000387}
388
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000389INTERCEPTOR(char*, strchr, const char *str, int c) {
Alexander Potapenko50f2e302012-10-05 12:11:06 +0000390 if (!asan_inited) return internal_strchr(str, c);
Alexander Potapenko8d6e3f72012-09-10 08:35:12 +0000391 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
392 // used.
393 if (asan_init_is_running) {
394 return REAL(strchr)(str, c);
395 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000396 ENSURE_ASAN_INITED();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000397 char *result = REAL(strchr)(str, c);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000398 if (flags()->replace_str) {
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000399 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000400 ASAN_READ_RANGE(str, bytes_read);
401 }
402 return result;
403}
404
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000405#if ASAN_INTERCEPT_INDEX
406# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
Evgeniy Stepanov4b0c5f22012-02-13 12:12:32 +0000407INTERCEPTOR(char*, index, const char *string, int c)
Alexander Potapenko72bbfd42013-02-21 15:15:43 +0000408 ALIAS(WRAPPER_NAME(strchr));
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000409# else
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000410# if SANITIZER_MAC
Alexander Potapenko50a002e2013-02-21 14:41:16 +0000411DECLARE_REAL(char*, index, const char *string, int c)
412OVERRIDE_FUNCTION(index, strchr);
413# else
Alexey Samsonovfdde5a92013-06-10 14:17:08 +0000414DEFINE_REAL(char*, index, const char *string, int c)
Alexander Potapenko50a002e2013-02-21 14:41:16 +0000415# endif
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000416# endif
417#endif // ASAN_INTERCEPT_INDEX
Kostya Serebryanyaf0f01d2011-12-28 02:24:50 +0000418
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000419// For both strcat() and strncat() we need to check the validity of |to|
420// argument irrespective of the |from| length.
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000421INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000422 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000423 if (flags()->replace_str) {
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000424 uptr from_length = REAL(strlen)(from);
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000425 ASAN_READ_RANGE(from, from_length + 1);
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000426 uptr to_length = REAL(strlen)(to);
427 ASAN_READ_RANGE(to, to_length);
428 ASAN_WRITE_RANGE(to + to_length, from_length + 1);
429 // If the copying actually happens, the |from| string should not overlap
430 // with the resulting string starting at |to|, which has a length of
431 // to_length + from_length + 1.
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000432 if (from_length > 0) {
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000433 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
434 from, from_length + 1);
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000435 }
436 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000437 return REAL(strcat)(to, from); // NOLINT
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000438}
439
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000440INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
441 ENSURE_ASAN_INITED();
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000442 if (flags()->replace_str) {
Alexey Samsonovc9256972012-06-15 13:09:52 +0000443 uptr from_length = MaybeRealStrnlen(from, size);
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000444 uptr copy_length = Min(size, from_length + 1);
445 ASAN_READ_RANGE(from, copy_length);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000446 uptr to_length = REAL(strlen)(to);
447 ASAN_READ_RANGE(to, to_length);
448 ASAN_WRITE_RANGE(to + to_length, from_length + 1);
449 if (from_length > 0) {
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000450 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
451 from, copy_length);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000452 }
453 }
454 return REAL(strncat)(to, from, size);
455}
456
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000457INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000458#if SANITIZER_MAC
Alexander Potapenkobeda44f2012-08-17 10:08:51 +0000459 if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT
Alexander Potapenko0ef53102012-08-17 09:00:08 +0000460#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000461 // strcpy is called from malloc_default_purgeable_zone()
462 // in __asan::ReplaceSystemAlloc() on Mac.
463 if (asan_init_is_running) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000464 return REAL(strcpy)(to, from); // NOLINT
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000465 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000466 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000467 if (flags()->replace_str) {
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000468 uptr from_size = REAL(strlen)(from) + 1;
Kostya Serebryanyc5e72a32011-12-28 19:24:31 +0000469 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000470 ASAN_READ_RANGE(from, from_size);
471 ASAN_WRITE_RANGE(to, from_size);
472 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000473 return REAL(strcpy)(to, from); // NOLINT
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000474}
475
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000476#if ASAN_INTERCEPT_STRDUP
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000477INTERCEPTOR(char*, strdup, const char *s) {
Alexander Potapenko50f2e302012-10-05 12:11:06 +0000478 if (!asan_inited) return internal_strdup(s);
Kostya Serebryanye1301912011-12-05 18:56:29 +0000479 ENSURE_ASAN_INITED();
Alexey Samsonovd530d892013-06-21 14:41:59 +0000480 uptr length = REAL(strlen)(s);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000481 if (flags()->replace_str) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000482 ASAN_READ_RANGE(s, length + 1);
483 }
Alexey Samsonovd530d892013-06-21 14:41:59 +0000484 GET_STACK_TRACE_MALLOC;
485 void *new_mem = asan_malloc(length + 1, &stack);
486 REAL(memcpy)(new_mem, s, length + 1);
487 return reinterpret_cast<char*>(new_mem);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000488}
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000489#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000490
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000491INTERCEPTOR(uptr, strlen, const char *s) {
Alexander Potapenko50f2e302012-10-05 12:11:06 +0000492 if (!asan_inited) return internal_strlen(s);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000493 // strlen is called from malloc_default_purgeable_zone()
494 // in __asan::ReplaceSystemAlloc() on Mac.
495 if (asan_init_is_running) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000496 return REAL(strlen)(s);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000497 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000498 ENSURE_ASAN_INITED();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000499 uptr length = REAL(strlen)(s);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000500 if (flags()->replace_str) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000501 ASAN_READ_RANGE(s, length + 1);
502 }
503 return length;
504}
505
Reid Klecknerb99228d2013-09-05 01:13:49 +0000506INTERCEPTOR(uptr, wcslen, const wchar_t *s) {
507 uptr length = REAL(wcslen)(s);
508 if (!asan_init_is_running) {
509 ENSURE_ASAN_INITED();
510 ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
511 }
512 return length;
513}
514
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000515INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
Kostya Serebryanye1301912011-12-05 18:56:29 +0000516 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000517 if (flags()->replace_str) {
Alexey Samsonovc9256972012-06-15 13:09:52 +0000518 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
Kostya Serebryanyc5e72a32011-12-28 19:24:31 +0000519 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000520 ASAN_READ_RANGE(from, from_size);
521 ASAN_WRITE_RANGE(to, size);
522 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000523 return REAL(strncpy)(to, from, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000524}
525
Alexey Samsonov81a7a4a2012-03-24 09:10:50 +0000526#if ASAN_INTERCEPT_STRNLEN
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000527INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
Kostya Serebryanye1301912011-12-05 18:56:29 +0000528 ENSURE_ASAN_INITED();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000529 uptr length = REAL(strnlen)(s, maxlen);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000530 if (flags()->replace_str) {
Kostya Serebryany2d8b3bd2011-12-02 18:42:04 +0000531 ASAN_READ_RANGE(s, Min(length + 1, maxlen));
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000532 }
533 return length;
534}
Alexey Samsonov81a7a4a2012-03-24 09:10:50 +0000535#endif // ASAN_INTERCEPT_STRNLEN
Kostya Serebryany547652c2012-01-09 19:35:11 +0000536
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000537static inline bool IsValidStrtolBase(int base) {
538 return (base == 0) || (2 <= base && base <= 36);
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000539}
540
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000541static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
Kostya Serebryanya27bdf72013-04-05 14:40:25 +0000542 CHECK(endptr);
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000543 if (nptr == *endptr) {
544 // No digits were found at strtol call, we need to find out the last
545 // symbol accessed by strtoll on our own.
546 // We get this symbol by skipping leading blanks and optional +/- sign.
547 while (IsSpace(*nptr)) nptr++;
548 if (*nptr == '+' || *nptr == '-') nptr++;
549 *endptr = (char*)nptr;
550 }
551 CHECK(*endptr >= nptr);
552}
553
Alexey Samsonov847f9322012-03-29 08:04:35 +0000554INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
555 char **endptr, int base) {
556 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000557 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000558 return REAL(strtol)(nptr, endptr, base);
559 }
560 char *real_endptr;
561 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000562 if (endptr != 0) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000563 *endptr = real_endptr;
564 }
565 if (IsValidStrtolBase(base)) {
566 FixRealStrtolEndptr(nptr, &real_endptr);
567 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
568 }
569 return result;
570}
571
572INTERCEPTOR(int, atoi, const char *nptr) {
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000573#if SANITIZER_MAC
Alexander Potapenko0ef53102012-08-17 09:00:08 +0000574 if (!asan_inited) return REAL(atoi)(nptr);
575#endif
Alexey Samsonov847f9322012-03-29 08:04:35 +0000576 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000577 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000578 return REAL(atoi)(nptr);
579 }
580 char *real_endptr;
581 // "man atoi" tells that behavior of atoi(nptr) is the same as
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000582 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
Alexey Samsonov847f9322012-03-29 08:04:35 +0000583 // parsed integer can't be stored in *long* type (even if it's
584 // different from int). So, we just imitate this behavior.
585 int result = REAL(strtol)(nptr, &real_endptr, 10);
586 FixRealStrtolEndptr(nptr, &real_endptr);
587 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
588 return result;
589}
590
591INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000592#if SANITIZER_MAC
Alexander Potapenko0ef53102012-08-17 09:00:08 +0000593 if (!asan_inited) return REAL(atol)(nptr);
594#endif
Alexey Samsonov847f9322012-03-29 08:04:35 +0000595 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000596 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000597 return REAL(atol)(nptr);
598 }
599 char *real_endptr;
600 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
601 FixRealStrtolEndptr(nptr, &real_endptr);
602 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
603 return result;
604}
605
606#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000607INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
608 char **endptr, int base) {
609 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000610 if (!flags()->replace_str) {
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000611 return REAL(strtoll)(nptr, endptr, base);
612 }
613 char *real_endptr;
614 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000615 if (endptr != 0) {
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000616 *endptr = real_endptr;
617 }
618 // If base has unsupported value, strtoll can exit with EINVAL
619 // without reading any characters. So do additional checks only
620 // if base is valid.
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000621 if (IsValidStrtolBase(base)) {
622 FixRealStrtolEndptr(nptr, &real_endptr);
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000623 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
624 }
625 return result;
626}
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000627
Alexey Samsonov847f9322012-03-29 08:04:35 +0000628INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000629 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000630 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000631 return REAL(atoll)(nptr);
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000632 }
633 char *real_endptr;
Alexey Samsonov847f9322012-03-29 08:04:35 +0000634 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
635 FixRealStrtolEndptr(nptr, &real_endptr);
636 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000637 return result;
638}
Alexey Samsonov847f9322012-03-29 08:04:35 +0000639#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000640
Alexey Samsonov46efcb02013-05-24 11:46:56 +0000641static void AtCxaAtexit(void *unused) {
642 (void)unused;
643 StopInitOrderChecking();
644}
645
646#if ASAN_INTERCEPT___CXA_ATEXIT
647INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
648 void *dso_handle) {
649 ENSURE_ASAN_INITED();
650 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
651 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
652 return res;
653}
654#endif // ASAN_INTERCEPT___CXA_ATEXIT
655
Alexander Potapenkofd552812013-06-07 15:10:02 +0000656#if !SANITIZER_MAC
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000657#define ASAN_INTERCEPT_FUNC(name) do { \
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000658 if (!INTERCEPT_FUNCTION(name) && common_flags()->verbosity > 0) \
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000659 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
660 } while (0)
Alexander Potapenkofd552812013-06-07 15:10:02 +0000661#else
662// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
663#define ASAN_INTERCEPT_FUNC(name)
664#endif // SANITIZER_MAC
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000665
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000666#if SANITIZER_WINDOWS
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000667INTERCEPTOR_WINAPI(DWORD, CreateThread,
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000668 void* security, uptr stack_size,
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000669 DWORD (__stdcall *start_routine)(void*), void* arg,
Alexey Samsonovb9a92842013-07-01 16:38:38 +0000670 DWORD thr_flags, void* tid) {
Alexey Samsonovbdd09662013-04-23 13:57:35 +0000671 // Strict init-order checking in thread-hostile.
Alexey Samsonov9465cbd2013-07-01 16:16:41 +0000672 if (flags()->strict_init_order)
673 StopInitOrderChecking();
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000674 GET_STACK_TRACE_THREAD;
Alexey Samsonov89c13842013-03-20 09:23:28 +0000675 u32 current_tid = GetCurrentTidOrInvalid();
Alexey Samsonovdfe3f962013-03-22 07:48:23 +0000676 AsanThread *t = AsanThread::Create(start_routine, arg);
677 CreateThreadContextArgs args = { t, &stack };
Timur Iskhodzhanov8d2438a2013-05-29 17:26:25 +0000678 bool detached = false; // FIXME: how can we determine it on Windows?
Alexey Samsonovdfe3f962013-03-22 07:48:23 +0000679 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000680 return REAL(CreateThread)(security, stack_size,
Alexey Samsonovb9a92842013-07-01 16:38:38 +0000681 asan_thread_start, t, thr_flags, tid);
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000682}
683
684namespace __asan {
685void InitializeWindowsInterceptors() {
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000686 ASAN_INTERCEPT_FUNC(CreateThread);
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000687}
688
689} // namespace __asan
690#endif
691
Kostya Serebryany547652c2012-01-09 19:35:11 +0000692// ---------------------- InitializeAsanInterceptors ---------------- {{{1
693namespace __asan {
694void InitializeAsanInterceptors() {
Kostya Serebryanyfdbdab52012-03-16 21:02:13 +0000695 static bool was_called_once;
696 CHECK(was_called_once == false);
697 was_called_once = true;
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000698 SANITIZER_COMMON_INTERCEPTORS_INIT;
699
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000700 // Intercept mem* functions.
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000701 ASAN_INTERCEPT_FUNC(memcmp);
702 ASAN_INTERCEPT_FUNC(memmove);
703 ASAN_INTERCEPT_FUNC(memset);
Alexey Samsonov38dd4ed2012-03-20 10:54:40 +0000704 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000705 ASAN_INTERCEPT_FUNC(memcpy);
Alexander Potapenko573fb4b2012-02-01 10:07:52 +0000706 }
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000707
708 // Intercept str* functions.
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000709 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
710 ASAN_INTERCEPT_FUNC(strchr);
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000711 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
712 ASAN_INTERCEPT_FUNC(strlen);
Reid Klecknerb99228d2013-09-05 01:13:49 +0000713 ASAN_INTERCEPT_FUNC(wcslen);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000714 ASAN_INTERCEPT_FUNC(strncat);
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000715 ASAN_INTERCEPT_FUNC(strncpy);
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000716#if ASAN_INTERCEPT_STRDUP
717 ASAN_INTERCEPT_FUNC(strdup);
718#endif
719#if ASAN_INTERCEPT_STRNLEN
720 ASAN_INTERCEPT_FUNC(strnlen);
721#endif
Alexander Potapenko69563982013-02-05 15:57:12 +0000722#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000723 ASAN_INTERCEPT_FUNC(index);
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000724#endif
Kostya Serebryany547652c2012-01-09 19:35:11 +0000725
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000726 ASAN_INTERCEPT_FUNC(atoi);
727 ASAN_INTERCEPT_FUNC(atol);
728 ASAN_INTERCEPT_FUNC(strtol);
Alexey Samsonov847f9322012-03-29 08:04:35 +0000729#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000730 ASAN_INTERCEPT_FUNC(atoll);
731 ASAN_INTERCEPT_FUNC(strtoll);
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000732#endif
733
Alexander Potapenkof0c6de32012-08-15 09:46:45 +0000734#if ASAN_INTERCEPT_MLOCKX
Alexander Potapenko00f1c092012-08-15 09:22:57 +0000735 // Intercept mlock/munlock.
736 ASAN_INTERCEPT_FUNC(mlock);
737 ASAN_INTERCEPT_FUNC(munlock);
738 ASAN_INTERCEPT_FUNC(mlockall);
739 ASAN_INTERCEPT_FUNC(munlockall);
Alexander Potapenkof0c6de32012-08-15 09:46:45 +0000740#endif
Alexander Potapenko00f1c092012-08-15 09:22:57 +0000741
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000742 // Intecept signal- and jump-related functions.
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000743 ASAN_INTERCEPT_FUNC(longjmp);
Alexey Samsonov34a32022012-03-26 09:07:29 +0000744#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000745 ASAN_INTERCEPT_FUNC(sigaction);
746 ASAN_INTERCEPT_FUNC(signal);
Evgeniy Stepanov919c2472012-02-13 12:04:36 +0000747#endif
Alexey Samsonov08700282012-11-23 09:46:34 +0000748#if ASAN_INTERCEPT_SWAPCONTEXT
749 ASAN_INTERCEPT_FUNC(swapcontext);
750#endif
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000751#if ASAN_INTERCEPT__LONGJMP
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000752 ASAN_INTERCEPT_FUNC(_longjmp);
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000753#endif
754#if ASAN_INTERCEPT_SIGLONGJMP
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000755 ASAN_INTERCEPT_FUNC(siglongjmp);
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000756#endif
757
758 // Intercept exception handling functions.
759#if ASAN_INTERCEPT___CXA_THROW
760 INTERCEPT_FUNCTION(__cxa_throw);
Timur Iskhodzhanov3e81fe42012-02-09 17:20:14 +0000761#endif
762
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000763 // Intercept threading-related functions
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000764#if ASAN_INTERCEPT_PTHREAD_CREATE
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000765 ASAN_INTERCEPT_FUNC(pthread_create);
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000766#endif
767
Alexey Samsonov46efcb02013-05-24 11:46:56 +0000768 // Intercept atexit function.
769#if ASAN_INTERCEPT___CXA_ATEXIT
770 ASAN_INTERCEPT_FUNC(__cxa_atexit);
771#endif
772
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000773 // Some Windows-specific interceptors.
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000774#if SANITIZER_WINDOWS
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000775 InitializeWindowsInterceptors();
776#endif
777
Dmitry Vyukov6866dba2013-10-15 13:28:51 +0000778 if (common_flags()->verbosity > 0) {
Alexander Potapenko2962f262012-03-21 09:33:05 +0000779 Report("AddressSanitizer: libc interceptors initialized\n");
Kostya Serebryany547652c2012-01-09 19:35:11 +0000780 }
781}
782
783} // namespace __asan