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 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping()
148 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping()
149 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
150 #include "sanitizer_common/sanitizer_common_interceptors.inc"
152 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
153 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
154 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
159 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
164 #include "sanitizer_common/sanitizer_common_syscalls.inc"
166 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
167 AsanThread
*t
= (AsanThread
*)arg
;
169 return t
->ThreadStart(GetTid());
172 #if ASAN_INTERCEPT_PTHREAD_CREATE
173 INTERCEPTOR(int, pthread_create
, void *thread
,
174 void *attr
, void *(*start_routine
)(void*), void *arg
) {
175 EnsureMainThreadIDIsCorrect();
176 // Strict init-order checking in thread-hostile.
177 if (flags()->strict_init_order
)
178 StopInitOrderChecking();
179 GET_STACK_TRACE_THREAD
;
182 REAL(pthread_attr_getdetachstate
)(attr
, &detached
);
184 u32 current_tid
= GetCurrentTidOrInvalid();
185 AsanThread
*t
= AsanThread::Create(start_routine
, arg
);
186 CreateThreadContextArgs args
= { t
, &stack
};
187 asanThreadRegistry().CreateThread(*(uptr
*)t
, detached
, current_tid
, &args
);
188 return REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
190 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
192 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
194 #if SANITIZER_ANDROID
195 INTERCEPTOR(void*, bsd_signal
, int signum
, void *handler
) {
196 if (!AsanInterceptsSignal(signum
) ||
197 common_flags()->allow_user_segv_handler
) {
198 return REAL(bsd_signal
)(signum
, handler
);
203 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
204 if (!AsanInterceptsSignal(signum
) ||
205 common_flags()->allow_user_segv_handler
) {
206 return REAL(signal
)(signum
, handler
);
212 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
213 struct sigaction
*oldact
) {
214 if (!AsanInterceptsSignal(signum
) ||
215 common_flags()->allow_user_segv_handler
) {
216 return REAL(sigaction
)(signum
, act
, oldact
);
221 namespace __sanitizer
{
222 int real_sigaction(int signum
, const void *act
, void *oldact
) {
223 return REAL(sigaction
)(signum
,
224 (struct sigaction
*)act
, (struct sigaction
*)oldact
);
226 } // namespace __sanitizer
228 #elif SANITIZER_POSIX
229 // We need to have defined REAL(sigaction) on posix systems.
230 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
231 struct sigaction
*oldact
)
232 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
234 #if ASAN_INTERCEPT_SWAPCONTEXT
235 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
236 // Align to page size.
237 uptr PageSize
= GetPageSizeCached();
238 uptr bottom
= stack
& ~(PageSize
- 1);
239 ssize
+= stack
- bottom
;
240 ssize
= RoundUpTo(ssize
, PageSize
);
241 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
242 if (ssize
&& ssize
<= kMaxSaneContextStackSize
) {
243 PoisonShadow(bottom
, ssize
, 0);
247 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
248 struct ucontext_t
*ucp
) {
249 static bool reported_warning
= false;
250 if (!reported_warning
) {
251 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
252 "functions and may produce false positives in some cases!\n");
253 reported_warning
= true;
255 // Clear shadow memory for new context (it may share stack
256 // with current context).
258 ReadContextStack(ucp
, &stack
, &ssize
);
259 ClearShadowMemoryForContextStack(stack
, ssize
);
260 int res
= REAL(swapcontext
)(oucp
, ucp
);
261 // swapcontext technically does not return, but program may swap context to
262 // "oucp" later, that would look as if swapcontext() returned 0.
263 // We need to clear shadow for ucp once again, as it may be in arbitrary
265 ClearShadowMemoryForContextStack(stack
, ssize
);
268 #endif // ASAN_INTERCEPT_SWAPCONTEXT
270 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
271 __asan_handle_no_return();
272 REAL(longjmp
)(env
, val
);
275 #if ASAN_INTERCEPT__LONGJMP
276 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
277 __asan_handle_no_return();
278 REAL(_longjmp
)(env
, val
);
282 #if ASAN_INTERCEPT_SIGLONGJMP
283 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
284 __asan_handle_no_return();
285 REAL(siglongjmp
)(env
, val
);
289 #if ASAN_INTERCEPT___CXA_THROW
290 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
291 CHECK(REAL(__cxa_throw
));
292 __asan_handle_no_return();
293 REAL(__cxa_throw
)(a
, b
, c
);
297 #if SANITIZER_WINDOWS
298 INTERCEPTOR_WINAPI(void, RaiseException
, void *a
, void *b
, void *c
, void *d
) {
299 CHECK(REAL(RaiseException
));
300 __asan_handle_no_return();
301 REAL(RaiseException
)(a
, b
, c
, d
);
304 INTERCEPTOR(int, _except_handler3
, void *a
, void *b
, void *c
, void *d
) {
305 CHECK(REAL(_except_handler3
));
306 __asan_handle_no_return();
307 return REAL(_except_handler3
)(a
, b
, c
, d
);
311 // This handler is named differently in -MT and -MD CRTs.
312 #define _except_handler4 _except_handler4_common
314 INTERCEPTOR(int, _except_handler4
, void *a
, void *b
, void *c
, void *d
) {
315 CHECK(REAL(_except_handler4
));
316 __asan_handle_no_return();
317 return REAL(_except_handler4
)(a
, b
, c
, d
);
321 static inline int CharCmp(unsigned char c1
, unsigned char c2
) {
322 return (c1
== c2
) ? 0 : (c1
< c2
) ? -1 : 1;
325 INTERCEPTOR(int, memcmp
, const void *a1
, const void *a2
, uptr size
) {
326 if (UNLIKELY(!asan_inited
)) return internal_memcmp(a1
, a2
, size
);
327 ENSURE_ASAN_INITED();
328 if (flags()->replace_intrin
) {
329 if (flags()->strict_memcmp
) {
330 // Check the entire regions even if the first bytes of the buffers are
332 ASAN_READ_RANGE(a1
, size
);
333 ASAN_READ_RANGE(a2
, size
);
334 // Fallthrough to REAL(memcmp) below.
336 unsigned char c1
= 0, c2
= 0;
337 const unsigned char *s1
= (const unsigned char*)a1
;
338 const unsigned char *s2
= (const unsigned char*)a2
;
340 for (i
= 0; i
< size
; i
++) {
345 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
346 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
347 return CharCmp(c1
, c2
);
350 return REAL(memcmp(a1
, a2
, size
));
353 void *__asan_memcpy(void *to
, const void *from
, uptr size
) {
354 if (UNLIKELY(!asan_inited
)) return internal_memcpy(to
, from
, size
);
355 // memcpy is called during __asan_init() from the internals
357 if (asan_init_is_running
) {
358 return REAL(memcpy
)(to
, from
, size
);
360 ENSURE_ASAN_INITED();
361 if (flags()->replace_intrin
) {
363 // We do not treat memcpy with to==from as a bug.
364 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
365 CHECK_RANGES_OVERLAP("memcpy", to
, size
, from
, size
);
367 ASAN_READ_RANGE(from
, size
);
368 ASAN_WRITE_RANGE(to
, size
);
370 return REAL(memcpy
)(to
, from
, size
);
373 void *__asan_memset(void *block
, int c
, uptr size
) {
374 if (UNLIKELY(!asan_inited
)) return internal_memset(block
, c
, size
);
375 // memset is called inside Printf.
376 if (asan_init_is_running
) {
377 return REAL(memset
)(block
, c
, size
);
379 ENSURE_ASAN_INITED();
380 if (flags()->replace_intrin
) {
381 ASAN_WRITE_RANGE(block
, size
);
383 return REAL(memset
)(block
, c
, size
);
386 void *__asan_memmove(void *to
, const void *from
, uptr size
) {
387 if (UNLIKELY(!asan_inited
))
388 return internal_memmove(to
, from
, size
);
389 ENSURE_ASAN_INITED();
390 if (flags()->replace_intrin
) {
391 ASAN_READ_RANGE(from
, size
);
392 ASAN_WRITE_RANGE(to
, size
);
394 return internal_memmove(to
, from
, size
);
397 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
398 return __asan_memmove(to
, from
, size
);
401 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
403 return __asan_memcpy(to
, from
, size
);
405 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
406 // with WRAP(memcpy). As a result, false positives are reported for memmove()
407 // calls. If we just disable error reporting with
408 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
409 // internal_memcpy(), which may lead to crashes, see
410 // http://llvm.org/bugs/show_bug.cgi?id=16362.
411 return __asan_memmove(to
, from
, size
);
412 #endif // !SANITIZER_MAC
415 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
416 return __asan_memset(block
, c
, size
);
419 INTERCEPTOR(char*, strchr
, const char *str
, int c
) {
420 if (UNLIKELY(!asan_inited
)) return internal_strchr(str
, c
);
421 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
423 if (asan_init_is_running
) {
424 return REAL(strchr
)(str
, c
);
426 ENSURE_ASAN_INITED();
427 char *result
= REAL(strchr
)(str
, c
);
428 if (flags()->replace_str
) {
429 uptr bytes_read
= (result
? result
- str
: REAL(strlen
)(str
)) + 1;
430 ASAN_READ_RANGE(str
, bytes_read
);
435 #if ASAN_INTERCEPT_INDEX
436 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
437 INTERCEPTOR(char*, index
, const char *string
, int c
)
438 ALIAS(WRAPPER_NAME(strchr
));
441 DECLARE_REAL(char*, index
, const char *string
, int c
)
442 OVERRIDE_FUNCTION(index
, strchr
);
444 DEFINE_REAL(char*, index
, const char *string
, int c
)
447 #endif // ASAN_INTERCEPT_INDEX
449 // For both strcat() and strncat() we need to check the validity of |to|
450 // argument irrespective of the |from| length.
451 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
452 ENSURE_ASAN_INITED();
453 if (flags()->replace_str
) {
454 uptr from_length
= REAL(strlen
)(from
);
455 ASAN_READ_RANGE(from
, from_length
+ 1);
456 uptr to_length
= REAL(strlen
)(to
);
457 ASAN_READ_RANGE(to
, to_length
);
458 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
459 // If the copying actually happens, the |from| string should not overlap
460 // with the resulting string starting at |to|, which has a length of
461 // to_length + from_length + 1.
462 if (from_length
> 0) {
463 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
464 from
, from_length
+ 1);
467 return REAL(strcat
)(to
, from
); // NOLINT
470 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
471 ENSURE_ASAN_INITED();
472 if (flags()->replace_str
) {
473 uptr from_length
= MaybeRealStrnlen(from
, size
);
474 uptr copy_length
= Min(size
, from_length
+ 1);
475 ASAN_READ_RANGE(from
, copy_length
);
476 uptr to_length
= REAL(strlen
)(to
);
477 ASAN_READ_RANGE(to
, to_length
);
478 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
479 if (from_length
> 0) {
480 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
484 return REAL(strncat
)(to
, from
, size
);
487 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
489 if (UNLIKELY(!asan_inited
)) return REAL(strcpy
)(to
, from
); // NOLINT
491 // strcpy is called from malloc_default_purgeable_zone()
492 // in __asan::ReplaceSystemAlloc() on Mac.
493 if (asan_init_is_running
) {
494 return REAL(strcpy
)(to
, from
); // NOLINT
496 ENSURE_ASAN_INITED();
497 if (flags()->replace_str
) {
498 uptr from_size
= REAL(strlen
)(from
) + 1;
499 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
500 ASAN_READ_RANGE(from
, from_size
);
501 ASAN_WRITE_RANGE(to
, from_size
);
503 return REAL(strcpy
)(to
, from
); // NOLINT
506 #if ASAN_INTERCEPT_STRDUP
507 INTERCEPTOR(char*, strdup
, const char *s
) {
508 if (UNLIKELY(!asan_inited
)) return internal_strdup(s
);
509 ENSURE_ASAN_INITED();
510 uptr length
= REAL(strlen
)(s
);
511 if (flags()->replace_str
) {
512 ASAN_READ_RANGE(s
, length
+ 1);
514 GET_STACK_TRACE_MALLOC
;
515 void *new_mem
= asan_malloc(length
+ 1, &stack
);
516 REAL(memcpy
)(new_mem
, s
, length
+ 1);
517 return reinterpret_cast<char*>(new_mem
);
521 INTERCEPTOR(SIZE_T
, strlen
, const char *s
) {
522 if (UNLIKELY(!asan_inited
)) return internal_strlen(s
);
523 // strlen is called from malloc_default_purgeable_zone()
524 // in __asan::ReplaceSystemAlloc() on Mac.
525 if (asan_init_is_running
) {
526 return REAL(strlen
)(s
);
528 ENSURE_ASAN_INITED();
529 SIZE_T length
= REAL(strlen
)(s
);
530 if (flags()->replace_str
) {
531 ASAN_READ_RANGE(s
, length
+ 1);
536 INTERCEPTOR(SIZE_T
, wcslen
, const wchar_t *s
) {
537 SIZE_T length
= REAL(wcslen
)(s
);
538 if (!asan_init_is_running
) {
539 ENSURE_ASAN_INITED();
540 ASAN_READ_RANGE(s
, (length
+ 1) * sizeof(wchar_t));
545 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
546 ENSURE_ASAN_INITED();
547 if (flags()->replace_str
) {
548 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
549 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
550 ASAN_READ_RANGE(from
, from_size
);
551 ASAN_WRITE_RANGE(to
, size
);
553 return REAL(strncpy
)(to
, from
, size
);
556 #if ASAN_INTERCEPT_STRNLEN
557 INTERCEPTOR(uptr
, strnlen
, const char *s
, uptr maxlen
) {
558 ENSURE_ASAN_INITED();
559 uptr length
= REAL(strnlen
)(s
, maxlen
);
560 if (flags()->replace_str
) {
561 ASAN_READ_RANGE(s
, Min(length
+ 1, maxlen
));
565 #endif // ASAN_INTERCEPT_STRNLEN
567 static inline bool IsValidStrtolBase(int base
) {
568 return (base
== 0) || (2 <= base
&& base
<= 36);
571 static inline void FixRealStrtolEndptr(const char *nptr
, char **endptr
) {
573 if (nptr
== *endptr
) {
574 // No digits were found at strtol call, we need to find out the last
575 // symbol accessed by strtoll on our own.
576 // We get this symbol by skipping leading blanks and optional +/- sign.
577 while (IsSpace(*nptr
)) nptr
++;
578 if (*nptr
== '+' || *nptr
== '-') nptr
++;
579 *endptr
= (char*)nptr
;
581 CHECK(*endptr
>= nptr
);
584 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
585 char **endptr
, int base
) {
586 ENSURE_ASAN_INITED();
587 if (!flags()->replace_str
) {
588 return REAL(strtol
)(nptr
, endptr
, base
);
591 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
593 *endptr
= real_endptr
;
595 if (IsValidStrtolBase(base
)) {
596 FixRealStrtolEndptr(nptr
, &real_endptr
);
597 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
602 INTERCEPTOR(int, atoi
, const char *nptr
) {
604 if (UNLIKELY(!asan_inited
)) return REAL(atoi
)(nptr
);
606 ENSURE_ASAN_INITED();
607 if (!flags()->replace_str
) {
608 return REAL(atoi
)(nptr
);
611 // "man atoi" tells that behavior of atoi(nptr) is the same as
612 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
613 // parsed integer can't be stored in *long* type (even if it's
614 // different from int). So, we just imitate this behavior.
615 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
616 FixRealStrtolEndptr(nptr
, &real_endptr
);
617 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
621 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
623 if (UNLIKELY(!asan_inited
)) return REAL(atol
)(nptr
);
625 ENSURE_ASAN_INITED();
626 if (!flags()->replace_str
) {
627 return REAL(atol
)(nptr
);
630 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
631 FixRealStrtolEndptr(nptr
, &real_endptr
);
632 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
636 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
637 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
638 char **endptr
, int base
) {
639 ENSURE_ASAN_INITED();
640 if (!flags()->replace_str
) {
641 return REAL(strtoll
)(nptr
, endptr
, base
);
644 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
646 *endptr
= real_endptr
;
648 // If base has unsupported value, strtoll can exit with EINVAL
649 // without reading any characters. So do additional checks only
651 if (IsValidStrtolBase(base
)) {
652 FixRealStrtolEndptr(nptr
, &real_endptr
);
653 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
658 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
659 ENSURE_ASAN_INITED();
660 if (!flags()->replace_str
) {
661 return REAL(atoll
)(nptr
);
664 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
665 FixRealStrtolEndptr(nptr
, &real_endptr
);
666 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
669 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
671 static void AtCxaAtexit(void *unused
) {
673 StopInitOrderChecking();
676 #if ASAN_INTERCEPT___CXA_ATEXIT
677 INTERCEPTOR(int, __cxa_atexit
, void (*func
)(void *), void *arg
,
680 if (UNLIKELY(!asan_inited
)) return REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
682 ENSURE_ASAN_INITED();
683 int res
= REAL(__cxa_atexit
)(func
, arg
, dso_handle
);
684 REAL(__cxa_atexit
)(AtCxaAtexit
, 0, 0);
687 #endif // ASAN_INTERCEPT___CXA_ATEXIT
689 #if ASAN_INTERCEPT_FORK
690 INTERCEPTOR(int, fork
, void) {
691 ENSURE_ASAN_INITED();
692 if (common_flags()->coverage
) CovBeforeFork();
693 int pid
= REAL(fork
)();
694 if (common_flags()->coverage
) CovAfterFork(pid
);
697 #endif // ASAN_INTERCEPT_FORK
699 #if SANITIZER_WINDOWS
700 INTERCEPTOR_WINAPI(DWORD
, CreateThread
,
701 void* security
, uptr stack_size
,
702 DWORD (__stdcall
*start_routine
)(void*), void* arg
,
703 DWORD thr_flags
, void* tid
) {
704 // Strict init-order checking in thread-hostile.
705 if (flags()->strict_init_order
)
706 StopInitOrderChecking();
707 GET_STACK_TRACE_THREAD
;
708 u32 current_tid
= GetCurrentTidOrInvalid();
709 AsanThread
*t
= AsanThread::Create(start_routine
, arg
);
710 CreateThreadContextArgs args
= { t
, &stack
};
711 bool detached
= false; // FIXME: how can we determine it on Windows?
712 asanThreadRegistry().CreateThread(*(uptr
*)t
, detached
, current_tid
, &args
);
713 return REAL(CreateThread
)(security
, stack_size
,
714 asan_thread_start
, t
, thr_flags
, tid
);
718 void InitializeWindowsInterceptors() {
719 ASAN_INTERCEPT_FUNC(CreateThread
);
720 ASAN_INTERCEPT_FUNC(RaiseException
);
721 ASAN_INTERCEPT_FUNC(_except_handler3
);
722 ASAN_INTERCEPT_FUNC(_except_handler4
);
725 } // namespace __asan
728 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
730 void InitializeAsanInterceptors() {
731 static bool was_called_once
;
732 CHECK(was_called_once
== false);
733 was_called_once
= true;
734 InitializeCommonInterceptors();
736 // Intercept mem* functions.
737 ASAN_INTERCEPT_FUNC(memcmp
);
738 ASAN_INTERCEPT_FUNC(memmove
);
739 ASAN_INTERCEPT_FUNC(memset
);
740 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
741 ASAN_INTERCEPT_FUNC(memcpy
);
744 // Intercept str* functions.
745 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
746 ASAN_INTERCEPT_FUNC(strchr
);
747 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
748 ASAN_INTERCEPT_FUNC(strlen
);
749 ASAN_INTERCEPT_FUNC(wcslen
);
750 ASAN_INTERCEPT_FUNC(strncat
);
751 ASAN_INTERCEPT_FUNC(strncpy
);
752 #if ASAN_INTERCEPT_STRDUP
753 ASAN_INTERCEPT_FUNC(strdup
);
755 #if ASAN_INTERCEPT_STRNLEN
756 ASAN_INTERCEPT_FUNC(strnlen
);
758 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
759 ASAN_INTERCEPT_FUNC(index
);
762 ASAN_INTERCEPT_FUNC(atoi
);
763 ASAN_INTERCEPT_FUNC(atol
);
764 ASAN_INTERCEPT_FUNC(strtol
);
765 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
766 ASAN_INTERCEPT_FUNC(atoll
);
767 ASAN_INTERCEPT_FUNC(strtoll
);
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 ASAN_INTERCEPT_FUNC(__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 #if ASAN_INTERCEPT_FORK
806 ASAN_INTERCEPT_FUNC(fork
);
809 // Some Windows-specific interceptors.
810 #if SANITIZER_WINDOWS
811 InitializeWindowsInterceptors();
814 VReport(1, "AddressSanitizer: libc interceptors initialized\n");
817 } // namespace __asan