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 //===----------------------------------------------------------------------===//
13 #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 "asan_suppressions.h"
22 #include "sanitizer_common/sanitizer_libc.h"
25 #include "sanitizer_common/sanitizer_posix.h"
28 #if defined(__i386) && SANITIZER_LINUX
29 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
30 #elif defined(__mips__) && SANITIZER_LINUX
31 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
36 // Return true if we can quickly decide that the region is unpoisoned.
37 static inline bool QuickCheckForUnpoisonedRegion(uptr beg
, uptr size
) {
38 if (size
== 0) return true;
40 return !AddressIsPoisoned(beg
) &&
41 !AddressIsPoisoned(beg
+ size
- 1) &&
42 !AddressIsPoisoned(beg
+ size
/ 2);
46 struct AsanInterceptorContext
{
47 const char *interceptor_name
;
50 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
51 // and ASAN_WRITE_RANGE as macro instead of function so
52 // that no extra frames are created, and stack trace contains
53 // relevant information only.
54 // We check all shadow bytes.
55 #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
56 uptr __offset = (uptr)(offset); \
57 uptr __size = (uptr)(size); \
59 if (__offset > __offset + __size) { \
60 GET_STACK_TRACE_FATAL_HERE; \
61 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
63 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
64 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
65 AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
66 bool suppressed = false; \
68 suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
69 if (!suppressed && HaveStackTraceBasedSuppressions()) { \
70 GET_STACK_TRACE_FATAL_HERE; \
71 suppressed = IsStackTraceSuppressed(&stack); \
75 GET_CURRENT_PC_BP_SP; \
76 ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
81 #define ASAN_READ_RANGE(ctx, offset, size) \
82 ACCESS_MEMORY_RANGE(ctx, offset, size, false)
83 #define ASAN_WRITE_RANGE(ctx, offset, size) \
84 ACCESS_MEMORY_RANGE(ctx, offset, size, true)
86 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
87 ASAN_READ_RANGE((ctx), (s), \
88 common_flags()->strict_string_checks ? (len) + 1 : (n))
90 #define ASAN_READ_STRING(ctx, s, n) \
91 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
93 // Behavior of functions like "memcpy" or "strcpy" is undefined
94 // if memory intervals overlap. We report error in this case.
95 // Macro is used to avoid creation of new frames.
96 static inline bool RangesOverlap(const char *offset1
, uptr length1
,
97 const char *offset2
, uptr length2
) {
98 return !((offset1
+ length1
<= offset2
) || (offset2
+ length2
<= offset1
));
100 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
101 const char *offset1 = (const char*)_offset1; \
102 const char *offset2 = (const char*)_offset2; \
103 if (RangesOverlap(offset1, length1, offset2, length2)) { \
104 GET_STACK_TRACE_FATAL_HERE; \
105 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
106 offset2, length2, &stack); \
110 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
111 #if ASAN_INTERCEPT_STRNLEN
113 return REAL(strnlen
)(s
, maxlen
);
116 return internal_strnlen(s
, maxlen
);
119 void SetThreadName(const char *name
) {
120 AsanThread
*t
= GetCurrentThread();
122 asanThreadRegistry().SetThreadName(t
->tid(), name
);
126 // FIXME: ask frontend whether we need to return failure.
130 } // namespace __asan
132 // ---------------------- Wrappers ---------------- {{{1
133 using namespace __asan
; // NOLINT
135 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc
, uptr
)
136 DECLARE_REAL_AND_INTERCEPTOR(void, free
, void *)
138 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \
139 AsanInterceptorContext _ctx = {#func}; \
140 ctx = (void *)&_ctx; \
143 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
144 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
145 ASAN_WRITE_RANGE(ctx, ptr, size)
146 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
147 ASAN_READ_RANGE(ctx, ptr, size)
148 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
149 ASAN_INTERCEPTOR_ENTER(ctx, func); \
151 if (asan_init_is_running) \
152 return REAL(func)(__VA_ARGS__); \
153 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
154 return REAL(func)(__VA_ARGS__); \
155 ENSURE_ASAN_INITED(); \
157 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
160 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
163 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
166 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
169 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
170 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
171 // But asan does not remember UserId's for threads (pthread_t);
172 // and remembers all ever existed threads, so the linear search by UserId
174 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
177 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
178 // Strict init-order checking is dlopen-hostile:
179 // https://code.google.com/p/address-sanitizer/issues/detail?id=178
180 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
181 if (flags()->strict_init_order) { \
182 StopInitOrderChecking(); \
184 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
185 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
186 CoverageUpdateMapping()
187 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
188 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
189 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
190 if (AsanThread *t = GetCurrentThread()) { \
191 *begin = t->tls_begin(); \
192 *end = t->tls_end(); \
196 #include "sanitizer_common/sanitizer_common_interceptors.inc"
198 // Syscall interceptors don't have contexts, we don't support suppressions
200 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
201 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
202 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
207 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
212 #include "sanitizer_common/sanitizer_common_syscalls.inc"
214 struct ThreadStartParam
{
216 atomic_uintptr_t is_registered
;
219 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
220 ThreadStartParam
*param
= reinterpret_cast<ThreadStartParam
*>(arg
);
221 AsanThread
*t
= nullptr;
222 while ((t
= reinterpret_cast<AsanThread
*>(
223 atomic_load(¶m
->t
, memory_order_acquire
))) == nullptr)
224 internal_sched_yield();
226 return t
->ThreadStart(GetTid(), ¶m
->is_registered
);
229 #if ASAN_INTERCEPT_PTHREAD_CREATE
230 INTERCEPTOR(int, pthread_create
, void *thread
,
231 void *attr
, void *(*start_routine
)(void*), void *arg
) {
232 EnsureMainThreadIDIsCorrect();
233 // Strict init-order checking is thread-hostile.
234 if (flags()->strict_init_order
)
235 StopInitOrderChecking();
236 GET_STACK_TRACE_THREAD
;
239 REAL(pthread_attr_getdetachstate
)(attr
, &detached
);
240 ThreadStartParam param
;
241 atomic_store(¶m
.t
, 0, memory_order_relaxed
);
242 atomic_store(¶m
.is_registered
, 0, memory_order_relaxed
);
243 int result
= REAL(pthread_create
)(thread
, attr
, asan_thread_start
, ¶m
);
245 u32 current_tid
= GetCurrentTidOrInvalid();
247 AsanThread::Create(start_routine
, arg
, current_tid
, &stack
, detached
);
248 atomic_store(¶m
.t
, reinterpret_cast<uptr
>(t
), memory_order_release
);
249 // Wait until the AsanThread object is initialized and the ThreadRegistry
250 // entry is in "started" state. One reason for this is that after this
251 // interceptor exits, the child thread's stack may be the only thing holding
252 // the |arg| pointer. This may cause LSan to report a leak if leak checking
253 // happens at a point when the interceptor has already exited, but the stack
254 // range for the child thread is not yet known.
255 while (atomic_load(¶m
.is_registered
, memory_order_acquire
) == 0)
256 internal_sched_yield();
261 INTERCEPTOR(int, pthread_join
, void *t
, void **arg
) {
262 return real_pthread_join(t
, arg
);
265 DEFINE_REAL_PTHREAD_FUNCTIONS
266 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
268 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
270 #if SANITIZER_ANDROID
271 INTERCEPTOR(void*, bsd_signal
, int signum
, void *handler
) {
272 if (!IsDeadlySignal(signum
) || common_flags()->allow_user_segv_handler
) {
273 return REAL(bsd_signal
)(signum
, handler
);
279 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
280 if (!IsDeadlySignal(signum
) || common_flags()->allow_user_segv_handler
) {
281 return REAL(signal
)(signum
, handler
);
286 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
287 struct sigaction
*oldact
) {
288 if (!IsDeadlySignal(signum
) || common_flags()->allow_user_segv_handler
) {
289 return REAL(sigaction
)(signum
, act
, oldact
);
294 namespace __sanitizer
{
295 int real_sigaction(int signum
, const void *act
, void *oldact
) {
296 return REAL(sigaction
)(signum
, (const struct sigaction
*)act
,
297 (struct sigaction
*)oldact
);
299 } // namespace __sanitizer
301 #elif SANITIZER_POSIX
302 // We need to have defined REAL(sigaction) on posix systems.
303 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
304 struct sigaction
*oldact
)
305 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
307 #if ASAN_INTERCEPT_SWAPCONTEXT
308 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
309 // Align to page size.
310 uptr PageSize
= GetPageSizeCached();
311 uptr bottom
= stack
& ~(PageSize
- 1);
312 ssize
+= stack
- bottom
;
313 ssize
= RoundUpTo(ssize
, PageSize
);
314 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
315 if (AddrIsInMem(bottom
) && ssize
&& ssize
<= kMaxSaneContextStackSize
) {
316 PoisonShadow(bottom
, ssize
, 0);
320 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
321 struct ucontext_t
*ucp
) {
322 static bool reported_warning
= false;
323 if (!reported_warning
) {
324 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
325 "functions and may produce false positives in some cases!\n");
326 reported_warning
= true;
328 // Clear shadow memory for new context (it may share stack
329 // with current context).
331 ReadContextStack(ucp
, &stack
, &ssize
);
332 ClearShadowMemoryForContextStack(stack
, ssize
);
333 int res
= REAL(swapcontext
)(oucp
, ucp
);
334 // swapcontext technically does not return, but program may swap context to
335 // "oucp" later, that would look as if swapcontext() returned 0.
336 // We need to clear shadow for ucp once again, as it may be in arbitrary
338 ClearShadowMemoryForContextStack(stack
, ssize
);
341 #endif // ASAN_INTERCEPT_SWAPCONTEXT
343 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
344 __asan_handle_no_return();
345 REAL(longjmp
)(env
, val
);
348 #if ASAN_INTERCEPT__LONGJMP
349 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
350 __asan_handle_no_return();
351 REAL(_longjmp
)(env
, val
);
355 #if ASAN_INTERCEPT_SIGLONGJMP
356 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
357 __asan_handle_no_return();
358 REAL(siglongjmp
)(env
, val
);
362 #if ASAN_INTERCEPT___CXA_THROW
363 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
364 CHECK(REAL(__cxa_throw
));
365 __asan_handle_no_return();
366 REAL(__cxa_throw
)(a
, b
, c
);
370 // memcpy is called during __asan_init() from the internals of printf(...).
371 // We do not treat memcpy with to==from as a bug.
372 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
373 #define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \
374 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
375 if (asan_init_is_running) { \
376 return REAL(memcpy)(to, from, size); \
378 ENSURE_ASAN_INITED(); \
379 if (flags()->replace_intrin) { \
381 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
383 ASAN_READ_RANGE(ctx, from, size); \
384 ASAN_WRITE_RANGE(ctx, to, size); \
386 return REAL(memcpy)(to, from, size); \
390 void *__asan_memcpy(void *to
, const void *from
, uptr size
) {
391 ASAN_MEMCPY_IMPL(nullptr, to
, from
, size
);
394 // memset is called inside Printf.
395 #define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \
396 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
397 if (asan_init_is_running) { \
398 return REAL(memset)(block, c, size); \
400 ENSURE_ASAN_INITED(); \
401 if (flags()->replace_intrin) { \
402 ASAN_WRITE_RANGE(ctx, block, size); \
404 return REAL(memset)(block, c, size); \
407 void *__asan_memset(void *block
, int c
, uptr size
) {
408 ASAN_MEMSET_IMPL(nullptr, block
, c
, size
);
411 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \
412 if (UNLIKELY(!asan_inited)) \
413 return internal_memmove(to, from, size); \
414 ENSURE_ASAN_INITED(); \
415 if (flags()->replace_intrin) { \
416 ASAN_READ_RANGE(ctx, from, size); \
417 ASAN_WRITE_RANGE(ctx, to, size); \
419 return internal_memmove(to, from, size); \
422 void *__asan_memmove(void *to
, const void *from
, uptr size
) {
423 ASAN_MEMMOVE_IMPL(nullptr, to
, from
, size
);
426 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
428 ASAN_INTERCEPTOR_ENTER(ctx
, memmove
);
429 ASAN_MEMMOVE_IMPL(ctx
, to
, from
, size
);
432 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
434 ASAN_INTERCEPTOR_ENTER(ctx
, memcpy
);
436 ASAN_MEMCPY_IMPL(ctx
, to
, from
, size
);
438 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
439 // with WRAP(memcpy). As a result, false positives are reported for memmove()
440 // calls. If we just disable error reporting with
441 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
442 // internal_memcpy(), which may lead to crashes, see
443 // http://llvm.org/bugs/show_bug.cgi?id=16362.
444 ASAN_MEMMOVE_IMPL(ctx
, to
, from
, size
);
445 #endif // !SANITIZER_MAC
448 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
450 ASAN_INTERCEPTOR_ENTER(ctx
, memset
);
451 ASAN_MEMSET_IMPL(ctx
, block
, c
, size
);
454 INTERCEPTOR(char*, strchr
, const char *str
, int c
) {
456 ASAN_INTERCEPTOR_ENTER(ctx
, strchr
);
457 if (UNLIKELY(!asan_inited
)) return internal_strchr(str
, c
);
458 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
460 if (asan_init_is_running
) {
461 return REAL(strchr
)(str
, c
);
463 ENSURE_ASAN_INITED();
464 char *result
= REAL(strchr
)(str
, c
);
465 if (flags()->replace_str
) {
466 uptr len
= REAL(strlen
)(str
);
467 uptr bytes_read
= (result
? result
- str
: len
) + 1;
468 ASAN_READ_STRING_OF_LEN(ctx
, str
, len
, bytes_read
);
473 #if ASAN_INTERCEPT_INDEX
474 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
475 INTERCEPTOR(char*, index
, const char *string
, int c
)
476 ALIAS(WRAPPER_NAME(strchr
));
479 DECLARE_REAL(char*, index
, const char *string
, int c
)
480 OVERRIDE_FUNCTION(index
, strchr
);
482 DEFINE_REAL(char*, index
, const char *string
, int c
)
485 #endif // ASAN_INTERCEPT_INDEX
487 // For both strcat() and strncat() we need to check the validity of |to|
488 // argument irrespective of the |from| length.
489 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
491 ASAN_INTERCEPTOR_ENTER(ctx
, strcat
); // NOLINT
492 ENSURE_ASAN_INITED();
493 if (flags()->replace_str
) {
494 uptr from_length
= REAL(strlen
)(from
);
495 ASAN_READ_RANGE(ctx
, from
, from_length
+ 1);
496 uptr to_length
= REAL(strlen
)(to
);
497 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
498 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
499 // If the copying actually happens, the |from| string should not overlap
500 // with the resulting string starting at |to|, which has a length of
501 // to_length + from_length + 1.
502 if (from_length
> 0) {
503 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
504 from
, from_length
+ 1);
507 return REAL(strcat
)(to
, from
); // NOLINT
510 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
512 ASAN_INTERCEPTOR_ENTER(ctx
, strncat
);
513 ENSURE_ASAN_INITED();
514 if (flags()->replace_str
) {
515 uptr from_length
= MaybeRealStrnlen(from
, size
);
516 uptr copy_length
= Min(size
, from_length
+ 1);
517 ASAN_READ_RANGE(ctx
, from
, copy_length
);
518 uptr to_length
= REAL(strlen
)(to
);
519 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
520 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
521 if (from_length
> 0) {
522 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
526 return REAL(strncat
)(to
, from
, size
);
529 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
531 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
); // NOLINT
533 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
535 // strcpy is called from malloc_default_purgeable_zone()
536 // in __asan::ReplaceSystemAlloc() on Mac.
537 if (asan_init_is_running
) {
538 return REAL(strcpy
)(to
, from
); // NOLINT
540 ENSURE_ASAN_INITED();
541 if (flags()->replace_str
) {
542 uptr from_size
= REAL(strlen
)(from
) + 1;
543 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
544 ASAN_READ_RANGE(ctx
, from
, from_size
);
545 ASAN_WRITE_RANGE(ctx
, to
, from_size
);
547 return REAL(strcpy
)(to
, from
); // NOLINT
550 #if ASAN_INTERCEPT_STRDUP
551 INTERCEPTOR(char*, strdup
, const char *s
) {
553 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
554 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
555 ENSURE_ASAN_INITED();
556 uptr length
= REAL(strlen
)(s
);
557 if (flags()->replace_str
) {
558 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
560 GET_STACK_TRACE_MALLOC
;
561 void *new_mem
= asan_malloc(length
+ 1, &stack
);
562 REAL(memcpy
)(new_mem
, s
, length
+ 1);
563 return reinterpret_cast<char*>(new_mem
);
567 INTERCEPTOR(SIZE_T
, strlen
, const char *s
) {
569 ASAN_INTERCEPTOR_ENTER(ctx
, strlen
);
570 if (UNLIKELY(!asan_inited
)) return internal_strlen(s
);
571 // strlen is called from malloc_default_purgeable_zone()
572 // in __asan::ReplaceSystemAlloc() on Mac.
573 if (asan_init_is_running
) {
574 return REAL(strlen
)(s
);
576 ENSURE_ASAN_INITED();
577 SIZE_T length
= REAL(strlen
)(s
);
578 if (flags()->replace_str
) {
579 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
584 INTERCEPTOR(SIZE_T
, wcslen
, const wchar_t *s
) {
586 ASAN_INTERCEPTOR_ENTER(ctx
, wcslen
);
587 SIZE_T length
= REAL(wcslen
)(s
);
588 if (!asan_init_is_running
) {
589 ENSURE_ASAN_INITED();
590 ASAN_READ_RANGE(ctx
, s
, (length
+ 1) * sizeof(wchar_t));
595 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
597 ASAN_INTERCEPTOR_ENTER(ctx
, strncpy
);
598 ENSURE_ASAN_INITED();
599 if (flags()->replace_str
) {
600 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
601 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
602 ASAN_READ_RANGE(ctx
, from
, from_size
);
603 ASAN_WRITE_RANGE(ctx
, to
, size
);
605 return REAL(strncpy
)(to
, from
, size
);
608 #if ASAN_INTERCEPT_STRNLEN
609 INTERCEPTOR(uptr
, strnlen
, const char *s
, uptr maxlen
) {
611 ASAN_INTERCEPTOR_ENTER(ctx
, strnlen
);
612 ENSURE_ASAN_INITED();
613 uptr length
= REAL(strnlen
)(s
, maxlen
);
614 if (flags()->replace_str
) {
615 ASAN_READ_RANGE(ctx
, s
, Min(length
+ 1, maxlen
));
619 #endif // ASAN_INTERCEPT_STRNLEN
621 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
622 char **endptr
, int base
) {
624 ASAN_INTERCEPTOR_ENTER(ctx
, strtol
);
625 ENSURE_ASAN_INITED();
626 if (!flags()->replace_str
) {
627 return REAL(strtol
)(nptr
, endptr
, base
);
630 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
631 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
635 INTERCEPTOR(int, atoi
, const char *nptr
) {
637 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
639 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
641 ENSURE_ASAN_INITED();
642 if (!flags()->replace_str
) {
643 return REAL(atoi
)(nptr
);
646 // "man atoi" tells that behavior of atoi(nptr) is the same as
647 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
648 // parsed integer can't be stored in *long* type (even if it's
649 // different from int). So, we just imitate this behavior.
650 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
651 FixRealStrtolEndptr(nptr
, &real_endptr
);
652 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
656 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
658 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
660 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
662 ENSURE_ASAN_INITED();
663 if (!flags()->replace_str
) {
664 return REAL(atol
)(nptr
);
667 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
668 FixRealStrtolEndptr(nptr
, &real_endptr
);
669 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
673 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
674 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
675 char **endptr
, int base
) {
677 ASAN_INTERCEPTOR_ENTER(ctx
, strtoll
);
678 ENSURE_ASAN_INITED();
679 if (!flags()->replace_str
) {
680 return REAL(strtoll
)(nptr
, endptr
, base
);
683 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
684 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
688 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
690 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
691 ENSURE_ASAN_INITED();
692 if (!flags()->replace_str
) {
693 return REAL(atoll
)(nptr
);
696 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
697 FixRealStrtolEndptr(nptr
, &real_endptr
);
698 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
701 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
703 static void AtCxaAtexit(void *unused
) {
705 StopInitOrderChecking();
708 #if ASAN_INTERCEPT___CXA_ATEXIT
709 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
712 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
714 ENSURE_ASAN_INITED();
715 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
716 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
719 #endif // ASAN_INTERCEPT___CXA_ATEXIT
721 #if ASAN_INTERCEPT_FORK
722 INTERCEPTOR(int, fork
, void) {
723 ENSURE_ASAN_INITED();
724 if (common_flags()->coverage
) CovBeforeFork();
725 int pid
= REAL(fork
)();
726 if (common_flags()->coverage
) CovAfterFork(pid
);
729 #endif // ASAN_INTERCEPT_FORK
731 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
733 void InitializeAsanInterceptors() {
734 static bool was_called_once
;
735 CHECK(was_called_once
== false);
736 was_called_once
= true;
737 InitializeCommonInterceptors();
739 // Intercept mem* functions.
740 ASAN_INTERCEPT_FUNC(memmove
);
741 ASAN_INTERCEPT_FUNC(memset
);
742 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
743 ASAN_INTERCEPT_FUNC(memcpy
);
746 // Intercept str* functions.
747 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
748 ASAN_INTERCEPT_FUNC(strchr
);
749 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
750 ASAN_INTERCEPT_FUNC(strlen
);
751 ASAN_INTERCEPT_FUNC(wcslen
);
752 ASAN_INTERCEPT_FUNC(strncat
);
753 ASAN_INTERCEPT_FUNC(strncpy
);
754 #if ASAN_INTERCEPT_STRDUP
755 ASAN_INTERCEPT_FUNC(strdup
);
757 #if ASAN_INTERCEPT_STRNLEN
758 ASAN_INTERCEPT_FUNC(strnlen
);
760 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
761 ASAN_INTERCEPT_FUNC(index
);
764 ASAN_INTERCEPT_FUNC(atoi
);
765 ASAN_INTERCEPT_FUNC(atol
);
766 ASAN_INTERCEPT_FUNC(strtol
);
767 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
768 ASAN_INTERCEPT_FUNC(atoll
);
769 ASAN_INTERCEPT_FUNC(strtoll
);
772 // Intecept signal- and jump-related functions.
773 ASAN_INTERCEPT_FUNC(longjmp
);
774 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
775 ASAN_INTERCEPT_FUNC(sigaction
);
776 #if SANITIZER_ANDROID
777 ASAN_INTERCEPT_FUNC(bsd_signal
);
779 ASAN_INTERCEPT_FUNC(signal
);
781 #if ASAN_INTERCEPT_SWAPCONTEXT
782 ASAN_INTERCEPT_FUNC(swapcontext
);
784 #if ASAN_INTERCEPT__LONGJMP
785 ASAN_INTERCEPT_FUNC(_longjmp
);
787 #if ASAN_INTERCEPT_SIGLONGJMP
788 ASAN_INTERCEPT_FUNC(siglongjmp
);
791 // Intercept exception handling functions.
792 #if ASAN_INTERCEPT___CXA_THROW
793 ASAN_INTERCEPT_FUNC(__cxa_throw
);
796 // Intercept threading-related functions
797 #if ASAN_INTERCEPT_PTHREAD_CREATE
798 #if defined(ASAN_PTHREAD_CREATE_VERSION)
799 ASAN_INTERCEPT_FUNC_VER(pthread_create
, ASAN_PTHREAD_CREATE_VERSION
);
801 ASAN_INTERCEPT_FUNC(pthread_create
);
803 ASAN_INTERCEPT_FUNC(pthread_join
);
806 // Intercept atexit function.
807 #if ASAN_INTERCEPT___CXA_ATEXIT
808 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
811 #if ASAN_INTERCEPT_FORK
812 ASAN_INTERCEPT_FUNC(fork
);
815 InitializePlatformInterceptors();
817 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
820 } // namespace __asan