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"
28 // Return true if we can quickly decide that the region is unpoisoned.
29 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
30 if (size == 0) return true;
32 return !AddressIsPoisoned(beg) &&
33 !AddressIsPoisoned(beg + size - 1) &&
34 !AddressIsPoisoned(beg + size / 2);
38 struct AsanInterceptorContext {
39 const char *interceptor_name;
42 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
43 // and ASAN_WRITE_RANGE as macro instead of function so
44 // that no extra frames are created, and stack trace contains
45 // relevant information only.
46 // We check all shadow bytes.
47 #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
48 uptr __offset = (uptr)(offset); \
49 uptr __size = (uptr)(size); \
51 if (__offset > __offset + __size) { \
52 GET_STACK_TRACE_FATAL_HERE; \
53 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
55 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
56 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
57 AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
58 bool suppressed = false; \
60 suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
61 if (!suppressed && HaveStackTraceBasedSuppressions()) { \
62 GET_STACK_TRACE_FATAL_HERE; \
63 suppressed = IsStackTraceSuppressed(&stack); \
67 GET_CURRENT_PC_BP_SP; \
68 __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
73 #define ASAN_READ_RANGE(ctx, offset, size) \
74 ACCESS_MEMORY_RANGE(ctx, offset, size, false)
75 #define ASAN_WRITE_RANGE(ctx, offset, size) \
76 ACCESS_MEMORY_RANGE(ctx, offset, size, true)
78 // Behavior of functions like "memcpy" or "strcpy" is undefined
79 // if memory intervals overlap. We report error in this case.
80 // Macro is used to avoid creation of new frames.
81 static inline bool RangesOverlap(const char *offset1, uptr length1,
82 const char *offset2, uptr length2) {
83 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
85 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
86 const char *offset1 = (const char*)_offset1; \
87 const char *offset2 = (const char*)_offset2; \
88 if (RangesOverlap(offset1, length1, offset2, length2)) { \
89 GET_STACK_TRACE_FATAL_HERE; \
90 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
91 offset2, length2, &stack); \
95 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
96 #if ASAN_INTERCEPT_STRNLEN
97 if (REAL(strnlen) != 0) {
98 return REAL(strnlen)(s, maxlen);
101 return internal_strnlen(s, maxlen);
104 void SetThreadName(const char *name) {
105 AsanThread *t = GetCurrentThread();
107 asanThreadRegistry().SetThreadName(t->tid(), name);
111 // FIXME: ask frontend whether we need to return failure.
115 } // namespace __asan
117 // ---------------------- Wrappers ---------------- {{{1
118 using namespace __asan; // NOLINT
120 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
121 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
124 #define ASAN_INTERCEPT_FUNC(name) \
126 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
127 VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
130 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
131 #define ASAN_INTERCEPT_FUNC(name)
132 #endif // SANITIZER_MAC
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, ...) \
146 if (asan_init_is_running) \
147 return REAL(func)(__VA_ARGS__); \
148 ASAN_INTERCEPTOR_ENTER(ctx, func); \
149 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
150 return REAL(func)(__VA_ARGS__); \
151 ENSURE_ASAN_INITED(); \
153 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
156 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
159 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
162 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
163 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
164 // But asan does not remember UserId's for threads (pthread_t);
165 // and remembers all ever existed threads, so the linear search by UserId
167 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
170 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
171 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
172 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping()
173 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping()
174 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
175 #include "sanitizer_common/sanitizer_common_interceptors.inc"
177 // Syscall interceptors don't have contexts, we don't support suppressions
179 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
180 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
181 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
186 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
191 #include "sanitizer_common/sanitizer_common_syscalls.inc"
193 struct ThreadStartParam {
195 atomic_uintptr_t is_registered;
198 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
199 ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
200 AsanThread *t = nullptr;
201 while ((t = reinterpret_cast<AsanThread *>(
202 atomic_load(¶m->t, memory_order_acquire))) == 0)
203 internal_sched_yield();
205 return t->ThreadStart(GetTid(), ¶m->is_registered);
208 #if ASAN_INTERCEPT_PTHREAD_CREATE
209 INTERCEPTOR(int, pthread_create, void *thread,
210 void *attr, void *(*start_routine)(void*), void *arg) {
211 EnsureMainThreadIDIsCorrect();
212 // Strict init-order checking is thread-hostile.
213 if (flags()->strict_init_order)
214 StopInitOrderChecking();
215 GET_STACK_TRACE_THREAD;
218 REAL(pthread_attr_getdetachstate)(attr, &detached);
219 ThreadStartParam param;
220 atomic_store(¶m.t, 0, memory_order_relaxed);
221 atomic_store(¶m.is_registered, 0, memory_order_relaxed);
222 int result = REAL(pthread_create)(thread, attr, asan_thread_start, ¶m);
224 u32 current_tid = GetCurrentTidOrInvalid();
226 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
227 atomic_store(¶m.t, reinterpret_cast<uptr>(t), memory_order_release);
228 // Wait until the AsanThread object is initialized and the ThreadRegistry
229 // entry is in "started" state. One reason for this is that after this
230 // interceptor exits, the child thread's stack may be the only thing holding
231 // the |arg| pointer. This may cause LSan to report a leak if leak checking
232 // happens at a point when the interceptor has already exited, but the stack
233 // range for the child thread is not yet known.
234 while (atomic_load(¶m.is_registered, memory_order_acquire) == 0)
235 internal_sched_yield();
239 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
241 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
243 #if SANITIZER_ANDROID
244 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
245 if (!AsanInterceptsSignal(signum) ||
246 common_flags()->allow_user_segv_handler) {
247 return REAL(bsd_signal)(signum, handler);
252 INTERCEPTOR(void*, signal, int signum, void *handler) {
253 if (!AsanInterceptsSignal(signum) ||
254 common_flags()->allow_user_segv_handler) {
255 return REAL(signal)(signum, handler);
261 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
262 struct sigaction *oldact) {
263 if (!AsanInterceptsSignal(signum) ||
264 common_flags()->allow_user_segv_handler) {
265 return REAL(sigaction)(signum, act, oldact);
270 namespace __sanitizer {
271 int real_sigaction(int signum, const void *act, void *oldact) {
272 return REAL(sigaction)(signum, (const struct sigaction *)act,
273 (struct sigaction *)oldact);
275 } // namespace __sanitizer
277 #elif SANITIZER_POSIX
278 // We need to have defined REAL(sigaction) on posix systems.
279 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
280 struct sigaction *oldact)
281 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
283 #if ASAN_INTERCEPT_SWAPCONTEXT
284 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
285 // Align to page size.
286 uptr PageSize = GetPageSizeCached();
287 uptr bottom = stack & ~(PageSize - 1);
288 ssize += stack - bottom;
289 ssize = RoundUpTo(ssize, PageSize);
290 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
291 if (ssize && ssize <= kMaxSaneContextStackSize) {
292 PoisonShadow(bottom, ssize, 0);
296 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
297 struct ucontext_t *ucp) {
298 static bool reported_warning = false;
299 if (!reported_warning) {
300 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
301 "functions and may produce false positives in some cases!\n");
302 reported_warning = true;
304 // Clear shadow memory for new context (it may share stack
305 // with current context).
307 ReadContextStack(ucp, &stack, &ssize);
308 ClearShadowMemoryForContextStack(stack, ssize);
309 int res = REAL(swapcontext)(oucp, ucp);
310 // swapcontext technically does not return, but program may swap context to
311 // "oucp" later, that would look as if swapcontext() returned 0.
312 // We need to clear shadow for ucp once again, as it may be in arbitrary
314 ClearShadowMemoryForContextStack(stack, ssize);
317 #endif // ASAN_INTERCEPT_SWAPCONTEXT
319 INTERCEPTOR(void, longjmp, void *env, int val) {
320 __asan_handle_no_return();
321 REAL(longjmp)(env, val);
324 #if ASAN_INTERCEPT__LONGJMP
325 INTERCEPTOR(void, _longjmp, void *env, int val) {
326 __asan_handle_no_return();
327 REAL(_longjmp)(env, val);
331 #if ASAN_INTERCEPT_SIGLONGJMP
332 INTERCEPTOR(void, siglongjmp, void *env, int val) {
333 __asan_handle_no_return();
334 REAL(siglongjmp)(env, val);
338 #if ASAN_INTERCEPT___CXA_THROW
339 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
340 CHECK(REAL(__cxa_throw));
341 __asan_handle_no_return();
342 REAL(__cxa_throw)(a, b, c);
346 #if SANITIZER_WINDOWS
347 INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
348 CHECK(REAL(RaiseException));
349 __asan_handle_no_return();
350 REAL(RaiseException)(a, b, c, d);
353 INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
354 CHECK(REAL(_except_handler3));
355 __asan_handle_no_return();
356 return REAL(_except_handler3)(a, b, c, d);
360 // This handler is named differently in -MT and -MD CRTs.
361 #define _except_handler4 _except_handler4_common
363 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
364 CHECK(REAL(_except_handler4));
365 __asan_handle_no_return();
366 return REAL(_except_handler4)(a, b, c, d);
370 static inline int CharCmp(unsigned char c1, unsigned char c2) {
371 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
374 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
376 ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
377 if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
378 ENSURE_ASAN_INITED();
379 if (flags()->replace_intrin) {
380 if (flags()->strict_memcmp) {
381 // Check the entire regions even if the first bytes of the buffers are
383 ASAN_READ_RANGE(ctx, a1, size);
384 ASAN_READ_RANGE(ctx, a2, size);
385 // Fallthrough to REAL(memcmp) below.
387 unsigned char c1 = 0, c2 = 0;
388 const unsigned char *s1 = (const unsigned char*)a1;
389 const unsigned char *s2 = (const unsigned char*)a2;
391 for (i = 0; i < size; i++) {
396 ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
397 ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
398 return CharCmp(c1, c2);
401 return REAL(memcmp(a1, a2, size));
404 // memcpy is called during __asan_init() from the internals of printf(...).
405 // We do not treat memcpy with to==from as a bug.
406 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
407 #define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \
408 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
409 if (asan_init_is_running) { \
410 return REAL(memcpy)(to, from, size); \
412 ENSURE_ASAN_INITED(); \
413 if (flags()->replace_intrin) { \
415 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
417 ASAN_READ_RANGE(ctx, from, size); \
418 ASAN_WRITE_RANGE(ctx, to, size); \
420 return REAL(memcpy)(to, from, size); \
424 void *__asan_memcpy(void *to, const void *from, uptr size) {
425 ASAN_MEMCPY_IMPL(nullptr, to, from, size);
428 // memset is called inside Printf.
429 #define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \
430 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
431 if (asan_init_is_running) { \
432 return REAL(memset)(block, c, size); \
434 ENSURE_ASAN_INITED(); \
435 if (flags()->replace_intrin) { \
436 ASAN_WRITE_RANGE(ctx, block, size); \
438 return REAL(memset)(block, c, size); \
441 void *__asan_memset(void *block, int c, uptr size) {
442 ASAN_MEMSET_IMPL(nullptr, block, c, size);
445 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \
446 if (UNLIKELY(!asan_inited)) \
447 return internal_memmove(to, from, size); \
448 ENSURE_ASAN_INITED(); \
449 if (flags()->replace_intrin) { \
450 ASAN_READ_RANGE(ctx, from, size); \
451 ASAN_WRITE_RANGE(ctx, to, size); \
453 return internal_memmove(to, from, size); \
456 void *__asan_memmove(void *to, const void *from, uptr size) {
457 ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
460 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
462 ASAN_INTERCEPTOR_ENTER(ctx, memmove);
463 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
466 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
468 ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
470 ASAN_MEMCPY_IMPL(ctx, to, from, size);
472 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
473 // with WRAP(memcpy). As a result, false positives are reported for memmove()
474 // calls. If we just disable error reporting with
475 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
476 // internal_memcpy(), which may lead to crashes, see
477 // http://llvm.org/bugs/show_bug.cgi?id=16362.
478 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
479 #endif // !SANITIZER_MAC
482 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
484 ASAN_INTERCEPTOR_ENTER(ctx, memset);
485 ASAN_MEMSET_IMPL(ctx, block, c, size);
488 INTERCEPTOR(char*, strchr, const char *str, int c) {
490 ASAN_INTERCEPTOR_ENTER(ctx, strchr);
491 if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
492 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
494 if (asan_init_is_running) {
495 return REAL(strchr)(str, c);
497 ENSURE_ASAN_INITED();
498 char *result = REAL(strchr)(str, c);
499 if (flags()->replace_str) {
500 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
501 ASAN_READ_RANGE(ctx, str, bytes_read);
506 #if ASAN_INTERCEPT_INDEX
507 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
508 INTERCEPTOR(char*, index, const char *string, int c)
509 ALIAS(WRAPPER_NAME(strchr));
512 DECLARE_REAL(char*, index, const char *string, int c)
513 OVERRIDE_FUNCTION(index, strchr);
515 DEFINE_REAL(char*, index, const char *string, int c)
518 #endif // ASAN_INTERCEPT_INDEX
520 // For both strcat() and strncat() we need to check the validity of |to|
521 // argument irrespective of the |from| length.
522 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
524 ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
525 ENSURE_ASAN_INITED();
526 if (flags()->replace_str) {
527 uptr from_length = REAL(strlen)(from);
528 ASAN_READ_RANGE(ctx, from, from_length + 1);
529 uptr to_length = REAL(strlen)(to);
530 ASAN_READ_RANGE(ctx, to, to_length);
531 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
532 // If the copying actually happens, the |from| string should not overlap
533 // with the resulting string starting at |to|, which has a length of
534 // to_length + from_length + 1.
535 if (from_length > 0) {
536 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
537 from, from_length + 1);
540 return REAL(strcat)(to, from); // NOLINT
543 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
545 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
546 ENSURE_ASAN_INITED();
547 if (flags()->replace_str) {
548 uptr from_length = MaybeRealStrnlen(from, size);
549 uptr copy_length = Min(size, from_length + 1);
550 ASAN_READ_RANGE(ctx, from, copy_length);
551 uptr to_length = REAL(strlen)(to);
552 ASAN_READ_RANGE(ctx, to, to_length);
553 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
554 if (from_length > 0) {
555 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
559 return REAL(strncat)(to, from, size);
562 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
564 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
566 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
568 // strcpy is called from malloc_default_purgeable_zone()
569 // in __asan::ReplaceSystemAlloc() on Mac.
570 if (asan_init_is_running) {
571 return REAL(strcpy)(to, from); // NOLINT
573 ENSURE_ASAN_INITED();
574 if (flags()->replace_str) {
575 uptr from_size = REAL(strlen)(from) + 1;
576 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
577 ASAN_READ_RANGE(ctx, from, from_size);
578 ASAN_WRITE_RANGE(ctx, to, from_size);
580 return REAL(strcpy)(to, from); // NOLINT
583 #if ASAN_INTERCEPT_STRDUP
584 INTERCEPTOR(char*, strdup, const char *s) {
586 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
587 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
588 ENSURE_ASAN_INITED();
589 uptr length = REAL(strlen)(s);
590 if (flags()->replace_str) {
591 ASAN_READ_RANGE(ctx, s, length + 1);
593 GET_STACK_TRACE_MALLOC;
594 void *new_mem = asan_malloc(length + 1, &stack);
595 REAL(memcpy)(new_mem, s, length + 1);
596 return reinterpret_cast<char*>(new_mem);
600 INTERCEPTOR(SIZE_T, strlen, const char *s) {
602 ASAN_INTERCEPTOR_ENTER(ctx, strlen);
603 if (UNLIKELY(!asan_inited)) return internal_strlen(s);
604 // strlen is called from malloc_default_purgeable_zone()
605 // in __asan::ReplaceSystemAlloc() on Mac.
606 if (asan_init_is_running) {
607 return REAL(strlen)(s);
609 ENSURE_ASAN_INITED();
610 SIZE_T length = REAL(strlen)(s);
611 if (flags()->replace_str) {
612 ASAN_READ_RANGE(ctx, s, length + 1);
617 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
619 ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
620 SIZE_T length = REAL(wcslen)(s);
621 if (!asan_init_is_running) {
622 ENSURE_ASAN_INITED();
623 ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
628 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
630 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
631 ENSURE_ASAN_INITED();
632 if (flags()->replace_str) {
633 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
634 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
635 ASAN_READ_RANGE(ctx, from, from_size);
636 ASAN_WRITE_RANGE(ctx, to, size);
638 return REAL(strncpy)(to, from, size);
641 #if ASAN_INTERCEPT_STRNLEN
642 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
644 ASAN_INTERCEPTOR_ENTER(ctx, strnlen);
645 ENSURE_ASAN_INITED();
646 uptr length = REAL(strnlen)(s, maxlen);
647 if (flags()->replace_str) {
648 ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen));
652 #endif // ASAN_INTERCEPT_STRNLEN
654 static inline bool IsValidStrtolBase(int base) {
655 return (base == 0) || (2 <= base && base <= 36);
658 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
660 if (nptr == *endptr) {
661 // No digits were found at strtol call, we need to find out the last
662 // symbol accessed by strtoll on our own.
663 // We get this symbol by skipping leading blanks and optional +/- sign.
664 while (IsSpace(*nptr)) nptr++;
665 if (*nptr == '+' || *nptr == '-') nptr++;
666 *endptr = const_cast<char *>(nptr);
668 CHECK(*endptr >= nptr);
671 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
672 char **endptr, int base) {
674 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
675 ENSURE_ASAN_INITED();
676 if (!flags()->replace_str) {
677 return REAL(strtol)(nptr, endptr, base);
680 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
682 *endptr = real_endptr;
684 if (IsValidStrtolBase(base)) {
685 FixRealStrtolEndptr(nptr, &real_endptr);
686 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
691 INTERCEPTOR(int, atoi, const char *nptr) {
693 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
695 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
697 ENSURE_ASAN_INITED();
698 if (!flags()->replace_str) {
699 return REAL(atoi)(nptr);
702 // "man atoi" tells that behavior of atoi(nptr) is the same as
703 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
704 // parsed integer can't be stored in *long* type (even if it's
705 // different from int). So, we just imitate this behavior.
706 int result = REAL(strtol)(nptr, &real_endptr, 10);
707 FixRealStrtolEndptr(nptr, &real_endptr);
708 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
712 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
714 ASAN_INTERCEPTOR_ENTER(ctx, atol);
716 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
718 ENSURE_ASAN_INITED();
719 if (!flags()->replace_str) {
720 return REAL(atol)(nptr);
723 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
724 FixRealStrtolEndptr(nptr, &real_endptr);
725 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
729 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
730 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
731 char **endptr, int base) {
733 ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
734 ENSURE_ASAN_INITED();
735 if (!flags()->replace_str) {
736 return REAL(strtoll)(nptr, endptr, base);
739 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
741 *endptr = real_endptr;
743 // If base has unsupported value, strtoll can exit with EINVAL
744 // without reading any characters. So do additional checks only
746 if (IsValidStrtolBase(base)) {
747 FixRealStrtolEndptr(nptr, &real_endptr);
748 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
753 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
755 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
756 ENSURE_ASAN_INITED();
757 if (!flags()->replace_str) {
758 return REAL(atoll)(nptr);
761 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
762 FixRealStrtolEndptr(nptr, &real_endptr);
763 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
766 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
768 static void AtCxaAtexit(void *unused) {
770 StopInitOrderChecking();
773 #if ASAN_INTERCEPT___CXA_ATEXIT
774 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
777 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
779 ENSURE_ASAN_INITED();
780 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
781 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
784 #endif // ASAN_INTERCEPT___CXA_ATEXIT
786 #if ASAN_INTERCEPT_FORK
787 INTERCEPTOR(int, fork, void) {
788 ENSURE_ASAN_INITED();
789 if (common_flags()->coverage) CovBeforeFork();
790 int pid = REAL(fork)();
791 if (common_flags()->coverage) CovAfterFork(pid);
794 #endif // ASAN_INTERCEPT_FORK
796 #if SANITIZER_WINDOWS
797 INTERCEPTOR_WINAPI(DWORD, CreateThread,
798 void* security, uptr stack_size,
799 DWORD (__stdcall *start_routine)(void*), void* arg,
800 DWORD thr_flags, void* tid) {
801 // Strict init-order checking is thread-hostile.
802 if (flags()->strict_init_order)
803 StopInitOrderChecking();
804 GET_STACK_TRACE_THREAD;
805 bool detached = false; // FIXME: how can we determine it on Windows?
806 ThreadStartParam param;
807 atomic_store(¶m.t, 0, memory_order_relaxed);
808 atomic_store(¶m.is_registered, 0, memory_order_relaxed);
809 DWORD result = REAL(CreateThread)(security, stack_size, asan_thread_start,
810 ¶m, thr_flags, tid);
812 u32 current_tid = GetCurrentTidOrInvalid();
814 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
815 atomic_store(¶m.t, reinterpret_cast<uptr>(t), memory_order_release);
816 // The pthread_create interceptor waits here, so we do the same for
818 while (atomic_load(¶m.is_registered, memory_order_acquire) == 0)
819 internal_sched_yield();
825 void InitializeWindowsInterceptors() {
826 ASAN_INTERCEPT_FUNC(CreateThread);
827 ASAN_INTERCEPT_FUNC(RaiseException);
828 ASAN_INTERCEPT_FUNC(_except_handler3);
829 ASAN_INTERCEPT_FUNC(_except_handler4);
832 } // namespace __asan
835 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
837 void InitializeAsanInterceptors() {
838 static bool was_called_once;
839 CHECK(was_called_once == false);
840 was_called_once = true;
841 InitializeCommonInterceptors();
843 // Intercept mem* functions.
844 ASAN_INTERCEPT_FUNC(memcmp);
845 ASAN_INTERCEPT_FUNC(memmove);
846 ASAN_INTERCEPT_FUNC(memset);
847 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
848 ASAN_INTERCEPT_FUNC(memcpy);
851 // Intercept str* functions.
852 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
853 ASAN_INTERCEPT_FUNC(strchr);
854 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
855 ASAN_INTERCEPT_FUNC(strlen);
856 ASAN_INTERCEPT_FUNC(wcslen);
857 ASAN_INTERCEPT_FUNC(strncat);
858 ASAN_INTERCEPT_FUNC(strncpy);
859 #if ASAN_INTERCEPT_STRDUP
860 ASAN_INTERCEPT_FUNC(strdup);
862 #if ASAN_INTERCEPT_STRNLEN
863 ASAN_INTERCEPT_FUNC(strnlen);
865 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
866 ASAN_INTERCEPT_FUNC(index);
869 ASAN_INTERCEPT_FUNC(atoi);
870 ASAN_INTERCEPT_FUNC(atol);
871 ASAN_INTERCEPT_FUNC(strtol);
872 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
873 ASAN_INTERCEPT_FUNC(atoll);
874 ASAN_INTERCEPT_FUNC(strtoll);
877 // Intecept signal- and jump-related functions.
878 ASAN_INTERCEPT_FUNC(longjmp);
879 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
880 ASAN_INTERCEPT_FUNC(sigaction);
881 #if SANITIZER_ANDROID
882 ASAN_INTERCEPT_FUNC(bsd_signal);
884 ASAN_INTERCEPT_FUNC(signal);
887 #if ASAN_INTERCEPT_SWAPCONTEXT
888 ASAN_INTERCEPT_FUNC(swapcontext);
890 #if ASAN_INTERCEPT__LONGJMP
891 ASAN_INTERCEPT_FUNC(_longjmp);
893 #if ASAN_INTERCEPT_SIGLONGJMP
894 ASAN_INTERCEPT_FUNC(siglongjmp);
897 // Intercept exception handling functions.
898 #if ASAN_INTERCEPT___CXA_THROW
899 ASAN_INTERCEPT_FUNC(__cxa_throw);
902 // Intercept threading-related functions
903 #if ASAN_INTERCEPT_PTHREAD_CREATE
904 ASAN_INTERCEPT_FUNC(pthread_create);
907 // Intercept atexit function.
908 #if ASAN_INTERCEPT___CXA_ATEXIT
909 ASAN_INTERCEPT_FUNC(__cxa_atexit);
912 #if ASAN_INTERCEPT_FORK
913 ASAN_INTERCEPT_FUNC(fork);
916 // Some Windows-specific interceptors.
917 #if SANITIZER_WINDOWS
918 InitializeWindowsInterceptors();
921 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
924 } // namespace __asan