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, ...) \
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 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
175 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
176 CoverageUpdateMapping()
177 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
178 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
179 #include "sanitizer_common/sanitizer_common_interceptors.inc"
181 // Syscall interceptors don't have contexts, we don't support suppressions
183 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
184 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
185 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
190 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
195 #include "sanitizer_common/sanitizer_common_syscalls.inc"
197 struct ThreadStartParam {
199 atomic_uintptr_t is_registered;
202 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
203 #if SANITIZER_WINDOWS
204 // FIXME: this is a bandaid fix for PR22025.
205 AsanThread *t = (AsanThread*)arg;
207 return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
209 ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
210 AsanThread *t = nullptr;
211 while ((t = reinterpret_cast<AsanThread *>(
212 atomic_load(¶m->t, memory_order_acquire))) == 0)
213 internal_sched_yield();
215 return t->ThreadStart(GetTid(), ¶m->is_registered);
219 #if ASAN_INTERCEPT_PTHREAD_CREATE
220 INTERCEPTOR(int, pthread_create, void *thread,
221 void *attr, void *(*start_routine)(void*), void *arg) {
222 EnsureMainThreadIDIsCorrect();
223 // Strict init-order checking is thread-hostile.
224 if (flags()->strict_init_order)
225 StopInitOrderChecking();
226 GET_STACK_TRACE_THREAD;
229 REAL(pthread_attr_getdetachstate)(attr, &detached);
230 ThreadStartParam param;
231 atomic_store(¶m.t, 0, memory_order_relaxed);
232 atomic_store(¶m.is_registered, 0, memory_order_relaxed);
233 int result = REAL(pthread_create)(thread, attr, asan_thread_start, ¶m);
235 u32 current_tid = GetCurrentTidOrInvalid();
237 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
238 atomic_store(¶m.t, reinterpret_cast<uptr>(t), memory_order_release);
239 // Wait until the AsanThread object is initialized and the ThreadRegistry
240 // entry is in "started" state. One reason for this is that after this
241 // interceptor exits, the child thread's stack may be the only thing holding
242 // the |arg| pointer. This may cause LSan to report a leak if leak checking
243 // happens at a point when the interceptor has already exited, but the stack
244 // range for the child thread is not yet known.
245 while (atomic_load(¶m.is_registered, memory_order_acquire) == 0)
246 internal_sched_yield();
251 INTERCEPTOR(int, pthread_join, void *t, void **arg) {
252 return real_pthread_join(t, arg);
255 DEFINE_REAL_PTHREAD_FUNCTIONS
256 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
258 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
260 #if SANITIZER_ANDROID
261 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
262 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
263 return REAL(bsd_signal)(signum, handler);
268 INTERCEPTOR(void*, signal, int signum, void *handler) {
269 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
270 return REAL(signal)(signum, handler);
276 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
277 struct sigaction *oldact) {
278 if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
279 return REAL(sigaction)(signum, act, oldact);
284 namespace __sanitizer {
285 int real_sigaction(int signum, const void *act, void *oldact) {
286 return REAL(sigaction)(signum, (const struct sigaction *)act,
287 (struct sigaction *)oldact);
289 } // namespace __sanitizer
291 #elif SANITIZER_POSIX
292 // We need to have defined REAL(sigaction) on posix systems.
293 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
294 struct sigaction *oldact)
295 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
297 #if ASAN_INTERCEPT_SWAPCONTEXT
298 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
299 // Align to page size.
300 uptr PageSize = GetPageSizeCached();
301 uptr bottom = stack & ~(PageSize - 1);
302 ssize += stack - bottom;
303 ssize = RoundUpTo(ssize, PageSize);
304 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
305 if (ssize && ssize <= kMaxSaneContextStackSize) {
306 PoisonShadow(bottom, ssize, 0);
310 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
311 struct ucontext_t *ucp) {
312 static bool reported_warning = false;
313 if (!reported_warning) {
314 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
315 "functions and may produce false positives in some cases!\n");
316 reported_warning = true;
318 // Clear shadow memory for new context (it may share stack
319 // with current context).
321 ReadContextStack(ucp, &stack, &ssize);
322 ClearShadowMemoryForContextStack(stack, ssize);
323 int res = REAL(swapcontext)(oucp, ucp);
324 // swapcontext technically does not return, but program may swap context to
325 // "oucp" later, that would look as if swapcontext() returned 0.
326 // We need to clear shadow for ucp once again, as it may be in arbitrary
328 ClearShadowMemoryForContextStack(stack, ssize);
331 #endif // ASAN_INTERCEPT_SWAPCONTEXT
333 INTERCEPTOR(void, longjmp, void *env, int val) {
334 __asan_handle_no_return();
335 REAL(longjmp)(env, val);
338 #if ASAN_INTERCEPT__LONGJMP
339 INTERCEPTOR(void, _longjmp, void *env, int val) {
340 __asan_handle_no_return();
341 REAL(_longjmp)(env, val);
345 #if ASAN_INTERCEPT_SIGLONGJMP
346 INTERCEPTOR(void, siglongjmp, void *env, int val) {
347 __asan_handle_no_return();
348 REAL(siglongjmp)(env, val);
352 #if ASAN_INTERCEPT___CXA_THROW
353 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
354 CHECK(REAL(__cxa_throw));
355 __asan_handle_no_return();
356 REAL(__cxa_throw)(a, b, c);
360 #if SANITIZER_WINDOWS
361 INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
362 CHECK(REAL(RaiseException));
363 __asan_handle_no_return();
364 REAL(RaiseException)(a, b, c, d);
367 INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
368 CHECK(REAL(_except_handler3));
369 __asan_handle_no_return();
370 return REAL(_except_handler3)(a, b, c, d);
374 // This handler is named differently in -MT and -MD CRTs.
375 #define _except_handler4 _except_handler4_common
377 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
378 CHECK(REAL(_except_handler4));
379 __asan_handle_no_return();
380 return REAL(_except_handler4)(a, b, c, d);
384 static inline int CharCmp(unsigned char c1, unsigned char c2) {
385 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
388 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
390 ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
391 if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
392 ENSURE_ASAN_INITED();
393 if (flags()->replace_intrin) {
394 if (flags()->strict_memcmp) {
395 // Check the entire regions even if the first bytes of the buffers are
397 ASAN_READ_RANGE(ctx, a1, size);
398 ASAN_READ_RANGE(ctx, a2, size);
399 // Fallthrough to REAL(memcmp) below.
401 unsigned char c1 = 0, c2 = 0;
402 const unsigned char *s1 = (const unsigned char*)a1;
403 const unsigned char *s2 = (const unsigned char*)a2;
405 for (i = 0; i < size; i++) {
410 ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
411 ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
412 return CharCmp(c1, c2);
415 return REAL(memcmp(a1, a2, size));
418 // memcpy is called during __asan_init() from the internals of printf(...).
419 // We do not treat memcpy with to==from as a bug.
420 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
421 #define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \
422 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
423 if (asan_init_is_running) { \
424 return REAL(memcpy)(to, from, size); \
426 ENSURE_ASAN_INITED(); \
427 if (flags()->replace_intrin) { \
429 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
431 ASAN_READ_RANGE(ctx, from, size); \
432 ASAN_WRITE_RANGE(ctx, to, size); \
434 return REAL(memcpy)(to, from, size); \
438 void *__asan_memcpy(void *to, const void *from, uptr size) {
439 ASAN_MEMCPY_IMPL(nullptr, to, from, size);
442 // memset is called inside Printf.
443 #define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \
444 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
445 if (asan_init_is_running) { \
446 return REAL(memset)(block, c, size); \
448 ENSURE_ASAN_INITED(); \
449 if (flags()->replace_intrin) { \
450 ASAN_WRITE_RANGE(ctx, block, size); \
452 return REAL(memset)(block, c, size); \
455 void *__asan_memset(void *block, int c, uptr size) {
456 ASAN_MEMSET_IMPL(nullptr, block, c, size);
459 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \
460 if (UNLIKELY(!asan_inited)) \
461 return internal_memmove(to, from, size); \
462 ENSURE_ASAN_INITED(); \
463 if (flags()->replace_intrin) { \
464 ASAN_READ_RANGE(ctx, from, size); \
465 ASAN_WRITE_RANGE(ctx, to, size); \
467 return internal_memmove(to, from, size); \
470 void *__asan_memmove(void *to, const void *from, uptr size) {
471 ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
474 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
476 ASAN_INTERCEPTOR_ENTER(ctx, memmove);
477 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
480 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
482 ASAN_INTERCEPTOR_ENTER(ctx, memcpy);
484 ASAN_MEMCPY_IMPL(ctx, to, from, size);
486 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
487 // with WRAP(memcpy). As a result, false positives are reported for memmove()
488 // calls. If we just disable error reporting with
489 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
490 // internal_memcpy(), which may lead to crashes, see
491 // http://llvm.org/bugs/show_bug.cgi?id=16362.
492 ASAN_MEMMOVE_IMPL(ctx, to, from, size);
493 #endif // !SANITIZER_MAC
496 INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
498 ASAN_INTERCEPTOR_ENTER(ctx, memset);
499 ASAN_MEMSET_IMPL(ctx, block, c, size);
502 INTERCEPTOR(char*, strchr, const char *str, int c) {
504 ASAN_INTERCEPTOR_ENTER(ctx, strchr);
505 if (UNLIKELY(!asan_inited)) return internal_strchr(str, c);
506 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
508 if (asan_init_is_running) {
509 return REAL(strchr)(str, c);
511 ENSURE_ASAN_INITED();
512 char *result = REAL(strchr)(str, c);
513 if (flags()->replace_str) {
514 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
515 ASAN_READ_RANGE(ctx, str, bytes_read);
520 #if ASAN_INTERCEPT_INDEX
521 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
522 INTERCEPTOR(char*, index, const char *string, int c)
523 ALIAS(WRAPPER_NAME(strchr));
526 DECLARE_REAL(char*, index, const char *string, int c)
527 OVERRIDE_FUNCTION(index, strchr);
529 DEFINE_REAL(char*, index, const char *string, int c)
532 #endif // ASAN_INTERCEPT_INDEX
534 // For both strcat() and strncat() we need to check the validity of |to|
535 // argument irrespective of the |from| length.
536 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
538 ASAN_INTERCEPTOR_ENTER(ctx, strcat); // NOLINT
539 ENSURE_ASAN_INITED();
540 if (flags()->replace_str) {
541 uptr from_length = REAL(strlen)(from);
542 ASAN_READ_RANGE(ctx, from, from_length + 1);
543 uptr to_length = REAL(strlen)(to);
544 ASAN_READ_RANGE(ctx, to, to_length);
545 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
546 // If the copying actually happens, the |from| string should not overlap
547 // with the resulting string starting at |to|, which has a length of
548 // to_length + from_length + 1.
549 if (from_length > 0) {
550 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
551 from, from_length + 1);
554 return REAL(strcat)(to, from); // NOLINT
557 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
559 ASAN_INTERCEPTOR_ENTER(ctx, strncat);
560 ENSURE_ASAN_INITED();
561 if (flags()->replace_str) {
562 uptr from_length = MaybeRealStrnlen(from, size);
563 uptr copy_length = Min(size, from_length + 1);
564 ASAN_READ_RANGE(ctx, from, copy_length);
565 uptr to_length = REAL(strlen)(to);
566 ASAN_READ_RANGE(ctx, to, to_length);
567 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
568 if (from_length > 0) {
569 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
573 return REAL(strncat)(to, from, size);
576 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
578 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); // NOLINT
580 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT
582 // strcpy is called from malloc_default_purgeable_zone()
583 // in __asan::ReplaceSystemAlloc() on Mac.
584 if (asan_init_is_running) {
585 return REAL(strcpy)(to, from); // NOLINT
587 ENSURE_ASAN_INITED();
588 if (flags()->replace_str) {
589 uptr from_size = REAL(strlen)(from) + 1;
590 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
591 ASAN_READ_RANGE(ctx, from, from_size);
592 ASAN_WRITE_RANGE(ctx, to, from_size);
594 return REAL(strcpy)(to, from); // NOLINT
597 #if ASAN_INTERCEPT_STRDUP
598 INTERCEPTOR(char*, strdup, const char *s) {
600 ASAN_INTERCEPTOR_ENTER(ctx, strdup);
601 if (UNLIKELY(!asan_inited)) return internal_strdup(s);
602 ENSURE_ASAN_INITED();
603 uptr length = REAL(strlen)(s);
604 if (flags()->replace_str) {
605 ASAN_READ_RANGE(ctx, s, length + 1);
607 GET_STACK_TRACE_MALLOC;
608 void *new_mem = asan_malloc(length + 1, &stack);
609 REAL(memcpy)(new_mem, s, length + 1);
610 return reinterpret_cast<char*>(new_mem);
614 INTERCEPTOR(SIZE_T, strlen, const char *s) {
616 ASAN_INTERCEPTOR_ENTER(ctx, strlen);
617 if (UNLIKELY(!asan_inited)) return internal_strlen(s);
618 // strlen is called from malloc_default_purgeable_zone()
619 // in __asan::ReplaceSystemAlloc() on Mac.
620 if (asan_init_is_running) {
621 return REAL(strlen)(s);
623 ENSURE_ASAN_INITED();
624 SIZE_T length = REAL(strlen)(s);
625 if (flags()->replace_str) {
626 ASAN_READ_RANGE(ctx, s, length + 1);
631 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
633 ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
634 SIZE_T length = REAL(wcslen)(s);
635 if (!asan_init_is_running) {
636 ENSURE_ASAN_INITED();
637 ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
642 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
644 ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
645 ENSURE_ASAN_INITED();
646 if (flags()->replace_str) {
647 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
648 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
649 ASAN_READ_RANGE(ctx, from, from_size);
650 ASAN_WRITE_RANGE(ctx, to, size);
652 return REAL(strncpy)(to, from, size);
655 #if ASAN_INTERCEPT_STRNLEN
656 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
658 ASAN_INTERCEPTOR_ENTER(ctx, strnlen);
659 ENSURE_ASAN_INITED();
660 uptr length = REAL(strnlen)(s, maxlen);
661 if (flags()->replace_str) {
662 ASAN_READ_RANGE(ctx, s, Min(length + 1, maxlen));
666 #endif // ASAN_INTERCEPT_STRNLEN
668 static inline bool IsValidStrtolBase(int base) {
669 return (base == 0) || (2 <= base && base <= 36);
672 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
674 if (nptr == *endptr) {
675 // No digits were found at strtol call, we need to find out the last
676 // symbol accessed by strtoll on our own.
677 // We get this symbol by skipping leading blanks and optional +/- sign.
678 while (IsSpace(*nptr)) nptr++;
679 if (*nptr == '+' || *nptr == '-') nptr++;
680 *endptr = const_cast<char *>(nptr);
682 CHECK(*endptr >= nptr);
685 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
686 char **endptr, int base) {
688 ASAN_INTERCEPTOR_ENTER(ctx, strtol);
689 ENSURE_ASAN_INITED();
690 if (!flags()->replace_str) {
691 return REAL(strtol)(nptr, endptr, base);
694 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
696 *endptr = real_endptr;
698 if (IsValidStrtolBase(base)) {
699 FixRealStrtolEndptr(nptr, &real_endptr);
700 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
705 INTERCEPTOR(int, atoi, const char *nptr) {
707 ASAN_INTERCEPTOR_ENTER(ctx, atoi);
709 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
711 ENSURE_ASAN_INITED();
712 if (!flags()->replace_str) {
713 return REAL(atoi)(nptr);
716 // "man atoi" tells that behavior of atoi(nptr) is the same as
717 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
718 // parsed integer can't be stored in *long* type (even if it's
719 // different from int). So, we just imitate this behavior.
720 int result = REAL(strtol)(nptr, &real_endptr, 10);
721 FixRealStrtolEndptr(nptr, &real_endptr);
722 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
726 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
728 ASAN_INTERCEPTOR_ENTER(ctx, atol);
730 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
732 ENSURE_ASAN_INITED();
733 if (!flags()->replace_str) {
734 return REAL(atol)(nptr);
737 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
738 FixRealStrtolEndptr(nptr, &real_endptr);
739 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
743 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
744 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
745 char **endptr, int base) {
747 ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
748 ENSURE_ASAN_INITED();
749 if (!flags()->replace_str) {
750 return REAL(strtoll)(nptr, endptr, base);
753 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
755 *endptr = real_endptr;
757 // If base has unsupported value, strtoll can exit with EINVAL
758 // without reading any characters. So do additional checks only
760 if (IsValidStrtolBase(base)) {
761 FixRealStrtolEndptr(nptr, &real_endptr);
762 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
767 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
769 ASAN_INTERCEPTOR_ENTER(ctx, atoll);
770 ENSURE_ASAN_INITED();
771 if (!flags()->replace_str) {
772 return REAL(atoll)(nptr);
775 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
776 FixRealStrtolEndptr(nptr, &real_endptr);
777 ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
780 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
782 static void AtCxaAtexit(void *unused) {
784 StopInitOrderChecking();
787 #if ASAN_INTERCEPT___CXA_ATEXIT
788 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
791 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
793 ENSURE_ASAN_INITED();
794 int res = REAL(__cxa_atexit)(func, arg, dso_handle);
795 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
798 #endif // ASAN_INTERCEPT___CXA_ATEXIT
800 #if ASAN_INTERCEPT_FORK
801 INTERCEPTOR(int, fork, void) {
802 ENSURE_ASAN_INITED();
803 if (common_flags()->coverage) CovBeforeFork();
804 int pid = REAL(fork)();
805 if (common_flags()->coverage) CovAfterFork(pid);
808 #endif // ASAN_INTERCEPT_FORK
810 #if SANITIZER_WINDOWS
811 INTERCEPTOR_WINAPI(DWORD, CreateThread,
812 void* security, uptr stack_size,
813 DWORD (__stdcall *start_routine)(void*), void* arg,
814 DWORD thr_flags, void* tid) {
815 // Strict init-order checking is thread-hostile.
816 if (flags()->strict_init_order)
817 StopInitOrderChecking();
818 GET_STACK_TRACE_THREAD;
819 // FIXME: The CreateThread interceptor is not the same as a pthread_create
820 // one. This is a bandaid fix for PR22025.
821 bool detached = false; // FIXME: how can we determine it on Windows?
822 u32 current_tid = GetCurrentTidOrInvalid();
824 AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
825 return REAL(CreateThread)(security, stack_size,
826 asan_thread_start, t, thr_flags, tid);
830 void InitializeWindowsInterceptors() {
831 ASAN_INTERCEPT_FUNC(CreateThread);
832 ASAN_INTERCEPT_FUNC(RaiseException);
833 ASAN_INTERCEPT_FUNC(_except_handler3);
834 ASAN_INTERCEPT_FUNC(_except_handler4);
837 } // namespace __asan
840 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
842 void InitializeAsanInterceptors() {
843 static bool was_called_once;
844 CHECK(was_called_once == false);
845 was_called_once = true;
846 InitializeCommonInterceptors();
848 // Intercept mem* functions.
849 ASAN_INTERCEPT_FUNC(memcmp);
850 ASAN_INTERCEPT_FUNC(memmove);
851 ASAN_INTERCEPT_FUNC(memset);
852 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
853 ASAN_INTERCEPT_FUNC(memcpy);
856 // Intercept str* functions.
857 ASAN_INTERCEPT_FUNC(strcat); // NOLINT
858 ASAN_INTERCEPT_FUNC(strchr);
859 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
860 ASAN_INTERCEPT_FUNC(strlen);
861 ASAN_INTERCEPT_FUNC(wcslen);
862 ASAN_INTERCEPT_FUNC(strncat);
863 ASAN_INTERCEPT_FUNC(strncpy);
864 #if ASAN_INTERCEPT_STRDUP
865 ASAN_INTERCEPT_FUNC(strdup);
867 #if ASAN_INTERCEPT_STRNLEN
868 ASAN_INTERCEPT_FUNC(strnlen);
870 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
871 ASAN_INTERCEPT_FUNC(index);
874 ASAN_INTERCEPT_FUNC(atoi);
875 ASAN_INTERCEPT_FUNC(atol);
876 ASAN_INTERCEPT_FUNC(strtol);
877 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
878 ASAN_INTERCEPT_FUNC(atoll);
879 ASAN_INTERCEPT_FUNC(strtoll);
882 // Intecept signal- and jump-related functions.
883 ASAN_INTERCEPT_FUNC(longjmp);
884 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
885 ASAN_INTERCEPT_FUNC(sigaction);
886 #if SANITIZER_ANDROID
887 ASAN_INTERCEPT_FUNC(bsd_signal);
889 ASAN_INTERCEPT_FUNC(signal);
892 #if ASAN_INTERCEPT_SWAPCONTEXT
893 ASAN_INTERCEPT_FUNC(swapcontext);
895 #if ASAN_INTERCEPT__LONGJMP
896 ASAN_INTERCEPT_FUNC(_longjmp);
898 #if ASAN_INTERCEPT_SIGLONGJMP
899 ASAN_INTERCEPT_FUNC(siglongjmp);
902 // Intercept exception handling functions.
903 #if ASAN_INTERCEPT___CXA_THROW
904 ASAN_INTERCEPT_FUNC(__cxa_throw);
907 // Intercept threading-related functions
908 #if ASAN_INTERCEPT_PTHREAD_CREATE
909 ASAN_INTERCEPT_FUNC(pthread_create);
910 ASAN_INTERCEPT_FUNC(pthread_join);
913 // Intercept atexit function.
914 #if ASAN_INTERCEPT___CXA_ATEXIT
915 ASAN_INTERCEPT_FUNC(__cxa_atexit);
918 #if ASAN_INTERCEPT_FORK
919 ASAN_INTERCEPT_FUNC(fork);
922 // Some Windows-specific interceptors.
923 #if SANITIZER_WINDOWS
924 InitializeWindowsInterceptors();
927 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
930 } // namespace __asan