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 "lsan/lsan_common.h"
23 #include "sanitizer_common/sanitizer_libc.h"
26 #include "sanitizer_common/sanitizer_posix.h"
29 #if defined(__i386) && SANITIZER_LINUX
30 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
31 #elif defined(__mips__) && SANITIZER_LINUX
32 #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
37 // Return true if we can quickly decide that the region is unpoisoned.
38 static inline bool QuickCheckForUnpoisonedRegion(uptr beg
, uptr size
) {
39 if (size
== 0) return true;
41 return !AddressIsPoisoned(beg
) &&
42 !AddressIsPoisoned(beg
+ size
- 1) &&
43 !AddressIsPoisoned(beg
+ size
/ 2);
47 struct AsanInterceptorContext
{
48 const char *interceptor_name
;
51 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
52 // and ASAN_WRITE_RANGE as macro instead of function so
53 // that no extra frames are created, and stack trace contains
54 // relevant information only.
55 // We check all shadow bytes.
56 #define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) do { \
57 uptr __offset = (uptr)(offset); \
58 uptr __size = (uptr)(size); \
60 if (__offset > __offset + __size) { \
61 GET_STACK_TRACE_FATAL_HERE; \
62 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
64 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
65 (__bad = __asan_region_is_poisoned(__offset, __size))) { \
66 AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
67 bool suppressed = false; \
69 suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
70 if (!suppressed && HaveStackTraceBasedSuppressions()) { \
71 GET_STACK_TRACE_FATAL_HERE; \
72 suppressed = IsStackTraceSuppressed(&stack); \
76 GET_CURRENT_PC_BP_SP; \
77 ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
82 #define ASAN_READ_RANGE(ctx, offset, size) \
83 ACCESS_MEMORY_RANGE(ctx, offset, size, false)
84 #define ASAN_WRITE_RANGE(ctx, offset, size) \
85 ACCESS_MEMORY_RANGE(ctx, offset, size, true)
87 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
88 ASAN_READ_RANGE((ctx), (s), \
89 common_flags()->strict_string_checks ? (len) + 1 : (n))
91 #define ASAN_READ_STRING(ctx, s, n) \
92 ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
94 // Behavior of functions like "memcpy" or "strcpy" is undefined
95 // if memory intervals overlap. We report error in this case.
96 // Macro is used to avoid creation of new frames.
97 static inline bool RangesOverlap(const char *offset1
, uptr length1
,
98 const char *offset2
, uptr length2
) {
99 return !((offset1
+ length1
<= offset2
) || (offset2
+ length2
<= offset1
));
101 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
102 const char *offset1 = (const char*)_offset1; \
103 const char *offset2 = (const char*)_offset2; \
104 if (RangesOverlap(offset1, length1, offset2, length2)) { \
105 GET_STACK_TRACE_FATAL_HERE; \
106 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
107 offset2, length2, &stack); \
111 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
112 #if SANITIZER_INTERCEPT_STRNLEN
114 return REAL(strnlen
)(s
, maxlen
);
117 return internal_strnlen(s
, maxlen
);
120 void SetThreadName(const char *name
) {
121 AsanThread
*t
= GetCurrentThread();
123 asanThreadRegistry().SetThreadName(t
->tid(), name
);
127 // FIXME: ask frontend whether we need to return failure.
131 } // namespace __asan
133 // ---------------------- Wrappers ---------------- {{{1
134 using namespace __asan
; // NOLINT
136 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc
, uptr
)
137 DECLARE_REAL_AND_INTERCEPTOR(void, free
, void *)
139 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \
140 AsanInterceptorContext _ctx = {#func}; \
141 ctx = (void *)&_ctx; \
144 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
145 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
146 ASAN_INTERCEPT_FUNC_VER(name, ver)
147 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
148 ASAN_WRITE_RANGE(ctx, ptr, size)
149 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
150 ASAN_READ_RANGE(ctx, ptr, size)
151 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
152 ASAN_INTERCEPTOR_ENTER(ctx, func); \
154 if (asan_init_is_running) \
155 return REAL(func)(__VA_ARGS__); \
156 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \
157 return REAL(func)(__VA_ARGS__); \
158 ENSURE_ASAN_INITED(); \
160 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
163 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
166 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
169 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
172 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
173 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
174 // But asan does not remember UserId's for threads (pthread_t);
175 // and remembers all ever existed threads, so the linear search by UserId
177 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
180 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
181 // Strict init-order checking is dlopen-hostile:
182 // https://github.com/google/sanitizers/issues/178
183 #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
184 if (flags()->strict_init_order) { \
185 StopInitOrderChecking(); \
187 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
188 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
189 CoverageUpdateMapping()
190 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
191 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
192 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
193 if (AsanThread *t = GetCurrentThread()) { \
194 *begin = t->tls_begin(); \
195 *end = t->tls_end(); \
199 // Asan needs custom handling of these:
200 #undef SANITIZER_INTERCEPT_MEMSET
201 #undef SANITIZER_INTERCEPT_MEMMOVE
202 #undef SANITIZER_INTERCEPT_MEMCPY
203 #include "sanitizer_common/sanitizer_common_interceptors.inc"
205 // Syscall interceptors don't have contexts, we don't support suppressions
207 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
208 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
209 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
214 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
219 #include "sanitizer_common/sanitizer_common_syscalls.inc"
221 struct ThreadStartParam
{
223 atomic_uintptr_t is_registered
;
226 #if ASAN_INTERCEPT_PTHREAD_CREATE
227 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
228 ThreadStartParam
*param
= reinterpret_cast<ThreadStartParam
*>(arg
);
229 AsanThread
*t
= nullptr;
230 while ((t
= reinterpret_cast<AsanThread
*>(
231 atomic_load(¶m
->t
, memory_order_acquire
))) == nullptr)
232 internal_sched_yield();
234 return t
->ThreadStart(GetTid(), ¶m
->is_registered
);
237 INTERCEPTOR(int, pthread_create
, void *thread
,
238 void *attr
, void *(*start_routine
)(void*), void *arg
) {
239 EnsureMainThreadIDIsCorrect();
240 // Strict init-order checking is thread-hostile.
241 if (flags()->strict_init_order
)
242 StopInitOrderChecking();
243 GET_STACK_TRACE_THREAD
;
246 REAL(pthread_attr_getdetachstate
)(attr
, &detached
);
247 ThreadStartParam param
;
248 atomic_store(¶m
.t
, 0, memory_order_relaxed
);
249 atomic_store(¶m
.is_registered
, 0, memory_order_relaxed
);
252 // Ignore all allocations made by pthread_create: thread stack/TLS may be
253 // stored by pthread for future reuse even after thread destruction, and
254 // the linked list it's stored in doesn't even hold valid pointers to the
255 // objects, the latter are calculated by obscure pointer arithmetic.
256 #if CAN_SANITIZE_LEAKS
257 __lsan::ScopedInterceptorDisabler disabler
;
259 result
= REAL(pthread_create
)(thread
, attr
, asan_thread_start
, ¶m
);
262 u32 current_tid
= GetCurrentTidOrInvalid();
264 AsanThread::Create(start_routine
, arg
, current_tid
, &stack
, detached
);
265 atomic_store(¶m
.t
, reinterpret_cast<uptr
>(t
), memory_order_release
);
266 // Wait until the AsanThread object is initialized and the ThreadRegistry
267 // entry is in "started" state. One reason for this is that after this
268 // interceptor exits, the child thread's stack may be the only thing holding
269 // the |arg| pointer. This may cause LSan to report a leak if leak checking
270 // happens at a point when the interceptor has already exited, but the stack
271 // range for the child thread is not yet known.
272 while (atomic_load(¶m
.is_registered
, memory_order_acquire
) == 0)
273 internal_sched_yield();
278 INTERCEPTOR(int, pthread_join
, void *t
, void **arg
) {
279 return real_pthread_join(t
, arg
);
282 DEFINE_REAL_PTHREAD_FUNCTIONS
283 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
285 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
287 #if SANITIZER_ANDROID
288 INTERCEPTOR(void*, bsd_signal
, int signum
, void *handler
) {
289 if (!IsHandledDeadlySignal(signum
) ||
290 common_flags()->allow_user_segv_handler
) {
291 return REAL(bsd_signal
)(signum
, handler
);
297 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
298 if (!IsHandledDeadlySignal(signum
) ||
299 common_flags()->allow_user_segv_handler
) {
300 return REAL(signal
)(signum
, handler
);
305 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
306 struct sigaction
*oldact
) {
307 if (!IsHandledDeadlySignal(signum
) ||
308 common_flags()->allow_user_segv_handler
) {
309 return REAL(sigaction
)(signum
, act
, oldact
);
314 namespace __sanitizer
{
315 int real_sigaction(int signum
, const void *act
, void *oldact
) {
316 return REAL(sigaction
)(signum
, (const struct sigaction
*)act
,
317 (struct sigaction
*)oldact
);
319 } // namespace __sanitizer
321 #elif SANITIZER_POSIX
322 // We need to have defined REAL(sigaction) on posix systems.
323 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
324 struct sigaction
*oldact
)
325 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
327 #if ASAN_INTERCEPT_SWAPCONTEXT
328 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
329 // Align to page size.
330 uptr PageSize
= GetPageSizeCached();
331 uptr bottom
= stack
& ~(PageSize
- 1);
332 ssize
+= stack
- bottom
;
333 ssize
= RoundUpTo(ssize
, PageSize
);
334 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
335 if (AddrIsInMem(bottom
) && ssize
&& ssize
<= kMaxSaneContextStackSize
) {
336 PoisonShadow(bottom
, ssize
, 0);
340 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
341 struct ucontext_t
*ucp
) {
342 static bool reported_warning
= false;
343 if (!reported_warning
) {
344 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
345 "functions and may produce false positives in some cases!\n");
346 reported_warning
= true;
348 // Clear shadow memory for new context (it may share stack
349 // with current context).
351 ReadContextStack(ucp
, &stack
, &ssize
);
352 ClearShadowMemoryForContextStack(stack
, ssize
);
353 int res
= REAL(swapcontext
)(oucp
, ucp
);
354 // swapcontext technically does not return, but program may swap context to
355 // "oucp" later, that would look as if swapcontext() returned 0.
356 // We need to clear shadow for ucp once again, as it may be in arbitrary
358 ClearShadowMemoryForContextStack(stack
, ssize
);
361 #endif // ASAN_INTERCEPT_SWAPCONTEXT
363 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
364 __asan_handle_no_return();
365 REAL(longjmp
)(env
, val
);
368 #if ASAN_INTERCEPT__LONGJMP
369 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
370 __asan_handle_no_return();
371 REAL(_longjmp
)(env
, val
);
375 #if ASAN_INTERCEPT_SIGLONGJMP
376 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
377 __asan_handle_no_return();
378 REAL(siglongjmp
)(env
, val
);
382 #if ASAN_INTERCEPT___CXA_THROW
383 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
384 CHECK(REAL(__cxa_throw
));
385 __asan_handle_no_return();
386 REAL(__cxa_throw
)(a
, b
, c
);
390 // memcpy is called during __asan_init() from the internals of printf(...).
391 // We do not treat memcpy with to==from as a bug.
392 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
393 #define ASAN_MEMCPY_IMPL(ctx, to, from, size) do { \
394 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); \
395 if (asan_init_is_running) { \
396 return REAL(memcpy)(to, from, size); \
398 ENSURE_ASAN_INITED(); \
399 if (flags()->replace_intrin) { \
401 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
403 ASAN_READ_RANGE(ctx, from, size); \
404 ASAN_WRITE_RANGE(ctx, to, size); \
406 return REAL(memcpy)(to, from, size); \
410 void *__asan_memcpy(void *to
, const void *from
, uptr size
) {
411 ASAN_MEMCPY_IMPL(nullptr, to
, from
, size
);
414 // memset is called inside Printf.
415 #define ASAN_MEMSET_IMPL(ctx, block, c, size) do { \
416 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); \
417 if (asan_init_is_running) { \
418 return REAL(memset)(block, c, size); \
420 ENSURE_ASAN_INITED(); \
421 if (flags()->replace_intrin) { \
422 ASAN_WRITE_RANGE(ctx, block, size); \
424 return REAL(memset)(block, c, size); \
427 void *__asan_memset(void *block
, int c
, uptr size
) {
428 ASAN_MEMSET_IMPL(nullptr, block
, c
, size
);
431 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) do { \
432 if (UNLIKELY(!asan_inited)) \
433 return internal_memmove(to, from, size); \
434 ENSURE_ASAN_INITED(); \
435 if (flags()->replace_intrin) { \
436 ASAN_READ_RANGE(ctx, from, size); \
437 ASAN_WRITE_RANGE(ctx, to, size); \
439 return internal_memmove(to, from, size); \
442 void *__asan_memmove(void *to
, const void *from
, uptr size
) {
443 ASAN_MEMMOVE_IMPL(nullptr, to
, from
, size
);
446 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
448 ASAN_INTERCEPTOR_ENTER(ctx
, memmove
);
449 ASAN_MEMMOVE_IMPL(ctx
, to
, from
, size
);
452 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
454 ASAN_INTERCEPTOR_ENTER(ctx
, memcpy
);
456 ASAN_MEMCPY_IMPL(ctx
, to
, from
, size
);
458 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
459 // with WRAP(memcpy). As a result, false positives are reported for memmove()
460 // calls. If we just disable error reporting with
461 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
462 // internal_memcpy(), which may lead to crashes, see
463 // http://llvm.org/bugs/show_bug.cgi?id=16362.
464 ASAN_MEMMOVE_IMPL(ctx
, to
, from
, size
);
465 #endif // !SANITIZER_MAC
468 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
470 ASAN_INTERCEPTOR_ENTER(ctx
, memset
);
471 ASAN_MEMSET_IMPL(ctx
, block
, c
, size
);
474 #if ASAN_INTERCEPT_INDEX
475 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
476 INTERCEPTOR(char*, index
, const char *string
, int c
)
477 ALIAS(WRAPPER_NAME(strchr
));
480 DECLARE_REAL(char*, index
, const char *string
, int c
)
481 OVERRIDE_FUNCTION(index
, strchr
);
483 DEFINE_REAL(char*, index
, const char *string
, int c
)
486 #endif // ASAN_INTERCEPT_INDEX
488 // For both strcat() and strncat() we need to check the validity of |to|
489 // argument irrespective of the |from| length.
490 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
492 ASAN_INTERCEPTOR_ENTER(ctx
, strcat
); // NOLINT
493 ENSURE_ASAN_INITED();
494 if (flags()->replace_str
) {
495 uptr from_length
= REAL(strlen
)(from
);
496 ASAN_READ_RANGE(ctx
, from
, from_length
+ 1);
497 uptr to_length
= REAL(strlen
)(to
);
498 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
499 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
500 // If the copying actually happens, the |from| string should not overlap
501 // with the resulting string starting at |to|, which has a length of
502 // to_length + from_length + 1.
503 if (from_length
> 0) {
504 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
505 from
, from_length
+ 1);
508 return REAL(strcat
)(to
, from
); // NOLINT
511 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
513 ASAN_INTERCEPTOR_ENTER(ctx
, strncat
);
514 ENSURE_ASAN_INITED();
515 if (flags()->replace_str
) {
516 uptr from_length
= MaybeRealStrnlen(from
, size
);
517 uptr copy_length
= Min(size
, from_length
+ 1);
518 ASAN_READ_RANGE(ctx
, from
, copy_length
);
519 uptr to_length
= REAL(strlen
)(to
);
520 ASAN_READ_STRING_OF_LEN(ctx
, to
, to_length
, to_length
);
521 ASAN_WRITE_RANGE(ctx
, to
+ to_length
, from_length
+ 1);
522 if (from_length
> 0) {
523 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
527 return REAL(strncat
)(to
, from
, size
);
530 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
532 ASAN_INTERCEPTOR_ENTER(ctx
, strcpy
); // NOLINT
534 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
536 // strcpy is called from malloc_default_purgeable_zone()
537 // in __asan::ReplaceSystemAlloc() on Mac.
538 if (asan_init_is_running
) {
539 return REAL(strcpy
)(to
, from
); // NOLINT
541 ENSURE_ASAN_INITED();
542 if (flags()->replace_str
) {
543 uptr from_size
= REAL(strlen
)(from
) + 1;
544 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
545 ASAN_READ_RANGE(ctx
, from
, from_size
);
546 ASAN_WRITE_RANGE(ctx
, to
, from_size
);
548 return REAL(strcpy
)(to
, from
); // NOLINT
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
);
566 #if ASAN_INTERCEPT___STRDUP
567 INTERCEPTOR(char*, __strdup
, const char *s
) {
569 ASAN_INTERCEPTOR_ENTER(ctx
, strdup
);
570 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
571 ENSURE_ASAN_INITED();
572 uptr length
= REAL(strlen
)(s
);
573 if (flags()->replace_str
) {
574 ASAN_READ_RANGE(ctx
, s
, length
+ 1);
576 GET_STACK_TRACE_MALLOC
;
577 void *new_mem
= asan_malloc(length
+ 1, &stack
);
578 REAL(memcpy
)(new_mem
, s
, length
+ 1);
579 return reinterpret_cast<char*>(new_mem
);
581 #endif // ASAN_INTERCEPT___STRDUP
583 INTERCEPTOR(SIZE_T
, wcslen
, const wchar_t *s
) {
585 ASAN_INTERCEPTOR_ENTER(ctx
, wcslen
);
586 SIZE_T length
= internal_wcslen(s
);
587 if (!asan_init_is_running
) {
588 ENSURE_ASAN_INITED();
589 ASAN_READ_RANGE(ctx
, s
, (length
+ 1) * sizeof(wchar_t));
594 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
596 ASAN_INTERCEPTOR_ENTER(ctx
, strncpy
);
597 ENSURE_ASAN_INITED();
598 if (flags()->replace_str
) {
599 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
600 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
601 ASAN_READ_RANGE(ctx
, from
, from_size
);
602 ASAN_WRITE_RANGE(ctx
, to
, size
);
604 return REAL(strncpy
)(to
, from
, size
);
607 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
608 char **endptr
, int base
) {
610 ASAN_INTERCEPTOR_ENTER(ctx
, strtol
);
611 ENSURE_ASAN_INITED();
612 if (!flags()->replace_str
) {
613 return REAL(strtol
)(nptr
, endptr
, base
);
616 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
617 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
621 INTERCEPTOR(int, atoi
, const char *nptr
) {
623 ASAN_INTERCEPTOR_ENTER(ctx
, atoi
);
625 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
627 ENSURE_ASAN_INITED();
628 if (!flags()->replace_str
) {
629 return REAL(atoi
)(nptr
);
632 // "man atoi" tells that behavior of atoi(nptr) is the same as
633 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
634 // parsed integer can't be stored in *long* type (even if it's
635 // different from int). So, we just imitate this behavior.
636 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
637 FixRealStrtolEndptr(nptr
, &real_endptr
);
638 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
642 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
644 ASAN_INTERCEPTOR_ENTER(ctx
, atol
);
646 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
648 ENSURE_ASAN_INITED();
649 if (!flags()->replace_str
) {
650 return REAL(atol
)(nptr
);
653 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
654 FixRealStrtolEndptr(nptr
, &real_endptr
);
655 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
659 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
660 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
661 char **endptr
, int base
) {
663 ASAN_INTERCEPTOR_ENTER(ctx
, strtoll
);
664 ENSURE_ASAN_INITED();
665 if (!flags()->replace_str
) {
666 return REAL(strtoll
)(nptr
, endptr
, base
);
669 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
670 StrtolFixAndCheck(ctx
, nptr
, endptr
, real_endptr
, base
);
674 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
676 ASAN_INTERCEPTOR_ENTER(ctx
, atoll
);
677 ENSURE_ASAN_INITED();
678 if (!flags()->replace_str
) {
679 return REAL(atoll
)(nptr
);
682 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
683 FixRealStrtolEndptr(nptr
, &real_endptr
);
684 ASAN_READ_STRING(ctx
, nptr
, (real_endptr
- nptr
) + 1);
687 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
689 #if ASAN_INTERCEPT___CXA_ATEXIT
690 static void AtCxaAtexit(void *unused
) {
692 StopInitOrderChecking();
695 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
698 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
700 ENSURE_ASAN_INITED();
701 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
702 REAL(__cxa_atexit
)(AtCxaAtexit
, nullptr, nullptr);
705 #endif // ASAN_INTERCEPT___CXA_ATEXIT
707 #if ASAN_INTERCEPT_FORK
708 INTERCEPTOR(int, fork
, void) {
709 ENSURE_ASAN_INITED();
710 if (common_flags()->coverage
) CovBeforeFork();
711 int pid
= REAL(fork
)();
712 if (common_flags()->coverage
) CovAfterFork(pid
);
715 #endif // ASAN_INTERCEPT_FORK
717 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
719 void InitializeAsanInterceptors() {
720 static bool was_called_once
;
721 CHECK(!was_called_once
);
722 was_called_once
= true;
723 InitializeCommonInterceptors();
725 // Intercept mem* functions.
726 ASAN_INTERCEPT_FUNC(memmove
);
727 ASAN_INTERCEPT_FUNC(memset
);
728 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
729 // In asan, REAL(memmove) is not used, but it is used in msan.
730 ASAN_INTERCEPT_FUNC(memcpy
);
732 ASSIGN_REAL(memcpy
, memmove
);
736 // Intercept str* functions.
737 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
738 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
739 ASAN_INTERCEPT_FUNC(wcslen
);
740 ASAN_INTERCEPT_FUNC(strncat
);
741 ASAN_INTERCEPT_FUNC(strncpy
);
742 ASAN_INTERCEPT_FUNC(strdup
);
743 #if ASAN_INTERCEPT___STRDUP
744 ASAN_INTERCEPT_FUNC(__strdup
);
746 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
747 ASAN_INTERCEPT_FUNC(index
);
750 ASAN_INTERCEPT_FUNC(atoi
);
751 ASAN_INTERCEPT_FUNC(atol
);
752 ASAN_INTERCEPT_FUNC(strtol
);
753 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
754 ASAN_INTERCEPT_FUNC(atoll
);
755 ASAN_INTERCEPT_FUNC(strtoll
);
758 // Intecept signal- and jump-related functions.
759 ASAN_INTERCEPT_FUNC(longjmp
);
760 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
761 ASAN_INTERCEPT_FUNC(sigaction
);
762 #if SANITIZER_ANDROID
763 ASAN_INTERCEPT_FUNC(bsd_signal
);
765 ASAN_INTERCEPT_FUNC(signal
);
767 #if ASAN_INTERCEPT_SWAPCONTEXT
768 ASAN_INTERCEPT_FUNC(swapcontext
);
770 #if ASAN_INTERCEPT__LONGJMP
771 ASAN_INTERCEPT_FUNC(_longjmp
);
773 #if ASAN_INTERCEPT_SIGLONGJMP
774 ASAN_INTERCEPT_FUNC(siglongjmp
);
777 // Intercept exception handling functions.
778 #if ASAN_INTERCEPT___CXA_THROW
779 ASAN_INTERCEPT_FUNC(__cxa_throw
);
782 // Intercept threading-related functions
783 #if ASAN_INTERCEPT_PTHREAD_CREATE
784 #if defined(ASAN_PTHREAD_CREATE_VERSION)
785 ASAN_INTERCEPT_FUNC_VER(pthread_create
, ASAN_PTHREAD_CREATE_VERSION
);
787 ASAN_INTERCEPT_FUNC(pthread_create
);
789 ASAN_INTERCEPT_FUNC(pthread_join
);
792 // Intercept atexit function.
793 #if ASAN_INTERCEPT___CXA_ATEXIT
794 ASAN_INTERCEPT_FUNC(__cxa_atexit
);
797 #if ASAN_INTERCEPT_FORK
798 ASAN_INTERCEPT_FUNC(fork
);
801 InitializePlatformInterceptors();
803 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
806 } // namespace __asan