1 //===-- asan_interceptors.cc ----------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 // Intercept various libc functions.
13 //===----------------------------------------------------------------------===//
14 #include "asan_interceptors.h"
16 #include "asan_allocator.h"
17 #include "asan_internal.h"
18 #include "asan_mapping.h"
19 #include "asan_poisoning.h"
20 #include "asan_report.h"
21 #include "asan_stack.h"
22 #include "asan_stats.h"
23 #include "asan_suppressions.h"
24 #include "sanitizer_common/sanitizer_libc.h"
27 #include "sanitizer_common/sanitizer_posix.h"
32 // Return true if we can quickly decide that the region is unpoisoned.
33 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
34 if (size == 0) return true;
36 return !AddressIsPoisoned(beg) &&
37 !AddressIsPoisoned(beg + size - 1) &&
38 !AddressIsPoisoned(beg + size / 2);
42 struct AsanInterceptorContext {
43 const char *interceptor_name;
46 // 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.
50 // We check all shadow bytes.
51 #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
52 uptr __offset = (uptr)(offset); \
53 uptr __size = (uptr)(size); \
55 if (__offset > __offset + __size) { \
56 GET_STACK_TRACE_FATAL_HERE; \
57 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
59 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
60 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
61 AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
62 bool suppressed = false; \
64 suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
65 if (!suppressed && HaveStackTraceBasedSuppressions()) { \
66 GET_STACK_TRACE_FATAL_HERE; \
67 suppressed = IsStackTraceSuppressed(&stack); \
71 GET_CURRENT_PC_BP_SP; \
72 __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \
77 #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)
82 #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))
86 #define ASAN_READ_STRING(ctx, s, n) \
87 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
89 // 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.
92 static inline bool RangesOverlap(const char *offset1, uptr length1,
93 const char *offset2, uptr length2) {
94 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
96 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
97 const char *offset1 = (const char*)_offset1; \
98 const char *offset2 = (const char*)_offset2; \
99 if (RangesOverlap(offset1, length1, offset2, length2)) { \
100 GET_STACK_TRACE_FATAL_HERE; \
101 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
102 offset2, length2, &stack); \
106 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
107 #if ASAN_INTERCEPT_STRNLEN
108 if (REAL(strnlen) != 0) {
109 return REAL(strnlen)(s, maxlen);
112 return internal_strnlen(s, maxlen);
115 void SetThreadName(const char *name) {
116 AsanThread *t = GetCurrentThread();
118 asanThreadRegistry().SetThreadName(t->tid(), name);
122 // FIXME: ask frontend whether we need to return failure.
126 } // namespace __asan
128 // ---------------------- Wrappers ---------------- {{{1
129 using namespace __asan; // NOLINT
131 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
132 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
134 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \
135 AsanInterceptorContext _ctx = {#func}; \
136 ctx = (void *)&_ctx; \
139 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
140 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
141 ASAN_WRITE_RANGE(ctx, ptr, size)
142 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
143 ASAN_READ_RANGE(ctx, ptr, size)
144 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
145 ASAN_INTERCEPTOR_ENTER(ctx, func); \
147 if (asan_init_is_running) \
148 return REAL(func)(__VA_ARGS__); \
149 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
150 return REAL(func)(__VA_ARGS__); \
151 ENSURE_ASAN_INITED(); \
153 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
156 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
159 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
162 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
165 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
166 // 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
170 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
173 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
174 // 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(); \
180 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
181 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
182 CoverageUpdateMapping()
183 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
184 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
185 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
186 if (AsanThread *t = GetCurrentThread()) { \
187 *begin = t->tls_begin(); \
188 *end = t->tls_end(); \
192 #include "sanitizer_common/sanitizer_common_interceptors.inc"
194 // Syscall interceptors don't have contexts, we don't support suppressions
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)
198 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
203 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
208 #include "sanitizer_common/sanitizer_common_syscalls.inc"
210 struct ThreadStartParam {
212 atomic_uintptr_t is_registered;
215 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
216 ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
217 AsanThread *t = nullptr;
218 while ((t = reinterpret_cast<AsanThread *>(
219 atomic_load(¶m->t, memory_order_acquire))) == 0)
220 internal_sched_yield();
222 return t->ThreadStart(GetTid(), ¶m->is_registered);
225 #if ASAN_INTERCEPT_PTHREAD_CREATE
226 INTERCEPTOR(int, pthread_create, void *thread,
227 void *attr, void *(*start_routine)(void*), void *arg) {
228 EnsureMainThreadIDIsCorrect();
229 // Strict init-order checking is thread-hostile.
230 if (flags()->strict_init_order)
231 StopInitOrderChecking();
232 GET_STACK_TRACE_THREAD;
235 REAL(pthread_attr_getdetachstate)(attr, &detached);
236 ThreadStartParam param;
237 atomic_store(¶m.t, 0, memory_order_relaxed);
238 atomic_store(¶m.is_registered, 0, memory_order_relaxed);
239 int result = REAL(pthread_create)(thread, attr, asan_thread_start, ¶m);
241 u32 current_tid = GetCurrentTidOrInvalid();
243 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
244 atomic_store(¶m.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(¶m.is_registered, memory_order_acquire) == 0)
252 internal_sched_yield();
257 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
258 return real_pthread_join(t, arg);
261 DEFINE_REAL_PTHREAD_FUNCTIONS
262 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
264 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
266 #if SANITIZER_ANDROID
267 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
268 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
269 return REAL(bsd_signal)(signum, handler);
274 INTERCEPTOR(void*, signal, int signum, void *handler) {
275 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
276 return REAL(signal)(signum, handler);
282 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
283 struct sigaction *oldact) {
284 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
285 return REAL(sigaction)(signum, act, oldact);
290 namespace __sanitizer {
291 int real_sigaction(int signum, const void *act, void *oldact) {
292 return REAL(sigaction)(signum, (const struct sigaction *)act,
293 (struct sigaction *)oldact);
295 } // namespace __sanitizer
297 #elif SANITIZER_POSIX
298 // We need to have defined REAL(sigaction) on posix systems.
299 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
300 struct sigaction *oldact)
301 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
303 #if ASAN_INTERCEPT_SWAPCONTEXT
304 static 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
311 if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
312 PoisonShadow(bottom, ssize, 0);
316 INTERCEPTOR(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;
324 // Clear shadow memory for new context (it may share stack
325 // with current context).
327 ReadContextStack(ucp, &stack, &ssize);
328 ClearShadowMemoryForContextStack(stack, ssize);
329 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
334 ClearShadowMemoryForContextStack(stack, ssize);
337 #endif // ASAN_INTERCEPT_SWAPCONTEXT
339 INTERCEPTOR(void, longjmp, void *env, int val) {
340 __asan_handle_no_return();
341 REAL(longjmp)(env, val);
344 #if ASAN_INTERCEPT__LONGJMP
345 INTERCEPTOR(void, _longjmp, void *env, int val) {
346 __asan_handle_no_return();
347 REAL(_longjmp)(env, val);
351 #if ASAN_INTERCEPT_SIGLONGJMP
352 INTERCEPTOR(void, siglongjmp, void *env, int val) {
353 __asan_handle_no_return();
354 REAL(siglongjmp)(env, val);
358 #if ASAN_INTERCEPT___CXA_THROW
359 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
360 CHECK(REAL(__cxa_throw));
361 __asan_handle_no_return();
362 REAL(__cxa_throw)(a, b, c);
366 static inline int CharCmp(unsigned char c1, unsigned char c2) {
367 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
370 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
372 ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
373 if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
374 ENSURE_ASAN_INITED();
375 if (flags()->replace_intrin) {
376 if (flags()->strict_memcmp) {
377 // Check the entire regions even if the first bytes of the buffers are
379 ASAN_READ_RANGE(ctx, a1, size);
380 ASAN_READ_RANGE(ctx, a2, size);
381 // Fallthrough to REAL(memcmp) below.
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;
387 for (i = 0; i < size; i++) {
392 ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
393 ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
394 return CharCmp(c1, c2);
397 return REAL(memcmp(a1, a2, size));
400 // 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); \
408 ENSURE_ASAN_INITED(); \
409 if (flags()->replace_intrin) { \
411 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
413 ASAN_READ_RANGE(ctx, from, size); \
414 ASAN_WRITE_RANGE(ctx, to, size); \
416 return REAL(memcpy)(to, from, size); \
420 void *__asan_memcpy(void *to, const void *from, uptr size) {
421 ASAN_MEMCPY_IMPL(nullptr, to, from, size);
424 // 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); \
430 ENSURE_ASAN_INITED(); \
431 if (flags()->replace_intrin) { \
432 ASAN_WRITE_RANGE(ctx, block, size); \
434 return REAL(memset)(block, c, size); \
437 void *__asan_memset(void *block, int c, uptr size) {
438 ASAN_MEMSET_IMPL(nullptr, block, c, size);
441 #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); \
449 return internal_memmove(to, from, size); \
452 void *__asan_memmove(void *to, const void *from, uptr size) {
453 ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
456 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
458 ASAN_INTERCEPTOR_ENTER(ctx, memmove);
459 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
462 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
464 ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
466 ASAN_MEMCPY_IMPL(ctx, to, from, size);
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.
474 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
475 #endif // !SANITIZER_MAC
478 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
480 ASAN_INTERCEPTOR_ENTER(ctx, memset);
481 ASAN_MEMSET_IMPL(ctx, block, c, size);
484 INTERCEPTOR(char*, strchr, const char *str, int c) {
486 ASAN_INTERCEPTOR_ENTER(ctx, strchr);
487 if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
488 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
490 if (asan_init_is_running) {
491 return REAL(strchr)(str, c);
493 ENSURE_ASAN_INITED();
494 char *result = REAL(strchr)(str, c);
495 if (flags()->replace_str) {
496 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);
503 #if ASAN_INTERCEPT_INDEX
504 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
505 INTERCEPTOR(char*, index, const char *string, int c)
506 ALIAS(WRAPPER_NAME(strchr));
509 DECLARE_REAL(char*, index, const char *string, int c)
510 OVERRIDE_FUNCTION(index, strchr);
512 DEFINE_REAL(char*, index, const char *string, int c)
515 #endif // ASAN_INTERCEPT_INDEX
517 // For both strcat() and strncat() we need to check the validity of |to|
518 // argument irrespective of the |from| length.
519 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
521 ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
522 ENSURE_ASAN_INITED();
523 if (flags()->replace_str) {
524 uptr from_length = REAL(strlen)(from);
525 ASAN_READ_RANGE(ctx, from, from_length + 1);
526 uptr to_length = REAL(strlen)(to);
527 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
528 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
529 // 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.
532 if (from_length > 0) {
533 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
534 from, from_length + 1);
537 return REAL(strcat)(to, from); // NOLINT
540 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
542 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
543 ENSURE_ASAN_INITED();
544 if (flags()->replace_str) {
545 uptr from_length = MaybeRealStrnlen(from, size);
546 uptr copy_length = Min(size, from_length + 1);
547 ASAN_READ_RANGE(ctx, from, copy_length);
548 uptr to_length = REAL(strlen)(to);
549 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
550 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
551 if (from_length > 0) {
552 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
556 return REAL(strncat)(to, from, size);
559 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
561 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
563 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
565 // strcpy is called from malloc_default_purgeable_zone()
566 // in __asan::ReplaceSystemAlloc() on Mac.
567 if (asan_init_is_running) {
568 return REAL(strcpy)(to, from); // NOLINT
570 ENSURE_ASAN_INITED();
571 if (flags()->replace_str) {
572 uptr from_size = REAL(strlen)(from) + 1;
573 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
574 ASAN_READ_RANGE(ctx, from, from_size);
575 ASAN_WRITE_RANGE(ctx, to, from_size);
577 return REAL(strcpy)(to, from); // NOLINT
580 #if ASAN_INTERCEPT_STRDUP
581 INTERCEPTOR(char*, strdup, const char *s) {
583 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
584 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
585 ENSURE_ASAN_INITED();
586 uptr length = REAL(strlen)(s);
587 if (flags()->replace_str) {
588 ASAN_READ_RANGE(ctx, s, length + 1);
590 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);
597 INTERCEPTOR(SIZE_T, strlen, const char *s) {
599 ASAN_INTERCEPTOR_ENTER(ctx, strlen);
600 if (UNLIKELY(!asan_inited)) return internal_strlen(s);
601 // strlen is called from malloc_default_purgeable_zone()
602 // in __asan::ReplaceSystemAlloc() on Mac.
603 if (asan_init_is_running) {
604 return REAL(strlen)(s);
606 ENSURE_ASAN_INITED();
607 SIZE_T length = REAL(strlen)(s);
608 if (flags()->replace_str) {
609 ASAN_READ_RANGE(ctx, s, length + 1);
614 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
616 ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
617 SIZE_T length = REAL(wcslen)(s);
618 if (!asan_init_is_running) {
619 ENSURE_ASAN_INITED();
620 ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
625 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
627 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
628 ENSURE_ASAN_INITED();
629 if (flags()->replace_str) {
630 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
631 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
632 ASAN_READ_RANGE(ctx, from, from_size);
633 ASAN_WRITE_RANGE(ctx, to, size);
635 return REAL(strncpy)(to, from, size);
638 #if ASAN_INTERCEPT_STRNLEN
639 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
641 ASAN_INTERCEPTOR_ENTER(ctx, strnlen);
642 ENSURE_ASAN_INITED();
643 uptr length = REAL(strnlen)(s, maxlen);
644 if (flags()->replace_str) {
645 ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen));
649 #endif // ASAN_INTERCEPT_STRNLEN
651 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
652 char **endptr, int base) {
654 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
655 ENSURE_ASAN_INITED();
656 if (!flags()->replace_str) {
657 return REAL(strtol)(nptr, endptr, base);
660 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
661 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
665 INTERCEPTOR(int, atoi, const char *nptr) {
667 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
669 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
671 ENSURE_ASAN_INITED();
672 if (!flags()->replace_str) {
673 return REAL(atoi)(nptr);
676 // "man atoi" tells that behavior of atoi(nptr) is the same as
677 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
678 // 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);
682 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
686 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
688 ASAN_INTERCEPTOR_ENTER(ctx, atol);
690 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
692 ENSURE_ASAN_INITED();
693 if (!flags()->replace_str) {
694 return REAL(atol)(nptr);
697 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
698 FixRealStrtolEndptr(nptr, &real_endptr);
699 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
703 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
704 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
705 char **endptr, int base) {
707 ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
708 ENSURE_ASAN_INITED();
709 if (!flags()->replace_str) {
710 return REAL(strtoll)(nptr, endptr, base);
713 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
714 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
718 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
720 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
721 ENSURE_ASAN_INITED();
722 if (!flags()->replace_str) {
723 return REAL(atoll)(nptr);
726 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
727 FixRealStrtolEndptr(nptr, &real_endptr);
728 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
731 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
733 static void AtCxaAtexit(void *unused) {
735 StopInitOrderChecking();
738 #if ASAN_INTERCEPT___CXA_ATEXIT
739 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
742 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
744 ENSURE_ASAN_INITED();
745 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
746 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
749 #endif // ASAN_INTERCEPT___CXA_ATEXIT
751 #if ASAN_INTERCEPT_FORK
752 INTERCEPTOR(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);
759 #endif // ASAN_INTERCEPT_FORK
761 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
763 void InitializeAsanInterceptors() {
764 static bool was_called_once;
765 CHECK(was_called_once == false);
766 was_called_once = true;
767 InitializeCommonInterceptors();
769 // Intercept mem* functions.
770 ASAN_INTERCEPT_FUNC(memcmp);
771 ASAN_INTERCEPT_FUNC(memmove);
772 ASAN_INTERCEPT_FUNC(memset);
773 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
774 ASAN_INTERCEPT_FUNC(memcpy);
777 // Intercept str* functions.
778 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
779 ASAN_INTERCEPT_FUNC(strchr);
780 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
781 ASAN_INTERCEPT_FUNC(strlen);
782 ASAN_INTERCEPT_FUNC(wcslen);
783 ASAN_INTERCEPT_FUNC(strncat);
784 ASAN_INTERCEPT_FUNC(strncpy);
785 #if ASAN_INTERCEPT_STRDUP
786 ASAN_INTERCEPT_FUNC(strdup);
788 #if ASAN_INTERCEPT_STRNLEN
789 ASAN_INTERCEPT_FUNC(strnlen);
791 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
792 ASAN_INTERCEPT_FUNC(index);
795 ASAN_INTERCEPT_FUNC(atoi);
796 ASAN_INTERCEPT_FUNC(atol);
797 ASAN_INTERCEPT_FUNC(strtol);
798 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
799 ASAN_INTERCEPT_FUNC(atoll);
800 ASAN_INTERCEPT_FUNC(strtoll);
803 // Intecept signal- and jump-related functions.
804 ASAN_INTERCEPT_FUNC(longjmp);
805 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
806 ASAN_INTERCEPT_FUNC(sigaction);
807 #if SANITIZER_ANDROID
808 ASAN_INTERCEPT_FUNC(bsd_signal);
810 ASAN_INTERCEPT_FUNC(signal);
813 #if ASAN_INTERCEPT_SWAPCONTEXT
814 ASAN_INTERCEPT_FUNC(swapcontext);
816 #if ASAN_INTERCEPT__LONGJMP
817 ASAN_INTERCEPT_FUNC(_longjmp);
819 #if ASAN_INTERCEPT_SIGLONGJMP
820 ASAN_INTERCEPT_FUNC(siglongjmp);
823 // Intercept exception handling functions.
824 #if ASAN_INTERCEPT___CXA_THROW
825 ASAN_INTERCEPT_FUNC(__cxa_throw);
828 // Intercept threading-related functions
829 #if ASAN_INTERCEPT_PTHREAD_CREATE
830 ASAN_INTERCEPT_FUNC(pthread_create);
831 ASAN_INTERCEPT_FUNC(pthread_join);
834 // Intercept atexit function.
835 #if ASAN_INTERCEPT___CXA_ATEXIT
836 ASAN_INTERCEPT_FUNC(__cxa_atexit);
839 #if ASAN_INTERCEPT_FORK
840 ASAN_INTERCEPT_FUNC(fork);
843 InitializePlatformInterceptors();
845 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
848 } // namespace __asan