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_intercepted_functions.h"
16 #include "asan_internal.h"
17 #include "asan_mapping.h"
18 #include "asan_report.h"
19 #include "asan_stack.h"
20 #include "asan_stats.h"
21 #include "asan_thread_registry.h"
22 #include "interception/interception.h"
23 #include "sanitizer_common/sanitizer_libc.h"
27 // Return true if we can quickly decide that the region is unpoisoned.
28 static inline bool QuickCheckForUnpoisonedRegion(uptr beg
, uptr size
) {
29 if (size
== 0) return true;
31 return !AddressIsPoisoned(beg
) &&
32 !AddressIsPoisoned(beg
+ size
- 1) &&
33 !AddressIsPoisoned(beg
+ size
/ 2);
37 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
38 // and ASAN_WRITE_RANGE as macro instead of function so
39 // that no extra frames are created, and stack trace contains
40 // relevant information only.
41 // We check all shadow bytes.
42 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
43 uptr __offset = (uptr)(offset); \
44 uptr __size = (uptr)(size); \
45 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
46 __asan_region_is_poisoned(__offset, __size)) { \
47 GET_CURRENT_PC_BP_SP; \
48 __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \
52 #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
53 #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
55 // Behavior of functions like "memcpy" or "strcpy" is undefined
56 // if memory intervals overlap. We report error in this case.
57 // Macro is used to avoid creation of new frames.
58 static inline bool RangesOverlap(const char *offset1
, uptr length1
,
59 const char *offset2
, uptr length2
) {
60 return !((offset1
+ length1
<= offset2
) || (offset2
+ length2
<= offset1
));
62 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
63 const char *offset1 = (const char*)_offset1; \
64 const char *offset2 = (const char*)_offset2; \
65 if (RangesOverlap(offset1, length1, offset2, length2)) { \
66 GET_STACK_TRACE_FATAL_HERE; \
67 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
68 offset2, length2, &stack); \
72 #define ENSURE_ASAN_INITED() do { \
73 CHECK(!asan_init_is_running); \
79 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
80 #if ASAN_INTERCEPT_STRNLEN
81 if (REAL(strnlen
) != 0) {
82 return REAL(strnlen
)(s
, maxlen
);
85 return internal_strnlen(s
, maxlen
);
88 void SetThreadName(const char *name
) {
89 AsanThread
*t
= asanThreadRegistry().GetCurrent();
91 t
->summary()->set_name(name
);
96 // ---------------------- Wrappers ---------------- {{{1
97 using namespace __asan
; // NOLINT
99 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
100 ASAN_WRITE_RANGE(ptr, size)
101 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
102 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
106 ENSURE_ASAN_INITED(); \
108 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
109 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
110 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
111 #include "sanitizer_common/sanitizer_common_interceptors.inc"
113 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
114 AsanThread
*t
= (AsanThread
*)arg
;
115 asanThreadRegistry().SetCurrent(t
);
116 return t
->ThreadStart();
119 #if ASAN_INTERCEPT_PTHREAD_CREATE
120 INTERCEPTOR(int, pthread_create
, void *thread
,
121 void *attr
, void *(*start_routine
)(void*), void *arg
) {
122 GET_STACK_TRACE_THREAD
;
123 u32 current_tid
= asanThreadRegistry().GetCurrentTidOrInvalid();
124 AsanThread
*t
= AsanThread::Create(current_tid
, start_routine
, arg
, &stack
);
125 asanThreadRegistry().RegisterThread(t
);
126 return REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
128 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
130 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
131 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
132 if (!AsanInterceptsSignal(signum
)) {
133 return REAL(signal
)(signum
, handler
);
138 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
139 struct sigaction
*oldact
) {
140 if (!AsanInterceptsSignal(signum
)) {
141 return REAL(sigaction
)(signum
, act
, oldact
);
146 // We need to have defined REAL(sigaction) on posix systems.
147 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
148 struct sigaction
*oldact
);
149 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
151 #if ASAN_INTERCEPT_SWAPCONTEXT
152 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
153 // Align to page size.
154 uptr PageSize
= GetPageSizeCached();
155 uptr bottom
= stack
& ~(PageSize
- 1);
156 ssize
+= stack
- bottom
;
157 ssize
= RoundUpTo(ssize
, PageSize
);
158 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
159 if (ssize
&& ssize
<= kMaxSaneContextStackSize
) {
160 PoisonShadow(bottom
, ssize
, 0);
164 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
165 struct ucontext_t
*ucp
) {
166 static bool reported_warning
= false;
167 if (!reported_warning
) {
168 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
169 "functions and may produce false positives in some cases!\n");
170 reported_warning
= true;
172 // Clear shadow memory for new context (it may share stack
173 // with current context).
175 ReadContextStack(ucp
, &stack
, &ssize
);
176 ClearShadowMemoryForContextStack(stack
, ssize
);
177 int res
= REAL(swapcontext
)(oucp
, ucp
);
178 // swapcontext technically does not return, but program may swap context to
179 // "oucp" later, that would look as if swapcontext() returned 0.
180 // We need to clear shadow for ucp once again, as it may be in arbitrary
182 ClearShadowMemoryForContextStack(stack
, ssize
);
185 #endif // ASAN_INTERCEPT_SWAPCONTEXT
187 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
188 __asan_handle_no_return();
189 REAL(longjmp
)(env
, val
);
192 #if ASAN_INTERCEPT__LONGJMP
193 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
194 __asan_handle_no_return();
195 REAL(_longjmp
)(env
, val
);
199 #if ASAN_INTERCEPT_SIGLONGJMP
200 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
201 __asan_handle_no_return();
202 REAL(siglongjmp
)(env
, val
);
206 #if ASAN_INTERCEPT___CXA_THROW
207 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
208 CHECK(REAL(__cxa_throw
));
209 __asan_handle_no_return();
210 REAL(__cxa_throw
)(a
, b
, c
);
214 // intercept mlock and friends.
215 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
216 // All functions return 0 (success).
217 static void MlockIsUnsupported() {
218 static bool printed
= 0;
221 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
225 INTERCEPTOR(int, mlock
, const void *addr
, uptr len
) {
226 MlockIsUnsupported();
230 INTERCEPTOR(int, munlock
, const void *addr
, uptr len
) {
231 MlockIsUnsupported();
235 INTERCEPTOR(int, mlockall
, int flags
) {
236 MlockIsUnsupported();
240 INTERCEPTOR(int, munlockall
, void) {
241 MlockIsUnsupported();
246 static inline int CharCmp(unsigned char c1
, unsigned char c2
) {
247 return (c1
== c2
) ? 0 : (c1
< c2
) ? -1 : 1;
250 static inline int CharCaseCmp(unsigned char c1
, unsigned char c2
) {
251 int c1_low
= ToLower(c1
);
252 int c2_low
= ToLower(c2
);
253 return c1_low
- c2_low
;
256 INTERCEPTOR(int, memcmp
, const void *a1
, const void *a2
, uptr size
) {
257 if (!asan_inited
) return internal_memcmp(a1
, a2
, size
);
258 ENSURE_ASAN_INITED();
259 unsigned char c1
= 0, c2
= 0;
260 const unsigned char *s1
= (const unsigned char*)a1
;
261 const unsigned char *s2
= (const unsigned char*)a2
;
263 for (i
= 0; i
< size
; i
++) {
268 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
269 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
270 return CharCmp(c1
, c2
);
273 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
274 if (!asan_inited
) return internal_memcpy(to
, from
, size
);
275 // memcpy is called during __asan_init() from the internals
277 if (asan_init_is_running
) {
278 return REAL(memcpy
)(to
, from
, size
);
280 ENSURE_ASAN_INITED();
281 if (flags()->replace_intrin
) {
283 // We do not treat memcpy with to==from as a bug.
284 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
285 CHECK_RANGES_OVERLAP("memcpy", to
, size
, from
, size
);
287 ASAN_READ_RANGE(from
, size
);
288 ASAN_WRITE_RANGE(to
, size
);
290 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
291 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
292 return internal_memcpy(to
, from
, size
);
295 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
296 if (!asan_inited
) return internal_memmove(to
, from
, size
);
297 if (asan_init_is_running
) {
298 return REAL(memmove
)(to
, from
, size
);
300 ENSURE_ASAN_INITED();
301 if (flags()->replace_intrin
) {
302 ASAN_READ_RANGE(from
, size
);
303 ASAN_WRITE_RANGE(to
, size
);
305 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
306 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
307 return internal_memmove(to
, from
, size
);
310 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
311 if (!asan_inited
) return internal_memset(block
, c
, size
);
312 // memset is called inside Printf.
313 if (asan_init_is_running
) {
314 return REAL(memset
)(block
, c
, size
);
316 ENSURE_ASAN_INITED();
317 if (flags()->replace_intrin
) {
318 ASAN_WRITE_RANGE(block
, size
);
320 return REAL(memset
)(block
, c
, size
);
323 INTERCEPTOR(char*, strchr
, const char *str
, int c
) {
324 if (!asan_inited
) return internal_strchr(str
, c
);
325 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
327 if (asan_init_is_running
) {
328 return REAL(strchr
)(str
, c
);
330 ENSURE_ASAN_INITED();
331 char *result
= REAL(strchr
)(str
, c
);
332 if (flags()->replace_str
) {
333 uptr bytes_read
= (result
? result
- str
: REAL(strlen
)(str
)) + 1;
334 ASAN_READ_RANGE(str
, bytes_read
);
339 #if ASAN_INTERCEPT_INDEX
340 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
341 INTERCEPTOR(char*, index
, const char *string
, int c
)
342 ALIAS(WRAPPER_NAME(strchr
));
344 DEFINE_REAL(char*, index
, const char *string
, int c
)
346 #endif // ASAN_INTERCEPT_INDEX
348 // For both strcat() and strncat() we need to check the validity of |to|
349 // argument irrespective of the |from| length.
350 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
351 ENSURE_ASAN_INITED();
352 if (flags()->replace_str
) {
353 uptr from_length
= REAL(strlen
)(from
);
354 ASAN_READ_RANGE(from
, from_length
+ 1);
355 uptr to_length
= REAL(strlen
)(to
);
356 ASAN_READ_RANGE(to
, to_length
);
357 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
358 // If the copying actually happens, the |from| string should not overlap
359 // with the resulting string starting at |to|, which has a length of
360 // to_length + from_length + 1.
361 if (from_length
> 0) {
362 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
363 from
, from_length
+ 1);
366 return REAL(strcat
)(to
, from
); // NOLINT
369 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
370 ENSURE_ASAN_INITED();
371 if (flags()->replace_str
) {
372 uptr from_length
= MaybeRealStrnlen(from
, size
);
373 uptr copy_length
= Min(size
, from_length
+ 1);
374 ASAN_READ_RANGE(from
, copy_length
);
375 uptr to_length
= REAL(strlen
)(to
);
376 ASAN_READ_RANGE(to
, to_length
);
377 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
378 if (from_length
> 0) {
379 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
383 return REAL(strncat
)(to
, from
, size
);
386 INTERCEPTOR(int, strcmp
, const char *s1
, const char *s2
) {
387 if (!asan_inited
) return internal_strcmp(s1
, s2
);
388 if (asan_init_is_running
) {
389 return REAL(strcmp
)(s1
, s2
);
391 ENSURE_ASAN_INITED();
392 unsigned char c1
, c2
;
395 c1
= (unsigned char)s1
[i
];
396 c2
= (unsigned char)s2
[i
];
397 if (c1
!= c2
|| c1
== '\0') break;
399 ASAN_READ_RANGE(s1
, i
+ 1);
400 ASAN_READ_RANGE(s2
, i
+ 1);
401 return CharCmp(c1
, c2
);
404 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
405 #if defined(__APPLE__)
406 if (!asan_inited
) return REAL(strcpy
)(to
, from
); // NOLINT
408 // strcpy is called from malloc_default_purgeable_zone()
409 // in __asan::ReplaceSystemAlloc() on Mac.
410 if (asan_init_is_running
) {
411 return REAL(strcpy
)(to
, from
); // NOLINT
413 ENSURE_ASAN_INITED();
414 if (flags()->replace_str
) {
415 uptr from_size
= REAL(strlen
)(from
) + 1;
416 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
417 ASAN_READ_RANGE(from
, from_size
);
418 ASAN_WRITE_RANGE(to
, from_size
);
420 return REAL(strcpy
)(to
, from
); // NOLINT
423 #if ASAN_INTERCEPT_STRDUP
424 INTERCEPTOR(char*, strdup
, const char *s
) {
425 #if defined(__APPLE__)
426 // FIXME: because internal_strdup() uses InternalAlloc(), which currently
427 // just calls malloc() on Mac, we can't use internal_strdup() with the
428 // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
429 // starts using mmap() instead.
430 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
431 if (!asan_inited
) return REAL(strdup
)(s
);
433 if (!asan_inited
) return internal_strdup(s
);
434 ENSURE_ASAN_INITED();
435 if (flags()->replace_str
) {
436 uptr length
= REAL(strlen
)(s
);
437 ASAN_READ_RANGE(s
, length
+ 1);
439 return REAL(strdup
)(s
);
443 INTERCEPTOR(uptr
, strlen
, const char *s
) {
444 if (!asan_inited
) return internal_strlen(s
);
445 // strlen is called from malloc_default_purgeable_zone()
446 // in __asan::ReplaceSystemAlloc() on Mac.
447 if (asan_init_is_running
) {
448 return REAL(strlen
)(s
);
450 ENSURE_ASAN_INITED();
451 uptr length
= REAL(strlen
)(s
);
452 if (flags()->replace_str
) {
453 ASAN_READ_RANGE(s
, length
+ 1);
458 #if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
459 INTERCEPTOR(int, strcasecmp
, const char *s1
, const char *s2
) {
460 ENSURE_ASAN_INITED();
461 unsigned char c1
, c2
;
464 c1
= (unsigned char)s1
[i
];
465 c2
= (unsigned char)s2
[i
];
466 if (CharCaseCmp(c1
, c2
) != 0 || c1
== '\0') break;
468 ASAN_READ_RANGE(s1
, i
+ 1);
469 ASAN_READ_RANGE(s2
, i
+ 1);
470 return CharCaseCmp(c1
, c2
);
473 INTERCEPTOR(int, strncasecmp
, const char *s1
, const char *s2
, uptr n
) {
474 ENSURE_ASAN_INITED();
475 unsigned char c1
= 0, c2
= 0;
477 for (i
= 0; i
< n
; i
++) {
478 c1
= (unsigned char)s1
[i
];
479 c2
= (unsigned char)s2
[i
];
480 if (CharCaseCmp(c1
, c2
) != 0 || c1
== '\0') break;
482 ASAN_READ_RANGE(s1
, Min(i
+ 1, n
));
483 ASAN_READ_RANGE(s2
, Min(i
+ 1, n
));
484 return CharCaseCmp(c1
, c2
);
486 #endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
488 INTERCEPTOR(int, strncmp
, const char *s1
, const char *s2
, uptr size
) {
489 if (!asan_inited
) return internal_strncmp(s1
, s2
, size
);
490 // strncmp is called from malloc_default_purgeable_zone()
491 // in __asan::ReplaceSystemAlloc() on Mac.
492 if (asan_init_is_running
) {
493 return REAL(strncmp
)(s1
, s2
, size
);
495 ENSURE_ASAN_INITED();
496 unsigned char c1
= 0, c2
= 0;
498 for (i
= 0; i
< size
; i
++) {
499 c1
= (unsigned char)s1
[i
];
500 c2
= (unsigned char)s2
[i
];
501 if (c1
!= c2
|| c1
== '\0') break;
503 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
504 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
505 return CharCmp(c1
, c2
);
508 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
509 ENSURE_ASAN_INITED();
510 if (flags()->replace_str
) {
511 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
512 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
513 ASAN_READ_RANGE(from
, from_size
);
514 ASAN_WRITE_RANGE(to
, size
);
516 return REAL(strncpy
)(to
, from
, size
);
519 #if ASAN_INTERCEPT_STRNLEN
520 INTERCEPTOR(uptr
, strnlen
, const char *s
, uptr maxlen
) {
521 ENSURE_ASAN_INITED();
522 uptr length
= REAL(strnlen
)(s
, maxlen
);
523 if (flags()->replace_str
) {
524 ASAN_READ_RANGE(s
, Min(length
+ 1, maxlen
));
528 #endif // ASAN_INTERCEPT_STRNLEN
530 static inline bool IsValidStrtolBase(int base
) {
531 return (base
== 0) || (2 <= base
&& base
<= 36);
534 static inline void FixRealStrtolEndptr(const char *nptr
, char **endptr
) {
536 if (nptr
== *endptr
) {
537 // No digits were found at strtol call, we need to find out the last
538 // symbol accessed by strtoll on our own.
539 // We get this symbol by skipping leading blanks and optional +/- sign.
540 while (IsSpace(*nptr
)) nptr
++;
541 if (*nptr
== '+' || *nptr
== '-') nptr
++;
542 *endptr
= (char*)nptr
;
544 CHECK(*endptr
>= nptr
);
547 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
548 char **endptr
, int base
) {
549 ENSURE_ASAN_INITED();
550 if (!flags()->replace_str
) {
551 return REAL(strtol
)(nptr
, endptr
, base
);
554 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
556 *endptr
= real_endptr
;
558 if (IsValidStrtolBase(base
)) {
559 FixRealStrtolEndptr(nptr
, &real_endptr
);
560 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
565 INTERCEPTOR(int, atoi
, const char *nptr
) {
566 #if defined(__APPLE__)
567 if (!asan_inited
) return REAL(atoi
)(nptr
);
569 ENSURE_ASAN_INITED();
570 if (!flags()->replace_str
) {
571 return REAL(atoi
)(nptr
);
574 // "man atoi" tells that behavior of atoi(nptr) is the same as
575 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
576 // parsed integer can't be stored in *long* type (even if it's
577 // different from int). So, we just imitate this behavior.
578 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
579 FixRealStrtolEndptr(nptr
, &real_endptr
);
580 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
584 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
585 #if defined(__APPLE__)
586 if (!asan_inited
) return REAL(atol
)(nptr
);
588 ENSURE_ASAN_INITED();
589 if (!flags()->replace_str
) {
590 return REAL(atol
)(nptr
);
593 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
594 FixRealStrtolEndptr(nptr
, &real_endptr
);
595 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
599 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
600 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
601 char **endptr
, int base
) {
602 ENSURE_ASAN_INITED();
603 if (!flags()->replace_str
) {
604 return REAL(strtoll
)(nptr
, endptr
, base
);
607 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
609 *endptr
= real_endptr
;
611 // If base has unsupported value, strtoll can exit with EINVAL
612 // without reading any characters. So do additional checks only
614 if (IsValidStrtolBase(base
)) {
615 FixRealStrtolEndptr(nptr
, &real_endptr
);
616 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
621 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
622 ENSURE_ASAN_INITED();
623 if (!flags()->replace_str
) {
624 return REAL(atoll
)(nptr
);
627 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
628 FixRealStrtolEndptr(nptr
, &real_endptr
);
629 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
632 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
634 #define ASAN_INTERCEPT_FUNC(name) do { \
635 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
636 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
640 INTERCEPTOR_WINAPI(DWORD
, CreateThread
,
641 void* security
, uptr stack_size
,
642 DWORD (__stdcall
*start_routine
)(void*), void* arg
,
643 DWORD flags
, void* tid
) {
644 GET_STACK_TRACE_THREAD
;
645 u32 current_tid
= asanThreadRegistry().GetCurrentTidOrInvalid();
646 AsanThread
*t
= AsanThread::Create(current_tid
, start_routine
, arg
, &stack
);
647 asanThreadRegistry().RegisterThread(t
);
648 return REAL(CreateThread
)(security
, stack_size
,
649 asan_thread_start
, t
, flags
, tid
);
653 void InitializeWindowsInterceptors() {
654 ASAN_INTERCEPT_FUNC(CreateThread
);
657 } // namespace __asan
660 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
662 void InitializeAsanInterceptors() {
663 static bool was_called_once
;
664 CHECK(was_called_once
== false);
665 was_called_once
= true;
666 #if defined(__APPLE__)
669 SANITIZER_COMMON_INTERCEPTORS_INIT
;
671 // Intercept mem* functions.
672 ASAN_INTERCEPT_FUNC(memcmp
);
673 ASAN_INTERCEPT_FUNC(memmove
);
674 ASAN_INTERCEPT_FUNC(memset
);
675 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
676 ASAN_INTERCEPT_FUNC(memcpy
);
679 // Intercept str* functions.
680 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
681 ASAN_INTERCEPT_FUNC(strchr
);
682 ASAN_INTERCEPT_FUNC(strcmp
);
683 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
684 ASAN_INTERCEPT_FUNC(strlen
);
685 ASAN_INTERCEPT_FUNC(strncat
);
686 ASAN_INTERCEPT_FUNC(strncmp
);
687 ASAN_INTERCEPT_FUNC(strncpy
);
688 #if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
689 ASAN_INTERCEPT_FUNC(strcasecmp
);
690 ASAN_INTERCEPT_FUNC(strncasecmp
);
692 #if ASAN_INTERCEPT_STRDUP
693 ASAN_INTERCEPT_FUNC(strdup
);
695 #if ASAN_INTERCEPT_STRNLEN
696 ASAN_INTERCEPT_FUNC(strnlen
);
698 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
699 ASAN_INTERCEPT_FUNC(index
);
702 ASAN_INTERCEPT_FUNC(atoi
);
703 ASAN_INTERCEPT_FUNC(atol
);
704 ASAN_INTERCEPT_FUNC(strtol
);
705 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
706 ASAN_INTERCEPT_FUNC(atoll
);
707 ASAN_INTERCEPT_FUNC(strtoll
);
710 #if ASAN_INTERCEPT_MLOCKX
711 // Intercept mlock/munlock.
712 ASAN_INTERCEPT_FUNC(mlock
);
713 ASAN_INTERCEPT_FUNC(munlock
);
714 ASAN_INTERCEPT_FUNC(mlockall
);
715 ASAN_INTERCEPT_FUNC(munlockall
);
718 // Intecept signal- and jump-related functions.
719 ASAN_INTERCEPT_FUNC(longjmp
);
720 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
721 ASAN_INTERCEPT_FUNC(sigaction
);
722 ASAN_INTERCEPT_FUNC(signal
);
724 #if ASAN_INTERCEPT_SWAPCONTEXT
725 ASAN_INTERCEPT_FUNC(swapcontext
);
727 #if ASAN_INTERCEPT__LONGJMP
728 ASAN_INTERCEPT_FUNC(_longjmp
);
730 #if ASAN_INTERCEPT_SIGLONGJMP
731 ASAN_INTERCEPT_FUNC(siglongjmp
);
734 // Intercept exception handling functions.
735 #if ASAN_INTERCEPT___CXA_THROW
736 INTERCEPT_FUNCTION(__cxa_throw
);
739 // Intercept threading-related functions
740 #if ASAN_INTERCEPT_PTHREAD_CREATE
741 ASAN_INTERCEPT_FUNC(pthread_create
);
744 // Some Windows-specific interceptors.
746 InitializeWindowsInterceptors();
749 if (flags()->verbosity
> 0) {
750 Report("AddressSanitizer: libc interceptors initialized\n");
755 } // namespace __asan