blob: d8b48d391ab8be811c493027d44de3200f135c5a [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"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000017#include "asan_internal.h"
18#include "asan_mapping.h"
Alexey Samsonov7e843492013-03-28 15:42:43 +000019#include "asan_poisoning.h"
Alexey Samsonov487fee72012-08-09 08:32:33 +000020#include "asan_report.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000021#include "asan_stack.h"
22#include "asan_stats.h"
Stephen Hines86277eb2015-03-23 12:06:32 -070023#include "asan_suppressions.h"
Alexey Samsonovc0d78c12012-06-04 13:27:49 +000024#include "sanitizer_common/sanitizer_libc.h"
25
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070026#if SANITIZER_POSIX
27#include "sanitizer_common/sanitizer_posix.h"
28#endif
29
Kostya Serebryany1e172b42011-11-30 01:07:02 +000030namespace __asan {
31
Kostya Serebryanya84805f2013-02-21 07:07:39 +000032// Return true if we can quickly decide that the region is unpoisoned.
33static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
34 if (size == 0) return true;
35 if (size <= 32)
36 return !AddressIsPoisoned(beg) &&
37 !AddressIsPoisoned(beg + size - 1) &&
38 !AddressIsPoisoned(beg + size / 2);
39 return false;
40}
41
Stephen Hines86277eb2015-03-23 12:06:32 -070042struct AsanInterceptorContext {
43 const char *interceptor_name;
44};
45
Kostya Serebryany1e172b42011-11-30 01:07:02 +000046// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
47// and ASAN_WRITE_RANGE as macro instead of function so
48// that no extra frames are created, and stack trace contains
49// relevant information only.
Kostya Serebryanyeb280932012-12-28 15:24:16 +000050// We check all shadow bytes.
Stephen Hines86277eb2015-03-23 12:06:32 -070051#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
Evgeniy Stepanov589dcda2013-02-05 14:32:03 +000052 uptr __offset = (uptr)(offset); \
53 uptr __size = (uptr)(size); \
Kostya Serebryany1b057b22013-02-26 07:25:18 +000054 uptr __bad = 0; \
Stephen Hines2d1fdb22014-05-28 23:58:16 -070055 if (__offset > __offset + __size) { \
56 GET_STACK_TRACE_FATAL_HERE; \
57 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
58 } \
Kostya Serebryanya84805f2013-02-21 07:07:39 +000059 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
Kostya Serebryany1b057b22013-02-26 07:25:18 +000060 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
Stephen Hines86277eb2015-03-23 12:06:32 -070061 AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
62 bool suppressed = false; \
63 if (_ctx) { \
64 suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
65 if (!suppressed && HaveStackTraceBasedSuppressions()) { \
66 GET_STACK_TRACE_FATAL_HERE; \
67 suppressed = IsStackTraceSuppressed(&stack); \
68 } \
69 } \
70 if (!suppressed) { \
71 GET_CURRENT_PC_BP_SP; \
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070072 __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \
Stephen Hines86277eb2015-03-23 12:06:32 -070073 } \
Evgeniy Stepanov589dcda2013-02-05 14:32:03 +000074 } \
75 } while (0)
Kostya Serebryany1e172b42011-11-30 01:07:02 +000076
Stephen Hines86277eb2015-03-23 12:06:32 -070077#define ASAN_READ_RANGE(ctx, offset, size) \
78 ACCESS_MEMORY_RANGE(ctx, offset, size, false)
79#define ASAN_WRITE_RANGE(ctx, offset, size) \
80 ACCESS_MEMORY_RANGE(ctx, offset, size, true)
Kostya Serebryany1e172b42011-11-30 01:07:02 +000081
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070082#define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
83 ASAN_READ_RANGE((ctx), (s), \
84 common_flags()->strict_string_checks ? (len) + 1 : (n))
85
86#define ASAN_READ_STRING(ctx, s, n) \
87 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
88
Kostya Serebryany1e172b42011-11-30 01:07:02 +000089// Behavior of functions like "memcpy" or "strcpy" is undefined
90// if memory intervals overlap. We report error in this case.
91// Macro is used to avoid creation of new frames.
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000092static inline bool RangesOverlap(const char *offset1, uptr length1,
93 const char *offset2, uptr length2) {
Kostya Serebryany0985ca22011-12-28 19:08:49 +000094 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
Kostya Serebryany1e172b42011-11-30 01:07:02 +000095}
Kostya Serebryanyc5e72a32011-12-28 19:24:31 +000096#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
Kostya Serebryany1e172b42011-11-30 01:07:02 +000097 const char *offset1 = (const char*)_offset1; \
98 const char *offset2 = (const char*)_offset2; \
Kostya Serebryany0985ca22011-12-28 19:08:49 +000099 if (RangesOverlap(offset1, length1, offset2, length2)) { \
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000100 GET_STACK_TRACE_FATAL_HERE; \
Alexey Samsonov487fee72012-08-09 08:32:33 +0000101 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
102 offset2, length2, &stack); \
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000103 } \
Kostya Serebryanye1301912011-12-05 18:56:29 +0000104} while (0)
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000105
Alexey Samsonovc9256972012-06-15 13:09:52 +0000106static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
Alexey Samsonov81a7a4a2012-03-24 09:10:50 +0000107#if ASAN_INTERCEPT_STRNLEN
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000108 if (REAL(strnlen) != 0) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000109 return REAL(strnlen)(s, maxlen);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000110 }
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000111#endif
Alexey Samsonovc9256972012-06-15 13:09:52 +0000112 return internal_strnlen(s, maxlen);
Kostya Serebryanya4ccf872012-01-09 22:20:49 +0000113}
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000114
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000115void SetThreadName(const char *name) {
Alexey Samsonov89c13842013-03-20 09:23:28 +0000116 AsanThread *t = GetCurrentThread();
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000117 if (t)
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000118 asanThreadRegistry().SetThreadName(t->tid(), name);
Kostya Serebryanyc20b3212013-01-18 06:43:13 +0000119}
120
Dmitry Vyukov8cde99f2013-10-03 15:43:59 +0000121int OnExit() {
Dmitry Vyukov14dd9802013-10-03 15:22:29 +0000122 // FIXME: ask frontend whether we need to return failure.
123 return 0;
124}
125
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000126} // namespace __asan
127
128// ---------------------- Wrappers ---------------- {{{1
129using namespace __asan; // NOLINT
130
Evgeniy Stepanov12eb79d2013-07-09 09:53:37 +0000131DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
132DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
133
Stephen Hines86277eb2015-03-23 12:06:32 -0700134#define ASAN_INTERCEPTOR_ENTER(ctx, func) \
135 AsanInterceptorContext _ctx = {#func}; \
136 ctx = (void *)&_ctx; \
137 (void) ctx; \
138
Evgeniy Stepanova537ea92013-11-11 11:28:30 +0000139#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
Evgeniy Stepanov82a90802013-01-18 13:12:56 +0000140#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
Stephen Hines86277eb2015-03-23 12:06:32 -0700141 ASAN_WRITE_RANGE(ctx, ptr, size)
142#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
143 ASAN_READ_RANGE(ctx, ptr, size)
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700144#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
Stephen Hines86277eb2015-03-23 12:06:32 -0700145 ASAN_INTERCEPTOR_ENTER(ctx, func); \
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700146 do { \
147 if (asan_init_is_running) \
148 return REAL(func)(__VA_ARGS__); \
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700149 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
150 return REAL(func)(__VA_ARGS__); \
151 ENSURE_ASAN_INITED(); \
Evgeniy Stepanov82a90802013-01-18 13:12:56 +0000152 } while (false)
Stephen Hines86277eb2015-03-23 12:06:32 -0700153#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
154 do { \
155 } while (false)
Evgeniy Stepanov9d1525e2013-05-29 09:09:58 +0000156#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
157 do { \
158 } while (false)
159#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
160 do { \
161 } while (false)
162#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
163 do { \
164 } while (false)
Evgeniy Stepanov996c4f22013-01-18 11:17:23 +0000165#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
Dmitry Vyukove767e352013-11-14 16:48:22 +0000166// Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
167// But asan does not remember UserId's for threads (pthread_t);
168// and remembers all ever existed threads, so the linear search by UserId
169// can be slow.
Dmitry Vyukov5cf2c462013-10-29 10:30:39 +0000170#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
Dmitry Vyukove767e352013-11-14 16:48:22 +0000171 do { \
172 } while (false)
Evgeniy Stepanove18e3f02013-08-12 13:19:53 +0000173#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
Stephen Hines86277eb2015-03-23 12:06:32 -0700174// Strict init-order checking is dlopen-hostile:
175// https://code.google.com/p/address-sanitizer/issues/detail?id=178
176#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
177 if (flags()->strict_init_order) { \
178 StopInitOrderChecking(); \
179 }
Dmitry Vyukov14dd9802013-10-03 15:22:29 +0000180#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
Stephen Hines86277eb2015-03-23 12:06:32 -0700181#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
182 CoverageUpdateMapping()
183#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
Stephen Hines6d186232014-11-26 17:56:19 -0800184#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -0700185#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
186 if (AsanThread *t = GetCurrentThread()) { \
187 *begin = t->tls_begin(); \
188 *end = t->tls_end(); \
189 } else { \
190 *begin = *end = 0; \
191 }
Evgeniy Stepanov4f32c0b2013-01-18 13:01:18 +0000192#include "sanitizer_common/sanitizer_common_interceptors.inc"
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000193
Stephen Hines86277eb2015-03-23 12:06:32 -0700194// Syscall interceptors don't have contexts, we don't support suppressions
195// for them.
196#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
197#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
Evgeniy Stepanovae4e6fd2013-07-09 09:29:19 +0000198#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
199 do { \
Evgeniy Stepanovdfab31b2013-10-29 18:29:39 +0000200 (void)(p); \
201 (void)(s); \
Evgeniy Stepanovae4e6fd2013-07-09 09:29:19 +0000202 } while (false)
203#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
204 do { \
Evgeniy Stepanovdfab31b2013-10-29 18:29:39 +0000205 (void)(p); \
206 (void)(s); \
Evgeniy Stepanovae4e6fd2013-07-09 09:29:19 +0000207 } while (false)
Evgeniy Stepanov881b6772013-04-12 14:57:03 +0000208#include "sanitizer_common/sanitizer_common_syscalls.inc"
209
Stephen Hines86277eb2015-03-23 12:06:32 -0700210struct ThreadStartParam {
211 atomic_uintptr_t t;
212 atomic_uintptr_t is_registered;
213};
214
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000215static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700216 ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
217 AsanThread *t = nullptr;
218 while ((t = reinterpret_cast<AsanThread *>(
219 atomic_load(&param->t, memory_order_acquire))) == 0)
220 internal_sched_yield();
221 SetCurrentThread(t);
222 return t->ThreadStart(GetTid(), &param->is_registered);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000223}
224
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000225#if ASAN_INTERCEPT_PTHREAD_CREATE
Evgeniy Stepanovb8ef9252012-02-22 12:31:25 +0000226INTERCEPTOR(int, pthread_create, void *thread,
227 void *attr, void *(*start_routine)(void*), void *arg) {
Sergey Matveevc6ac98d2013-07-08 12:57:24 +0000228 EnsureMainThreadIDIsCorrect();
Stephen Hines86277eb2015-03-23 12:06:32 -0700229 // Strict init-order checking is thread-hostile.
Alexey Samsonov9465cbd2013-07-01 16:16:41 +0000230 if (flags()->strict_init_order)
231 StopInitOrderChecking();
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000232 GET_STACK_TRACE_THREAD;
Alexey Samsonovdef1be92013-03-21 11:23:41 +0000233 int detached = 0;
234 if (attr != 0)
Evgeniy Stepanovbb6bc9a2013-11-11 08:56:49 +0000235 REAL(pthread_attr_getdetachstate)(attr, &detached);
Stephen Hines86277eb2015-03-23 12:06:32 -0700236 ThreadStartParam param;
237 atomic_store(&param.t, 0, memory_order_relaxed);
238 atomic_store(&param.is_registered, 0, memory_order_relaxed);
239 int result = REAL(pthread_create)(thread, attr, asan_thread_start, &param);
240 if (result == 0) {
241 u32 current_tid = GetCurrentTidOrInvalid();
242 AsanThread *t =
243 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
244 atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
245 // Wait until the AsanThread object is initialized and the ThreadRegistry
246 // entry is in "started" state. One reason for this is that after this
247 // interceptor exits, the child thread's stack may be the only thing holding
248 // the |arg| pointer. This may cause LSan to report a leak if leak checking
249 // happens at a point when the interceptor has already exited, but the stack
250 // range for the child thread is not yet known.
251 while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
252 internal_sched_yield();
253 }
254 return result;
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000255}
Stephen Hines86277eb2015-03-23 12:06:32 -0700256
257INTERCEPTOR(int, pthread_join, void *t, void **arg) {
258 return real_pthread_join(t, arg);
259}
260
261DEFINE_REAL_PTHREAD_FUNCTIONS
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000262#endif // ASAN_INTERCEPT_PTHREAD_CREATE
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000263
Alexey Samsonov34a32022012-03-26 09:07:29 +0000264#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700265
266#if SANITIZER_ANDROID
267INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700268 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700269 return REAL(bsd_signal)(signum, handler);
270 }
271 return 0;
272}
273#else
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000274INTERCEPTOR(void*, signal, int signum, void *handler) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700275 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
Alexander Potapenko034bda52012-04-16 08:33:01 +0000276 return REAL(signal)(signum, handler);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000277 }
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000278 return 0;
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000279}
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700280#endif
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000281
Alexey Samsonovda13ba82012-02-16 17:00:45 +0000282INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
283 struct sigaction *oldact) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700284 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
Alexander Potapenko034bda52012-04-16 08:33:01 +0000285 return REAL(sigaction)(signum, act, oldact);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000286 }
Alexander Potapenko034bda52012-04-16 08:33:01 +0000287 return 0;
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000288}
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700289
290namespace __sanitizer {
291int real_sigaction(int signum, const void *act, void *oldact) {
Stephen Hines6d186232014-11-26 17:56:19 -0800292 return REAL(sigaction)(signum, (const struct sigaction *)act,
293 (struct sigaction *)oldact);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700294}
295} // namespace __sanitizer
296
Evgeniy Stepanove1ba0002013-03-19 15:26:41 +0000297#elif SANITIZER_POSIX
Alexey Samsonov34a32022012-03-26 09:07:29 +0000298// We need to have defined REAL(sigaction) on posix systems.
299DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
Alexey Samsonovfdde5a92013-06-10 14:17:08 +0000300 struct sigaction *oldact)
Alexey Samsonov34a32022012-03-26 09:07:29 +0000301#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000302
Alexey Samsonov08700282012-11-23 09:46:34 +0000303#if ASAN_INTERCEPT_SWAPCONTEXT
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000304static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
305 // Align to page size.
306 uptr PageSize = GetPageSizeCached();
307 uptr bottom = stack & ~(PageSize - 1);
308 ssize += stack - bottom;
309 ssize = RoundUpTo(ssize, PageSize);
310 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700311 if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000312 PoisonShadow(bottom, ssize, 0);
313 }
314}
315
Alexey Samsonov08700282012-11-23 09:46:34 +0000316INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
317 struct ucontext_t *ucp) {
318 static bool reported_warning = false;
319 if (!reported_warning) {
320 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
321 "functions and may produce false positives in some cases!\n");
322 reported_warning = true;
323 }
324 // Clear shadow memory for new context (it may share stack
325 // with current context).
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000326 uptr stack, ssize;
327 ReadContextStack(ucp, &stack, &ssize);
328 ClearShadowMemoryForContextStack(stack, ssize);
Alexey Samsonov08700282012-11-23 09:46:34 +0000329 int res = REAL(swapcontext)(oucp, ucp);
330 // swapcontext technically does not return, but program may swap context to
331 // "oucp" later, that would look as if swapcontext() returned 0.
332 // We need to clear shadow for ucp once again, as it may be in arbitrary
333 // state.
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000334 ClearShadowMemoryForContextStack(stack, ssize);
Alexey Samsonov08700282012-11-23 09:46:34 +0000335 return res;
336}
Alexey Samsonov57db4ba2013-01-17 15:45:28 +0000337#endif // ASAN_INTERCEPT_SWAPCONTEXT
Alexey Samsonov08700282012-11-23 09:46:34 +0000338
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000339INTERCEPTOR(void, longjmp, void *env, int val) {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000340 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000341 REAL(longjmp)(env, val);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000342}
343
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000344#if ASAN_INTERCEPT__LONGJMP
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000345INTERCEPTOR(void, _longjmp, void *env, int val) {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000346 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000347 REAL(_longjmp)(env, val);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000348}
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000349#endif
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000350
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000351#if ASAN_INTERCEPT_SIGLONGJMP
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000352INTERCEPTOR(void, siglongjmp, void *env, int val) {
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000353 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000354 REAL(siglongjmp)(env, val);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000355}
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000356#endif
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000357
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000358#if ASAN_INTERCEPT___CXA_THROW
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000359INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000360 CHECK(REAL(__cxa_throw));
Kostya Serebryanyf54b1f92012-02-08 21:33:27 +0000361 __asan_handle_no_return();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000362 REAL(__cxa_throw)(a, b, c);
Kostya Serebryany4803ab92012-01-09 18:53:15 +0000363}
364#endif
365
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000366static inline int CharCmp(unsigned char c1, unsigned char c2) {
367 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
368}
369
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000370INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700371 void *ctx;
372 ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700373 if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000374 ENSURE_ASAN_INITED();
Kostya Serebryany1b057b22013-02-26 07:25:18 +0000375 if (flags()->replace_intrin) {
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000376 if (flags()->strict_memcmp) {
377 // Check the entire regions even if the first bytes of the buffers are
378 // different.
Stephen Hines86277eb2015-03-23 12:06:32 -0700379 ASAN_READ_RANGE(ctx, a1, size);
380 ASAN_READ_RANGE(ctx, a2, size);
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000381 // Fallthrough to REAL(memcmp) below.
382 } else {
383 unsigned char c1 = 0, c2 = 0;
384 const unsigned char *s1 = (const unsigned char*)a1;
385 const unsigned char *s2 = (const unsigned char*)a2;
386 uptr i;
387 for (i = 0; i < size; i++) {
388 c1 = s1[i];
389 c2 = s2[i];
390 if (c1 != c2) break;
391 }
Stephen Hines86277eb2015-03-23 12:06:32 -0700392 ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
393 ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
Alexander Potapenko8bd5e742013-02-28 14:09:30 +0000394 return CharCmp(c1, c2);
395 }
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000396 }
Kostya Serebryany1b057b22013-02-26 07:25:18 +0000397 return REAL(memcmp(a1, a2, size));
Kostya Serebryany52fb2382011-12-28 18:56:42 +0000398}
399
Stephen Hines86277eb2015-03-23 12:06:32 -0700400// memcpy is called during __asan_init() from the internals of printf(...).
401// We do not treat memcpy with to==from as a bug.
402// See http://llvm.org/bugs/show_bug.cgi?id=11763.
403#define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \
404 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
405 if (asan_init_is_running) { \
406 return REAL(memcpy)(to, from, size); \
407 } \
408 ENSURE_ASAN_INITED(); \
409 if (flags()->replace_intrin) { \
410 if (to != from) { \
411 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
412 } \
413 ASAN_READ_RANGE(ctx, from, size); \
414 ASAN_WRITE_RANGE(ctx, to, size); \
415 } \
416 return REAL(memcpy)(to, from, size); \
417 } while (0)
418
419
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700420void *__asan_memcpy(void *to, const void *from, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700421 ASAN_MEMCPY_IMPL(nullptr, to, from, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000422}
423
Stephen Hines86277eb2015-03-23 12:06:32 -0700424// memset is called inside Printf.
425#define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \
426 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
427 if (asan_init_is_running) { \
428 return REAL(memset)(block, c, size); \
429 } \
430 ENSURE_ASAN_INITED(); \
431 if (flags()->replace_intrin) { \
432 ASAN_WRITE_RANGE(ctx, block, size); \
433 } \
434 return REAL(memset)(block, c, size); \
435 } while (0)
436
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700437void *__asan_memset(void *block, int c, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700438 ASAN_MEMSET_IMPL(nullptr, block, c, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000439}
440
Stephen Hines86277eb2015-03-23 12:06:32 -0700441#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \
442 if (UNLIKELY(!asan_inited)) \
443 return internal_memmove(to, from, size); \
444 ENSURE_ASAN_INITED(); \
445 if (flags()->replace_intrin) { \
446 ASAN_READ_RANGE(ctx, from, size); \
447 ASAN_WRITE_RANGE(ctx, to, size); \
448 } \
449 return internal_memmove(to, from, size); \
450 } while (0)
451
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700452void *__asan_memmove(void *to, const void *from, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700453 ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700454}
455
456INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700457 void *ctx;
458 ASAN_INTERCEPTOR_ENTER(ctx, memmove);
459 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700460}
461
462INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700463 void *ctx;
464 ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700465#if !SANITIZER_MAC
Stephen Hines86277eb2015-03-23 12:06:32 -0700466 ASAN_MEMCPY_IMPL(ctx, to, from, size);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700467#else
468 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
469 // with WRAP(memcpy). As a result, false positives are reported for memmove()
470 // calls. If we just disable error reporting with
471 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
472 // internal_memcpy(), which may lead to crashes, see
473 // http://llvm.org/bugs/show_bug.cgi?id=16362.
Stephen Hines86277eb2015-03-23 12:06:32 -0700474 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700475#endif // !SANITIZER_MAC
476}
477
478INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700479 void *ctx;
480 ASAN_INTERCEPTOR_ENTER(ctx, memset);
481 ASAN_MEMSET_IMPL(ctx, block, c, size);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700482}
483
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000484INTERCEPTOR(char*, strchr, const char *str, int c) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700485 void *ctx;
486 ASAN_INTERCEPTOR_ENTER(ctx, strchr);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700487 if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
Alexander Potapenko8d6e3f72012-09-10 08:35:12 +0000488 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
489 // used.
490 if (asan_init_is_running) {
491 return REAL(strchr)(str, c);
492 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000493 ENSURE_ASAN_INITED();
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000494 char *result = REAL(strchr)(str, c);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000495 if (flags()->replace_str) {
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700496 uptr len = REAL(strlen)(str);
497 uptr bytes_read = (result ? result - str : len) + 1;
498 ASAN_READ_STRING_OF_LEN(ctx, str, len, bytes_read);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000499 }
500 return result;
501}
502
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000503#if ASAN_INTERCEPT_INDEX
504# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
Evgeniy Stepanov4b0c5f22012-02-13 12:12:32 +0000505INTERCEPTOR(char*, index, const char *string, int c)
Alexander Potapenko72bbfd42013-02-21 15:15:43 +0000506 ALIAS(WRAPPER_NAME(strchr));
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000507# else
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000508# if SANITIZER_MAC
Alexander Potapenko50a002e2013-02-21 14:41:16 +0000509DECLARE_REAL(char*, index, const char *string, int c)
510OVERRIDE_FUNCTION(index, strchr);
511# else
Alexey Samsonovfdde5a92013-06-10 14:17:08 +0000512DEFINE_REAL(char*, index, const char *string, int c)
Alexander Potapenko50a002e2013-02-21 14:41:16 +0000513# endif
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000514# endif
515#endif // ASAN_INTERCEPT_INDEX
Kostya Serebryanyaf0f01d2011-12-28 02:24:50 +0000516
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000517// For both strcat() and strncat() we need to check the validity of |to|
518// argument irrespective of the |from| length.
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000519INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
Stephen Hines86277eb2015-03-23 12:06:32 -0700520 void *ctx;
521 ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000522 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000523 if (flags()->replace_str) {
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000524 uptr from_length = REAL(strlen)(from);
Stephen Hines86277eb2015-03-23 12:06:32 -0700525 ASAN_READ_RANGE(ctx, from, from_length + 1);
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000526 uptr to_length = REAL(strlen)(to);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700527 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
Stephen Hines86277eb2015-03-23 12:06:32 -0700528 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000529 // If the copying actually happens, the |from| string should not overlap
530 // with the resulting string starting at |to|, which has a length of
531 // to_length + from_length + 1.
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000532 if (from_length > 0) {
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000533 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
534 from, from_length + 1);
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000535 }
536 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000537 return REAL(strcat)(to, from); // NOLINT
Kostya Serebryany0985ca22011-12-28 19:08:49 +0000538}
539
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000540INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700541 void *ctx;
542 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000543 ENSURE_ASAN_INITED();
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000544 if (flags()->replace_str) {
Alexey Samsonovc9256972012-06-15 13:09:52 +0000545 uptr from_length = MaybeRealStrnlen(from, size);
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000546 uptr copy_length = Min(size, from_length + 1);
Stephen Hines86277eb2015-03-23 12:06:32 -0700547 ASAN_READ_RANGE(ctx, from, copy_length);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000548 uptr to_length = REAL(strlen)(to);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700549 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
Stephen Hines86277eb2015-03-23 12:06:32 -0700550 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000551 if (from_length > 0) {
Alexander Potapenko37b3fcd2012-08-02 10:25:46 +0000552 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
553 from, copy_length);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000554 }
555 }
556 return REAL(strncat)(to, from, size);
557}
558
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000559INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
Stephen Hines86277eb2015-03-23 12:06:32 -0700560 void *ctx;
561 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000562#if SANITIZER_MAC
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700563 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
Alexander Potapenko0ef53102012-08-17 09:00:08 +0000564#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000565 // strcpy is called from malloc_default_purgeable_zone()
566 // in __asan::ReplaceSystemAlloc() on Mac.
567 if (asan_init_is_running) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000568 return REAL(strcpy)(to, from); // NOLINT
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000569 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000570 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000571 if (flags()->replace_str) {
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000572 uptr from_size = REAL(strlen)(from) + 1;
Kostya Serebryanyc5e72a32011-12-28 19:24:31 +0000573 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
Stephen Hines86277eb2015-03-23 12:06:32 -0700574 ASAN_READ_RANGE(ctx, from, from_size);
575 ASAN_WRITE_RANGE(ctx, to, from_size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000576 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000577 return REAL(strcpy)(to, from); // NOLINT
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000578}
579
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000580#if ASAN_INTERCEPT_STRDUP
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000581INTERCEPTOR(char*, strdup, const char *s) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700582 void *ctx;
583 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700584 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
Kostya Serebryanye1301912011-12-05 18:56:29 +0000585 ENSURE_ASAN_INITED();
Alexey Samsonovd530d892013-06-21 14:41:59 +0000586 uptr length = REAL(strlen)(s);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000587 if (flags()->replace_str) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700588 ASAN_READ_RANGE(ctx, s, length + 1);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000589 }
Alexey Samsonovd530d892013-06-21 14:41:59 +0000590 GET_STACK_TRACE_MALLOC;
591 void *new_mem = asan_malloc(length + 1, &stack);
592 REAL(memcpy)(new_mem, s, length + 1);
593 return reinterpret_cast<char*>(new_mem);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000594}
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000595#endif
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000596
Stephen Hines6d186232014-11-26 17:56:19 -0800597INTERCEPTOR(SIZE_T, strlen, const char *s) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700598 void *ctx;
599 ASAN_INTERCEPTOR_ENTER(ctx, strlen);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700600 if (UNLIKELY(!asan_inited)) return internal_strlen(s);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000601 // strlen is called from malloc_default_purgeable_zone()
602 // in __asan::ReplaceSystemAlloc() on Mac.
603 if (asan_init_is_running) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000604 return REAL(strlen)(s);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000605 }
Kostya Serebryanye1301912011-12-05 18:56:29 +0000606 ENSURE_ASAN_INITED();
Stephen Hines6d186232014-11-26 17:56:19 -0800607 SIZE_T length = REAL(strlen)(s);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000608 if (flags()->replace_str) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700609 ASAN_READ_RANGE(ctx, s, length + 1);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000610 }
611 return length;
612}
613
Stephen Hines6d186232014-11-26 17:56:19 -0800614INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700615 void *ctx;
616 ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
Stephen Hines6d186232014-11-26 17:56:19 -0800617 SIZE_T length = REAL(wcslen)(s);
Reid Klecknerb99228d2013-09-05 01:13:49 +0000618 if (!asan_init_is_running) {
619 ENSURE_ASAN_INITED();
Stephen Hines86277eb2015-03-23 12:06:32 -0700620 ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
Reid Klecknerb99228d2013-09-05 01:13:49 +0000621 }
622 return length;
623}
624
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000625INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700626 void *ctx;
627 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
Kostya Serebryanye1301912011-12-05 18:56:29 +0000628 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000629 if (flags()->replace_str) {
Alexey Samsonovc9256972012-06-15 13:09:52 +0000630 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
Kostya Serebryanyc5e72a32011-12-28 19:24:31 +0000631 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
Stephen Hines86277eb2015-03-23 12:06:32 -0700632 ASAN_READ_RANGE(ctx, from, from_size);
633 ASAN_WRITE_RANGE(ctx, to, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000634 }
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000635 return REAL(strncpy)(to, from, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000636}
637
Alexey Samsonov81a7a4a2012-03-24 09:10:50 +0000638#if ASAN_INTERCEPT_STRNLEN
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000639INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700640 void *ctx;
641 ASAN_INTERCEPTOR_ENTER(ctx, strnlen);
Kostya Serebryanye1301912011-12-05 18:56:29 +0000642 ENSURE_ASAN_INITED();
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000643 uptr length = REAL(strnlen)(s, maxlen);
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000644 if (flags()->replace_str) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700645 ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen));
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000646 }
647 return length;
648}
Alexey Samsonov81a7a4a2012-03-24 09:10:50 +0000649#endif // ASAN_INTERCEPT_STRNLEN
Kostya Serebryany547652c2012-01-09 19:35:11 +0000650
Alexey Samsonov847f9322012-03-29 08:04:35 +0000651INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
652 char **endptr, int base) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700653 void *ctx;
654 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
Alexey Samsonov847f9322012-03-29 08:04:35 +0000655 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000656 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000657 return REAL(strtol)(nptr, endptr, base);
658 }
659 char *real_endptr;
660 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700661 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
Alexey Samsonov847f9322012-03-29 08:04:35 +0000662 return result;
663}
664
665INTERCEPTOR(int, atoi, const char *nptr) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700666 void *ctx;
667 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000668#if SANITIZER_MAC
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700669 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
Alexander Potapenko0ef53102012-08-17 09:00:08 +0000670#endif
Alexey Samsonov847f9322012-03-29 08:04:35 +0000671 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000672 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000673 return REAL(atoi)(nptr);
674 }
675 char *real_endptr;
676 // "man atoi" tells that behavior of atoi(nptr) is the same as
Kostya Serebryany3f4c3872012-05-31 14:35:53 +0000677 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
Alexey Samsonov847f9322012-03-29 08:04:35 +0000678 // parsed integer can't be stored in *long* type (even if it's
679 // different from int). So, we just imitate this behavior.
680 int result = REAL(strtol)(nptr, &real_endptr, 10);
681 FixRealStrtolEndptr(nptr, &real_endptr);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700682 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
Alexey Samsonov847f9322012-03-29 08:04:35 +0000683 return result;
684}
685
686INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
Stephen Hines86277eb2015-03-23 12:06:32 -0700687 void *ctx;
688 ASAN_INTERCEPTOR_ENTER(ctx, atol);
Evgeniy Stepanov24e13722013-03-19 14:33:38 +0000689#if SANITIZER_MAC
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700690 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
Alexander Potapenko0ef53102012-08-17 09:00:08 +0000691#endif
Alexey Samsonov847f9322012-03-29 08:04:35 +0000692 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000693 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000694 return REAL(atol)(nptr);
695 }
696 char *real_endptr;
697 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
698 FixRealStrtolEndptr(nptr, &real_endptr);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700699 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
Alexey Samsonov847f9322012-03-29 08:04:35 +0000700 return result;
701}
702
703#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000704INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
705 char **endptr, int base) {
Stephen Hines86277eb2015-03-23 12:06:32 -0700706 void *ctx;
707 ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000708 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000709 if (!flags()->replace_str) {
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000710 return REAL(strtoll)(nptr, endptr, base);
711 }
712 char *real_endptr;
713 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700714 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000715 return result;
716}
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000717
Alexey Samsonov847f9322012-03-29 08:04:35 +0000718INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
Stephen Hines86277eb2015-03-23 12:06:32 -0700719 void *ctx;
720 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000721 ENSURE_ASAN_INITED();
Alexey Samsonovcb8c4dc2012-07-09 14:36:04 +0000722 if (!flags()->replace_str) {
Alexey Samsonov847f9322012-03-29 08:04:35 +0000723 return REAL(atoll)(nptr);
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000724 }
725 char *real_endptr;
Alexey Samsonov847f9322012-03-29 08:04:35 +0000726 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
727 FixRealStrtolEndptr(nptr, &real_endptr);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700728 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000729 return result;
730}
Alexey Samsonov847f9322012-03-29 08:04:35 +0000731#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
Alexey Samsonov8f6a77f2012-03-26 16:42:22 +0000732
Alexey Samsonov46efcb02013-05-24 11:46:56 +0000733static void AtCxaAtexit(void *unused) {
734 (void)unused;
735 StopInitOrderChecking();
736}
737
738#if ASAN_INTERCEPT___CXA_ATEXIT
739INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
740 void *dso_handle) {
Alexander Potapenkob527f7d2013-11-13 13:34:53 +0000741#if SANITIZER_MAC
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700742 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
Alexander Potapenkob527f7d2013-11-13 13:34:53 +0000743#endif
Alexey Samsonov46efcb02013-05-24 11:46:56 +0000744 ENSURE_ASAN_INITED();
745 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
746 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
747 return res;
748}
749#endif // ASAN_INTERCEPT___CXA_ATEXIT
750
Stephen Hines6a211c52014-07-21 00:49:56 -0700751#if ASAN_INTERCEPT_FORK
752INTERCEPTOR(int, fork, void) {
753 ENSURE_ASAN_INITED();
754 if (common_flags()->coverage) CovBeforeFork();
755 int pid = REAL(fork)();
756 if (common_flags()->coverage) CovAfterFork(pid);
757 return pid;
758}
759#endif // ASAN_INTERCEPT_FORK
760
Kostya Serebryany547652c2012-01-09 19:35:11 +0000761// ---------------------- InitializeAsanInterceptors ---------------- {{{1
762namespace __asan {
763void InitializeAsanInterceptors() {
Kostya Serebryanyfdbdab52012-03-16 21:02:13 +0000764 static bool was_called_once;
765 CHECK(was_called_once == false);
766 was_called_once = true;
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700767 InitializeCommonInterceptors();
Kostya Serebryany8530e2b2012-12-12 09:54:35 +0000768
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000769 // Intercept mem* functions.
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000770 ASAN_INTERCEPT_FUNC(memcmp);
771 ASAN_INTERCEPT_FUNC(memmove);
772 ASAN_INTERCEPT_FUNC(memset);
Alexey Samsonov38dd4ed2012-03-20 10:54:40 +0000773 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000774 ASAN_INTERCEPT_FUNC(memcpy);
Alexander Potapenko573fb4b2012-02-01 10:07:52 +0000775 }
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000776
777 // Intercept str* functions.
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000778 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
779 ASAN_INTERCEPT_FUNC(strchr);
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000780 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
781 ASAN_INTERCEPT_FUNC(strlen);
Reid Klecknerb99228d2013-09-05 01:13:49 +0000782 ASAN_INTERCEPT_FUNC(wcslen);
Alexey Samsonovc1bdd5a2012-06-08 13:27:46 +0000783 ASAN_INTERCEPT_FUNC(strncat);
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000784 ASAN_INTERCEPT_FUNC(strncpy);
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000785#if ASAN_INTERCEPT_STRDUP
786 ASAN_INTERCEPT_FUNC(strdup);
787#endif
788#if ASAN_INTERCEPT_STRNLEN
789 ASAN_INTERCEPT_FUNC(strnlen);
790#endif
Alexander Potapenko69563982013-02-05 15:57:12 +0000791#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000792 ASAN_INTERCEPT_FUNC(index);
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000793#endif
Kostya Serebryany547652c2012-01-09 19:35:11 +0000794
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000795 ASAN_INTERCEPT_FUNC(atoi);
796 ASAN_INTERCEPT_FUNC(atol);
797 ASAN_INTERCEPT_FUNC(strtol);
Alexey Samsonov847f9322012-03-29 08:04:35 +0000798#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000799 ASAN_INTERCEPT_FUNC(atoll);
800 ASAN_INTERCEPT_FUNC(strtoll);
Alexey Samsonov84ba3242012-03-24 08:39:14 +0000801#endif
802
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000803 // Intecept signal- and jump-related functions.
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000804 ASAN_INTERCEPT_FUNC(longjmp);
Alexey Samsonov34a32022012-03-26 09:07:29 +0000805#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000806 ASAN_INTERCEPT_FUNC(sigaction);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700807#if SANITIZER_ANDROID
808 ASAN_INTERCEPT_FUNC(bsd_signal);
809#else
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000810 ASAN_INTERCEPT_FUNC(signal);
Evgeniy Stepanov919c2472012-02-13 12:04:36 +0000811#endif
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700812#endif
Alexey Samsonov08700282012-11-23 09:46:34 +0000813#if ASAN_INTERCEPT_SWAPCONTEXT
814 ASAN_INTERCEPT_FUNC(swapcontext);
815#endif
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000816#if ASAN_INTERCEPT__LONGJMP
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000817 ASAN_INTERCEPT_FUNC(_longjmp);
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000818#endif
819#if ASAN_INTERCEPT_SIGLONGJMP
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000820 ASAN_INTERCEPT_FUNC(siglongjmp);
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000821#endif
822
823 // Intercept exception handling functions.
824#if ASAN_INTERCEPT___CXA_THROW
Stephen Hines6d186232014-11-26 17:56:19 -0800825 ASAN_INTERCEPT_FUNC(__cxa_throw);
Timur Iskhodzhanov3e81fe42012-02-09 17:20:14 +0000826#endif
827
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000828 // Intercept threading-related functions
Alexey Samsonovfd2ae4f2012-08-01 11:17:00 +0000829#if ASAN_INTERCEPT_PTHREAD_CREATE
Dmitry Vyukov580469d2012-05-24 13:54:31 +0000830 ASAN_INTERCEPT_FUNC(pthread_create);
Stephen Hines86277eb2015-03-23 12:06:32 -0700831 ASAN_INTERCEPT_FUNC(pthread_join);
Timur Iskhodzhanov07bb9f12012-02-22 13:59:49 +0000832#endif
833
Alexey Samsonov46efcb02013-05-24 11:46:56 +0000834 // Intercept atexit function.
835#if ASAN_INTERCEPT___CXA_ATEXIT
836 ASAN_INTERCEPT_FUNC(__cxa_atexit);
837#endif
838
Stephen Hines6a211c52014-07-21 00:49:56 -0700839#if ASAN_INTERCEPT_FORK
840 ASAN_INTERCEPT_FUNC(fork);
841#endif
842
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -0700843 InitializePlatformInterceptors();
Timur Iskhodzhanov600972e2012-02-24 15:28:43 +0000844
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700845 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
Kostya Serebryany547652c2012-01-09 19:35:11 +0000846}
847
848} // namespace __asan