1 //===-- asan_interceptors.cc ----------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Intercept various libc functions.
11 //===----------------------------------------------------------------------===//
12 #include "asan_interceptors.h"
14 #include "asan_allocator.h"
15 #include "asan_internal.h"
16 #include "asan_mapping.h"
17 #include "asan_poisoning.h"
18 #include "asan_report.h"
19 #include "asan_stack.h"
20 #include "asan_stats.h"
21 #include "sanitizer_common/sanitizer_libc.h"
25 // Return true if we can quickly decide that the region is unpoisoned.
26 static inline bool QuickCheckForUnpoisonedRegion(uptr beg
, uptr size
) {
27 if (size
== 0) return true;
29 return !AddressIsPoisoned(beg
) &&
30 !AddressIsPoisoned(beg
+ size
- 1) &&
31 !AddressIsPoisoned(beg
+ size
/ 2);
35 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
36 // and ASAN_WRITE_RANGE as macro instead of function so
37 // that no extra frames are created, and stack trace contains
38 // relevant information only.
39 // We check all shadow bytes.
40 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
41 uptr __offset = (uptr)(offset); \
42 uptr __size = (uptr)(size); \
44 if (__offset > __offset + __size) { \
45 GET_STACK_TRACE_FATAL_HERE; \
46 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
48 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
49 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
50 GET_CURRENT_PC_BP_SP; \
51 __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
55 #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
56 #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
58 // Behavior of functions like "memcpy" or "strcpy" is undefined
59 // if memory intervals overlap. We report error in this case.
60 // Macro is used to avoid creation of new frames.
61 static inline bool RangesOverlap(const char *offset1
, uptr length1
,
62 const char *offset2
, uptr length2
) {
63 return !((offset1
+ length1
<= offset2
) || (offset2
+ length2
<= offset1
));
65 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
66 const char *offset1 = (const char*)_offset1; \
67 const char *offset2 = (const char*)_offset2; \
68 if (RangesOverlap(offset1, length1, offset2, length2)) { \
69 GET_STACK_TRACE_FATAL_HERE; \
70 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
71 offset2, length2, &stack); \
75 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
76 #if ASAN_INTERCEPT_STRNLEN
77 if (REAL(strnlen
) != 0) {
78 return REAL(strnlen
)(s
, maxlen
);
81 return internal_strnlen(s
, maxlen
);
84 void SetThreadName(const char *name
) {
85 AsanThread
*t
= GetCurrentThread();
87 asanThreadRegistry().SetThreadName(t
->tid(), name
);
91 // FIXME: ask frontend whether we need to return failure.
97 // ---------------------- Wrappers ---------------- {{{1
98 using namespace __asan
; // NOLINT
100 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc
, uptr
)
101 DECLARE_REAL_AND_INTERCEPTOR(void, free
, void *)
104 #define ASAN_INTERCEPT_FUNC(name) \
106 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
107 VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
110 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
111 #define ASAN_INTERCEPT_FUNC(name)
112 #endif // SANITIZER_MAC
114 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
115 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
116 ASAN_WRITE_RANGE(ptr, size)
117 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
118 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
120 if (asan_init_is_running) \
121 return REAL(func)(__VA_ARGS__); \
124 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
125 return REAL(func)(__VA_ARGS__); \
126 ENSURE_ASAN_INITED(); \
128 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
131 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
134 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
137 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
138 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
139 // But asan does not remember UserId's for threads (pthread_t);
140 // and remembers all ever existed threads, so the linear search by UserId
142 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
145 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
146 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
147 #include "sanitizer_common/sanitizer_common_interceptors.inc"
149 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
150 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
151 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
156 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
161 #include "sanitizer_common/sanitizer_common_syscalls.inc"
163 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
164 AsanThread
*t
= (AsanThread
*)arg
;
166 return t
->ThreadStart(GetTid());
169 #if ASAN_INTERCEPT_PTHREAD_CREATE
170 INTERCEPTOR(int, pthread_create
, void *thread
,
171 void *attr
, void *(*start_routine
)(void*), void *arg
) {
172 EnsureMainThreadIDIsCorrect();
173 // Strict init-order checking in thread-hostile.
174 if (flags()->strict_init_order
)
175 StopInitOrderChecking();
176 GET_STACK_TRACE_THREAD
;
179 REAL(pthread_attr_getdetachstate
)(attr
, &detached
);
181 u32 current_tid
= GetCurrentTidOrInvalid();
182 AsanThread
*t
= AsanThread::Create(start_routine
, arg
);
183 CreateThreadContextArgs args
= { t
, &stack
};
184 asanThreadRegistry().CreateThread(*(uptr
*)t
, detached
, current_tid
, &args
);
185 return REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
187 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
189 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
191 #if SANITIZER_ANDROID
192 INTERCEPTOR(void*, bsd_signal
, int signum
, void *handler
) {
193 if (!AsanInterceptsSignal(signum
) ||
194 common_flags()->allow_user_segv_handler
) {
195 return REAL(bsd_signal
)(signum
, handler
);
200 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
201 if (!AsanInterceptsSignal(signum
) ||
202 common_flags()->allow_user_segv_handler
) {
203 return REAL(signal
)(signum
, handler
);
209 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
210 struct sigaction
*oldact
) {
211 if (!AsanInterceptsSignal(signum
) ||
212 common_flags()->allow_user_segv_handler
) {
213 return REAL(sigaction
)(signum
, act
, oldact
);
218 namespace __sanitizer
{
219 int real_sigaction(int signum
, const void *act
, void *oldact
) {
220 return REAL(sigaction
)(signum
,
221 (struct sigaction
*)act
, (struct sigaction
*)oldact
);
223 } // namespace __sanitizer
225 #elif SANITIZER_POSIX
226 // We need to have defined REAL(sigaction) on posix systems.
227 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
228 struct sigaction
*oldact
)
229 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
231 #if ASAN_INTERCEPT_SWAPCONTEXT
232 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
233 // Align to page size.
234 uptr PageSize
= GetPageSizeCached();
235 uptr bottom
= stack
& ~(PageSize
- 1);
236 ssize
+= stack
- bottom
;
237 ssize
= RoundUpTo(ssize
, PageSize
);
238 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
239 if (ssize
&& ssize
<= kMaxSaneContextStackSize
) {
240 PoisonShadow(bottom
, ssize
, 0);
244 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
245 struct ucontext_t
*ucp
) {
246 static bool reported_warning
= false;
247 if (!reported_warning
) {
248 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
249 "functions and may produce false positives in some cases!\n");
250 reported_warning
= true;
252 // Clear shadow memory for new context (it may share stack
253 // with current context).
255 ReadContextStack(ucp
, &stack
, &ssize
);
256 ClearShadowMemoryForContextStack(stack
, ssize
);
257 int res
= REAL(swapcontext
)(oucp
, ucp
);
258 // swapcontext technically does not return, but program may swap context to
259 // "oucp" later, that would look as if swapcontext() returned 0.
260 // We need to clear shadow for ucp once again, as it may be in arbitrary
262 ClearShadowMemoryForContextStack(stack
, ssize
);
265 #endif // ASAN_INTERCEPT_SWAPCONTEXT
267 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
268 __asan_handle_no_return();
269 REAL(longjmp
)(env
, val
);
272 #if ASAN_INTERCEPT__LONGJMP
273 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
274 __asan_handle_no_return();
275 REAL(_longjmp
)(env
, val
);
279 #if ASAN_INTERCEPT_SIGLONGJMP
280 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
281 __asan_handle_no_return();
282 REAL(siglongjmp
)(env
, val
);
286 #if ASAN_INTERCEPT___CXA_THROW
287 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
288 CHECK(REAL(__cxa_throw
));
289 __asan_handle_no_return();
290 REAL(__cxa_throw
)(a
, b
, c
);
294 // intercept mlock and friends.
295 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
296 // All functions return 0 (success).
297 static void MlockIsUnsupported() {
298 static bool printed
= false;
302 "INFO: AddressSanitizer ignores "
303 "mlock/mlockall/munlock/munlockall\n");
306 INTERCEPTOR(int, mlock
, const void *addr
, uptr len
) {
307 MlockIsUnsupported();
311 INTERCEPTOR(int, munlock
, const void *addr
, uptr len
) {
312 MlockIsUnsupported();
316 INTERCEPTOR(int, mlockall
, int flags
) {
317 MlockIsUnsupported();
321 INTERCEPTOR(int, munlockall
, void) {
322 MlockIsUnsupported();
326 static inline int CharCmp(unsigned char c1
, unsigned char c2
) {
327 return (c1
== c2
) ? 0 : (c1
< c2
) ? -1 : 1;
330 INTERCEPTOR(int, memcmp
, const void *a1
, const void *a2
, uptr size
) {
331 if (UNLIKELY(!asan_inited
)) return internal_memcmp(a1
, a2
, size
);
332 ENSURE_ASAN_INITED();
333 if (flags()->replace_intrin
) {
334 if (flags()->strict_memcmp
) {
335 // Check the entire regions even if the first bytes of the buffers are
337 ASAN_READ_RANGE(a1
, size
);
338 ASAN_READ_RANGE(a2
, size
);
339 // Fallthrough to REAL(memcmp) below.
341 unsigned char c1
= 0, c2
= 0;
342 const unsigned char *s1
= (const unsigned char*)a1
;
343 const unsigned char *s2
= (const unsigned char*)a2
;
345 for (i
= 0; i
< size
; i
++) {
350 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
351 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
352 return CharCmp(c1
, c2
);
355 return REAL(memcmp(a1
, a2
, size
));
358 void *__asan_memcpy(void *to
, const void *from
, uptr size
) {
359 if (UNLIKELY(!asan_inited
)) return internal_memcpy(to
, from
, size
);
360 // memcpy is called during __asan_init() from the internals
362 if (asan_init_is_running
) {
363 return REAL(memcpy
)(to
, from
, size
);
365 ENSURE_ASAN_INITED();
366 if (flags()->replace_intrin
) {
368 // We do not treat memcpy with to==from as a bug.
369 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
370 CHECK_RANGES_OVERLAP("memcpy", to
, size
, from
, size
);
372 ASAN_READ_RANGE(from
, size
);
373 ASAN_WRITE_RANGE(to
, size
);
375 return REAL(memcpy
)(to
, from
, size
);
378 void *__asan_memset(void *block
, int c
, uptr size
) {
379 if (UNLIKELY(!asan_inited
)) return internal_memset(block
, c
, size
);
380 // memset is called inside Printf.
381 if (asan_init_is_running
) {
382 return REAL(memset
)(block
, c
, size
);
384 ENSURE_ASAN_INITED();
385 if (flags()->replace_intrin
) {
386 ASAN_WRITE_RANGE(block
, size
);
388 return REAL(memset
)(block
, c
, size
);
391 void *__asan_memmove(void *to
, const void *from
, uptr size
) {
392 if (UNLIKELY(!asan_inited
))
393 return internal_memmove(to
, from
, size
);
394 ENSURE_ASAN_INITED();
395 if (flags()->replace_intrin
) {
396 ASAN_READ_RANGE(from
, size
);
397 ASAN_WRITE_RANGE(to
, size
);
399 return internal_memmove(to
, from
, size
);
402 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
403 return __asan_memmove(to
, from
, size
);
406 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
408 return __asan_memcpy(to
, from
, size
);
410 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
411 // with WRAP(memcpy). As a result, false positives are reported for memmove()
412 // calls. If we just disable error reporting with
413 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
414 // internal_memcpy(), which may lead to crashes, see
415 // http://llvm.org/bugs/show_bug.cgi?id=16362.
416 return __asan_memmove(to
, from
, size
);
417 #endif // !SANITIZER_MAC
420 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
421 return __asan_memset(block
, c
, size
);
424 INTERCEPTOR(char*, strchr
, const char *str
, int c
) {
425 if (UNLIKELY(!asan_inited
)) return internal_strchr(str
, c
);
426 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
428 if (asan_init_is_running
) {
429 return REAL(strchr
)(str
, c
);
431 ENSURE_ASAN_INITED();
432 char *result
= REAL(strchr
)(str
, c
);
433 if (flags()->replace_str
) {
434 uptr bytes_read
= (result
? result
- str
: REAL(strlen
)(str
)) + 1;
435 ASAN_READ_RANGE(str
, bytes_read
);
440 #if ASAN_INTERCEPT_INDEX
441 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
442 INTERCEPTOR(char*, index
, const char *string
, int c
)
443 ALIAS(WRAPPER_NAME(strchr
));
446 DECLARE_REAL(char*, index
, const char *string
, int c
)
447 OVERRIDE_FUNCTION(index
, strchr
);
449 DEFINE_REAL(char*, index
, const char *string
, int c
)
452 #endif // ASAN_INTERCEPT_INDEX
454 // For both strcat() and strncat() we need to check the validity of |to|
455 // argument irrespective of the |from| length.
456 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
457 ENSURE_ASAN_INITED();
458 if (flags()->replace_str
) {
459 uptr from_length
= REAL(strlen
)(from
);
460 ASAN_READ_RANGE(from
, from_length
+ 1);
461 uptr to_length
= REAL(strlen
)(to
);
462 ASAN_READ_RANGE(to
, to_length
);
463 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
464 // If the copying actually happens, the |from| string should not overlap
465 // with the resulting string starting at |to|, which has a length of
466 // to_length + from_length + 1.
467 if (from_length
> 0) {
468 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
469 from
, from_length
+ 1);
472 return REAL(strcat
)(to
, from
); // NOLINT
475 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
476 ENSURE_ASAN_INITED();
477 if (flags()->replace_str
) {
478 uptr from_length
= MaybeRealStrnlen(from
, size
);
479 uptr copy_length
= Min(size
, from_length
+ 1);
480 ASAN_READ_RANGE(from
, copy_length
);
481 uptr to_length
= REAL(strlen
)(to
);
482 ASAN_READ_RANGE(to
, to_length
);
483 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
484 if (from_length
> 0) {
485 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
489 return REAL(strncat
)(to
, from
, size
);
492 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
494 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
496 // strcpy is called from malloc_default_purgeable_zone()
497 // in __asan::ReplaceSystemAlloc() on Mac.
498 if (asan_init_is_running
) {
499 return REAL(strcpy
)(to
, from
); // NOLINT
501 ENSURE_ASAN_INITED();
502 if (flags()->replace_str
) {
503 uptr from_size
= REAL(strlen
)(from
) + 1;
504 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
505 ASAN_READ_RANGE(from
, from_size
);
506 ASAN_WRITE_RANGE(to
, from_size
);
508 return REAL(strcpy
)(to
, from
); // NOLINT
511 #if ASAN_INTERCEPT_STRDUP
512 INTERCEPTOR(char*, strdup
, const char *s
) {
513 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
514 ENSURE_ASAN_INITED();
515 uptr length
= REAL(strlen
)(s
);
516 if (flags()->replace_str
) {
517 ASAN_READ_RANGE(s
, length
+ 1);
519 GET_STACK_TRACE_MALLOC
;
520 void *new_mem
= asan_malloc(length
+ 1, &stack
);
521 REAL(memcpy
)(new_mem
, s
, length
+ 1);
522 return reinterpret_cast<char*>(new_mem
);
526 INTERCEPTOR(uptr
, strlen
, const char *s
) {
527 if (UNLIKELY(!asan_inited
)) return internal_strlen(s
);
528 // strlen is called from malloc_default_purgeable_zone()
529 // in __asan::ReplaceSystemAlloc() on Mac.
530 if (asan_init_is_running
) {
531 return REAL(strlen
)(s
);
533 ENSURE_ASAN_INITED();
534 uptr length
= REAL(strlen
)(s
);
535 if (flags()->replace_str
) {
536 ASAN_READ_RANGE(s
, length
+ 1);
541 INTERCEPTOR(uptr
, wcslen
, const wchar_t *s
) {
542 uptr length
= REAL(wcslen
)(s
);
543 if (!asan_init_is_running
) {
544 ENSURE_ASAN_INITED();
545 ASAN_READ_RANGE(s
, (length
+ 1) * sizeof(wchar_t));
550 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
551 ENSURE_ASAN_INITED();
552 if (flags()->replace_str
) {
553 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
554 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
555 ASAN_READ_RANGE(from
, from_size
);
556 ASAN_WRITE_RANGE(to
, size
);
558 return REAL(strncpy
)(to
, from
, size
);
561 #if ASAN_INTERCEPT_STRNLEN
562 INTERCEPTOR(uptr
, strnlen
, const char *s
, uptr maxlen
) {
563 ENSURE_ASAN_INITED();
564 uptr length
= REAL(strnlen
)(s
, maxlen
);
565 if (flags()->replace_str
) {
566 ASAN_READ_RANGE(s
, Min(length
+ 1, maxlen
));
570 #endif // ASAN_INTERCEPT_STRNLEN
572 static inline bool IsValidStrtolBase(int base
) {
573 return (base
== 0) || (2 <= base
&& base
<= 36);
576 static inline void FixRealStrtolEndptr(const char *nptr
, char **endptr
) {
578 if (nptr
== *endptr
) {
579 // No digits were found at strtol call, we need to find out the last
580 // symbol accessed by strtoll on our own.
581 // We get this symbol by skipping leading blanks and optional +/- sign.
582 while (IsSpace(*nptr
)) nptr
++;
583 if (*nptr
== '+' || *nptr
== '-') nptr
++;
584 *endptr
= (char*)nptr
;
586 CHECK(*endptr
>= nptr
);
589 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
590 char **endptr
, int base
) {
591 ENSURE_ASAN_INITED();
592 if (!flags()->replace_str
) {
593 return REAL(strtol
)(nptr
, endptr
, base
);
596 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
598 *endptr
= real_endptr
;
600 if (IsValidStrtolBase(base
)) {
601 FixRealStrtolEndptr(nptr
, &real_endptr
);
602 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
607 INTERCEPTOR(int, atoi
, const char *nptr
) {
609 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
611 ENSURE_ASAN_INITED();
612 if (!flags()->replace_str
) {
613 return REAL(atoi
)(nptr
);
616 // "man atoi" tells that behavior of atoi(nptr) is the same as
617 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
618 // parsed integer can't be stored in *long* type (even if it's
619 // different from int). So, we just imitate this behavior.
620 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
621 FixRealStrtolEndptr(nptr
, &real_endptr
);
622 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
626 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
628 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
630 ENSURE_ASAN_INITED();
631 if (!flags()->replace_str
) {
632 return REAL(atol
)(nptr
);
635 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
636 FixRealStrtolEndptr(nptr
, &real_endptr
);
637 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
641 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
642 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
643 char **endptr
, int base
) {
644 ENSURE_ASAN_INITED();
645 if (!flags()->replace_str
) {
646 return REAL(strtoll
)(nptr
, endptr
, base
);
649 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
651 *endptr
= real_endptr
;
653 // If base has unsupported value, strtoll can exit with EINVAL
654 // without reading any characters. So do additional checks only
656 if (IsValidStrtolBase(base
)) {
657 FixRealStrtolEndptr(nptr
, &real_endptr
);
658 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
663 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
664 ENSURE_ASAN_INITED();
665 if (!flags()->replace_str
) {
666 return REAL(atoll
)(nptr
);
669 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
670 FixRealStrtolEndptr(nptr
, &real_endptr
);
671 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
674 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
676 static void AtCxaAtexit(void *unused
) {
678 StopInitOrderChecking();
681 #if ASAN_INTERCEPT___CXA_ATEXIT
682 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
685 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
687 ENSURE_ASAN_INITED();
688 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
689 REAL(__cxa_atexit
)(AtCxaAtexit
, 0, 0);
692 #endif // ASAN_INTERCEPT___CXA_ATEXIT
694 #if SANITIZER_WINDOWS
695 INTERCEPTOR_WINAPI(DWORD
, CreateThread
,
696 void* security
, uptr stack_size
,
697 DWORD (__stdcall
*start_routine
)(void*), void* arg
,
698 DWORD thr_flags
, void* tid
) {
699 // Strict init-order checking in thread-hostile.
700 if (flags()->strict_init_order
)
701 StopInitOrderChecking();
702 GET_STACK_TRACE_THREAD
;
703 u32 current_tid
= GetCurrentTidOrInvalid();
704 AsanThread
*t
= AsanThread::Create(start_routine
, arg
);
705 CreateThreadContextArgs args
= { t
, &stack
};
706 bool detached
= false; // FIXME: how can we determine it on Windows?
707 asanThreadRegistry().CreateThread(*(uptr
*)t
, detached
, current_tid
, &args
);
708 return REAL(CreateThread
)(security
, stack_size
,
709 asan_thread_start
, t
, thr_flags
, tid
);
713 void InitializeWindowsInterceptors() {
714 ASAN_INTERCEPT_FUNC(CreateThread
);
717 } // namespace __asan
720 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
722 void InitializeAsanInterceptors() {
723 static bool was_called_once
;
724 CHECK(was_called_once
== false);
725 was_called_once
= true;
726 InitializeCommonInterceptors();
728 // Intercept mem* functions.
729 ASAN_INTERCEPT_FUNC(memcmp
);
730 ASAN_INTERCEPT_FUNC(memmove
);
731 ASAN_INTERCEPT_FUNC(memset
);
732 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
733 ASAN_INTERCEPT_FUNC(memcpy
);
736 // Intercept str* functions.
737 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
738 ASAN_INTERCEPT_FUNC(strchr
);
739 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
740 ASAN_INTERCEPT_FUNC(strlen
);
741 ASAN_INTERCEPT_FUNC(wcslen
);
742 ASAN_INTERCEPT_FUNC(strncat
);
743 ASAN_INTERCEPT_FUNC(strncpy
);
744 #if ASAN_INTERCEPT_STRDUP
745 ASAN_INTERCEPT_FUNC(strdup
);
747 #if ASAN_INTERCEPT_STRNLEN
748 ASAN_INTERCEPT_FUNC(strnlen
);
750 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
751 ASAN_INTERCEPT_FUNC(index
);
754 ASAN_INTERCEPT_FUNC(atoi
);
755 ASAN_INTERCEPT_FUNC(atol
);
756 ASAN_INTERCEPT_FUNC(strtol
);
757 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
758 ASAN_INTERCEPT_FUNC(atoll
);
759 ASAN_INTERCEPT_FUNC(strtoll
);
762 #if ASAN_INTERCEPT_MLOCKX
763 // Intercept mlock/munlock.
764 ASAN_INTERCEPT_FUNC(mlock
);
765 ASAN_INTERCEPT_FUNC(munlock
);
766 ASAN_INTERCEPT_FUNC(mlockall
);
767 ASAN_INTERCEPT_FUNC(munlockall
);
770 // Intecept signal- and jump-related functions.
771 ASAN_INTERCEPT_FUNC(longjmp
);
772 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
773 ASAN_INTERCEPT_FUNC(sigaction
);
774 #if SANITIZER_ANDROID
775 ASAN_INTERCEPT_FUNC(bsd_signal
);
777 ASAN_INTERCEPT_FUNC(signal
);
780 #if ASAN_INTERCEPT_SWAPCONTEXT
781 ASAN_INTERCEPT_FUNC(swapcontext
);
783 #if ASAN_INTERCEPT__LONGJMP
784 ASAN_INTERCEPT_FUNC(_longjmp
);
786 #if ASAN_INTERCEPT_SIGLONGJMP
787 ASAN_INTERCEPT_FUNC(siglongjmp
);
790 // Intercept exception handling functions.
791 #if ASAN_INTERCEPT___CXA_THROW
792 INTERCEPT_FUNCTION(__cxa_throw
);
795 // Intercept threading-related functions
796 #if ASAN_INTERCEPT_PTHREAD_CREATE
797 ASAN_INTERCEPT_FUNC(pthread_create
);
800 // Intercept atexit function.
801 #if ASAN_INTERCEPT___CXA_ATEXIT
802 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
805 // Some Windows-specific interceptors.
806 #if SANITIZER_WINDOWS
807 InitializeWindowsInterceptors();
810 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
813 } // namespace __asan