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/asan_interface.h"
24 #include "sanitizer_common/sanitizer_libc.h"
28 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
29 // and ASAN_WRITE_RANGE as macro instead of function so
30 // that no extra frames are created, and stack trace contains
31 // relevant information only.
32 // We check all shadow bytes.
33 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
34 if (uptr __ptr = __asan_region_is_poisoned((uptr)(offset), size)) { \
35 GET_CURRENT_PC_BP_SP; \
36 __asan_report_error(pc, bp, sp, __ptr, isWrite, /* access_size */1); \
40 #define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
41 #define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
43 // Behavior of functions like "memcpy" or "strcpy" is undefined
44 // if memory intervals overlap. We report error in this case.
45 // Macro is used to avoid creation of new frames.
46 static inline bool RangesOverlap(const char *offset1
, uptr length1
,
47 const char *offset2
, uptr length2
) {
48 return !((offset1
+ length1
<= offset2
) || (offset2
+ length2
<= offset1
));
50 #define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
51 const char *offset1 = (const char*)_offset1; \
52 const char *offset2 = (const char*)_offset2; \
53 if (RangesOverlap(offset1, length1, offset2, length2)) { \
54 GET_STACK_TRACE_FATAL_HERE; \
55 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
56 offset2, length2, &stack); \
60 #define ENSURE_ASAN_INITED() do { \
61 CHECK(!asan_init_is_running); \
67 static inline uptr
MaybeRealStrnlen(const char *s
, uptr maxlen
) {
68 #if ASAN_INTERCEPT_STRNLEN
69 if (REAL(strnlen
) != 0) {
70 return REAL(strnlen
)(s
, maxlen
);
73 return internal_strnlen(s
, maxlen
);
76 void SetThreadName(const char *name
) {
77 AsanThread
*t
= asanThreadRegistry().GetCurrent();
79 t
->summary()->set_name(name
);
84 // ---------------------- Wrappers ---------------- {{{1
85 using namespace __asan
; // NOLINT
87 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
88 ASAN_WRITE_RANGE(ptr, size)
89 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
90 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
94 ENSURE_ASAN_INITED(); \
96 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
97 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
98 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
99 #include "sanitizer_common/sanitizer_common_interceptors.inc"
101 static thread_return_t THREAD_CALLING_CONV
asan_thread_start(void *arg
) {
102 AsanThread
*t
= (AsanThread
*)arg
;
103 asanThreadRegistry().SetCurrent(t
);
104 return t
->ThreadStart();
107 #if ASAN_INTERCEPT_PTHREAD_CREATE
108 INTERCEPTOR(int, pthread_create
, void *thread
,
109 void *attr
, void *(*start_routine
)(void*), void *arg
) {
110 GET_STACK_TRACE_THREAD
;
111 u32 current_tid
= asanThreadRegistry().GetCurrentTidOrInvalid();
112 AsanThread
*t
= AsanThread::Create(current_tid
, start_routine
, arg
, &stack
);
113 asanThreadRegistry().RegisterThread(t
);
114 return REAL(pthread_create
)(thread
, attr
, asan_thread_start
, t
);
116 #endif // ASAN_INTERCEPT_PTHREAD_CREATE
118 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
119 INTERCEPTOR(void*, signal
, int signum
, void *handler
) {
120 if (!AsanInterceptsSignal(signum
)) {
121 return REAL(signal
)(signum
, handler
);
126 INTERCEPTOR(int, sigaction
, int signum
, const struct sigaction
*act
,
127 struct sigaction
*oldact
) {
128 if (!AsanInterceptsSignal(signum
)) {
129 return REAL(sigaction
)(signum
, act
, oldact
);
134 // We need to have defined REAL(sigaction) on posix systems.
135 DEFINE_REAL(int, sigaction
, int signum
, const struct sigaction
*act
,
136 struct sigaction
*oldact
);
137 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
139 #if ASAN_INTERCEPT_SWAPCONTEXT
140 static void ClearShadowMemoryForContextStack(uptr stack
, uptr ssize
) {
141 // Align to page size.
142 uptr PageSize
= GetPageSizeCached();
143 uptr bottom
= stack
& ~(PageSize
- 1);
144 ssize
+= stack
- bottom
;
145 ssize
= RoundUpTo(ssize
, PageSize
);
146 static const uptr kMaxSaneContextStackSize
= 1 << 22; // 4 Mb
147 if (ssize
&& ssize
<= kMaxSaneContextStackSize
) {
148 PoisonShadow(bottom
, ssize
, 0);
152 INTERCEPTOR(int, swapcontext
, struct ucontext_t
*oucp
,
153 struct ucontext_t
*ucp
) {
154 static bool reported_warning
= false;
155 if (!reported_warning
) {
156 Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
157 "functions and may produce false positives in some cases!\n");
158 reported_warning
= true;
160 // Clear shadow memory for new context (it may share stack
161 // with current context).
163 ReadContextStack(ucp
, &stack
, &ssize
);
164 ClearShadowMemoryForContextStack(stack
, ssize
);
165 int res
= REAL(swapcontext
)(oucp
, ucp
);
166 // swapcontext technically does not return, but program may swap context to
167 // "oucp" later, that would look as if swapcontext() returned 0.
168 // We need to clear shadow for ucp once again, as it may be in arbitrary
170 ClearShadowMemoryForContextStack(stack
, ssize
);
173 #endif // ASAN_INTERCEPT_SWAPCONTEXT
175 INTERCEPTOR(void, longjmp
, void *env
, int val
) {
176 __asan_handle_no_return();
177 REAL(longjmp
)(env
, val
);
180 #if ASAN_INTERCEPT__LONGJMP
181 INTERCEPTOR(void, _longjmp
, void *env
, int val
) {
182 __asan_handle_no_return();
183 REAL(_longjmp
)(env
, val
);
187 #if ASAN_INTERCEPT_SIGLONGJMP
188 INTERCEPTOR(void, siglongjmp
, void *env
, int val
) {
189 __asan_handle_no_return();
190 REAL(siglongjmp
)(env
, val
);
194 #if ASAN_INTERCEPT___CXA_THROW
195 INTERCEPTOR(void, __cxa_throw
, void *a
, void *b
, void *c
) {
196 CHECK(REAL(__cxa_throw
));
197 __asan_handle_no_return();
198 REAL(__cxa_throw
)(a
, b
, c
);
202 // intercept mlock and friends.
203 // Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
204 // All functions return 0 (success).
205 static void MlockIsUnsupported() {
206 static bool printed
= 0;
209 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
213 INTERCEPTOR(int, mlock
, const void *addr
, uptr len
) {
214 MlockIsUnsupported();
218 INTERCEPTOR(int, munlock
, const void *addr
, uptr len
) {
219 MlockIsUnsupported();
223 INTERCEPTOR(int, mlockall
, int flags
) {
224 MlockIsUnsupported();
228 INTERCEPTOR(int, munlockall
, void) {
229 MlockIsUnsupported();
234 static inline int CharCmp(unsigned char c1
, unsigned char c2
) {
235 return (c1
== c2
) ? 0 : (c1
< c2
) ? -1 : 1;
238 static inline int CharCaseCmp(unsigned char c1
, unsigned char c2
) {
239 int c1_low
= ToLower(c1
);
240 int c2_low
= ToLower(c2
);
241 return c1_low
- c2_low
;
244 INTERCEPTOR(int, memcmp
, const void *a1
, const void *a2
, uptr size
) {
245 if (!asan_inited
) return internal_memcmp(a1
, a2
, size
);
246 ENSURE_ASAN_INITED();
247 unsigned char c1
= 0, c2
= 0;
248 const unsigned char *s1
= (const unsigned char*)a1
;
249 const unsigned char *s2
= (const unsigned char*)a2
;
251 for (i
= 0; i
< size
; i
++) {
256 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
257 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
258 return CharCmp(c1
, c2
);
261 INTERCEPTOR(void*, memcpy
, void *to
, const void *from
, uptr size
) {
262 if (!asan_inited
) return internal_memcpy(to
, from
, size
);
263 // memcpy is called during __asan_init() from the internals
265 if (asan_init_is_running
) {
266 return REAL(memcpy
)(to
, from
, size
);
268 ENSURE_ASAN_INITED();
269 if (flags()->replace_intrin
) {
271 // We do not treat memcpy with to==from as a bug.
272 // See http://llvm.org/bugs/show_bug.cgi?id=11763.
273 CHECK_RANGES_OVERLAP("memcpy", to
, size
, from
, size
);
275 ASAN_READ_RANGE(from
, size
);
276 ASAN_WRITE_RANGE(to
, size
);
278 #if MAC_INTERPOSE_FUNCTIONS
279 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
280 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
281 return internal_memcpy(to
, from
, size
);
283 return REAL(memcpy
)(to
, from
, size
);
287 INTERCEPTOR(void*, memmove
, void *to
, const void *from
, uptr size
) {
288 if (!asan_inited
) return internal_memmove(to
, from
, size
);
289 if (asan_init_is_running
) {
290 return REAL(memmove
)(to
, from
, size
);
292 ENSURE_ASAN_INITED();
293 if (flags()->replace_intrin
) {
294 ASAN_READ_RANGE(from
, size
);
295 ASAN_WRITE_RANGE(to
, size
);
297 #if MAC_INTERPOSE_FUNCTIONS
298 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
299 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
300 return internal_memmove(to
, from
, size
);
302 return REAL(memmove
)(to
, from
, size
);
306 INTERCEPTOR(void*, memset
, void *block
, int c
, uptr size
) {
307 if (!asan_inited
) return internal_memset(block
, c
, size
);
308 // memset is called inside Printf.
309 if (asan_init_is_running
) {
310 return REAL(memset
)(block
, c
, size
);
312 ENSURE_ASAN_INITED();
313 if (flags()->replace_intrin
) {
314 ASAN_WRITE_RANGE(block
, size
);
316 return REAL(memset
)(block
, c
, size
);
319 INTERCEPTOR(char*, strchr
, const char *str
, int c
) {
320 if (!asan_inited
) return internal_strchr(str
, c
);
321 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
323 if (asan_init_is_running
) {
324 return REAL(strchr
)(str
, c
);
326 ENSURE_ASAN_INITED();
327 char *result
= REAL(strchr
)(str
, c
);
328 if (flags()->replace_str
) {
329 uptr bytes_read
= (result
? result
- str
: REAL(strlen
)(str
)) + 1;
330 ASAN_READ_RANGE(str
, bytes_read
);
335 #if ASAN_INTERCEPT_INDEX
336 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
337 INTERCEPTOR(char*, index
, const char *string
, int c
)
338 ALIAS(WRAPPER_NAME(strchr
));
340 DEFINE_REAL(char*, index
, const char *string
, int c
)
342 #endif // ASAN_INTERCEPT_INDEX
344 // For both strcat() and strncat() we need to check the validity of |to|
345 // argument irrespective of the |from| length.
346 INTERCEPTOR(char*, strcat
, char *to
, const char *from
) { // NOLINT
347 ENSURE_ASAN_INITED();
348 if (flags()->replace_str
) {
349 uptr from_length
= REAL(strlen
)(from
);
350 ASAN_READ_RANGE(from
, from_length
+ 1);
351 uptr to_length
= REAL(strlen
)(to
);
352 ASAN_READ_RANGE(to
, to_length
);
353 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
354 // If the copying actually happens, the |from| string should not overlap
355 // with the resulting string starting at |to|, which has a length of
356 // to_length + from_length + 1.
357 if (from_length
> 0) {
358 CHECK_RANGES_OVERLAP("strcat", to
, from_length
+ to_length
+ 1,
359 from
, from_length
+ 1);
362 return REAL(strcat
)(to
, from
); // NOLINT
365 INTERCEPTOR(char*, strncat
, char *to
, const char *from
, uptr size
) {
366 ENSURE_ASAN_INITED();
367 if (flags()->replace_str
) {
368 uptr from_length
= MaybeRealStrnlen(from
, size
);
369 uptr copy_length
= Min(size
, from_length
+ 1);
370 ASAN_READ_RANGE(from
, copy_length
);
371 uptr to_length
= REAL(strlen
)(to
);
372 ASAN_READ_RANGE(to
, to_length
);
373 ASAN_WRITE_RANGE(to
+ to_length
, from_length
+ 1);
374 if (from_length
> 0) {
375 CHECK_RANGES_OVERLAP("strncat", to
, to_length
+ copy_length
+ 1,
379 return REAL(strncat
)(to
, from
, size
);
382 INTERCEPTOR(int, strcmp
, const char *s1
, const char *s2
) {
383 if (!asan_inited
) return internal_strcmp(s1
, s2
);
384 if (asan_init_is_running
) {
385 return REAL(strcmp
)(s1
, s2
);
387 ENSURE_ASAN_INITED();
388 unsigned char c1
, c2
;
391 c1
= (unsigned char)s1
[i
];
392 c2
= (unsigned char)s2
[i
];
393 if (c1
!= c2
|| c1
== '\0') break;
395 ASAN_READ_RANGE(s1
, i
+ 1);
396 ASAN_READ_RANGE(s2
, i
+ 1);
397 return CharCmp(c1
, c2
);
400 INTERCEPTOR(char*, strcpy
, char *to
, const char *from
) { // NOLINT
401 #if MAC_INTERPOSE_FUNCTIONS
402 if (!asan_inited
) return REAL(strcpy
)(to
, from
); // NOLINT
404 // strcpy is called from malloc_default_purgeable_zone()
405 // in __asan::ReplaceSystemAlloc() on Mac.
406 if (asan_init_is_running
) {
407 return REAL(strcpy
)(to
, from
); // NOLINT
409 ENSURE_ASAN_INITED();
410 if (flags()->replace_str
) {
411 uptr from_size
= REAL(strlen
)(from
) + 1;
412 CHECK_RANGES_OVERLAP("strcpy", to
, from_size
, from
, from_size
);
413 ASAN_READ_RANGE(from
, from_size
);
414 ASAN_WRITE_RANGE(to
, from_size
);
416 return REAL(strcpy
)(to
, from
); // NOLINT
419 #if ASAN_INTERCEPT_STRDUP
420 INTERCEPTOR(char*, strdup
, const char *s
) {
421 #if MAC_INTERPOSE_FUNCTIONS
422 // FIXME: because internal_strdup() uses InternalAlloc(), which currently
423 // just calls malloc() on Mac, we can't use internal_strdup() with the
424 // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
425 // starts using mmap() instead.
426 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
427 if (!asan_inited
) return REAL(strdup
)(s
);
429 if (!asan_inited
) return internal_strdup(s
);
430 ENSURE_ASAN_INITED();
431 if (flags()->replace_str
) {
432 uptr length
= REAL(strlen
)(s
);
433 ASAN_READ_RANGE(s
, length
+ 1);
435 return REAL(strdup
)(s
);
439 INTERCEPTOR(uptr
, strlen
, const char *s
) {
440 if (!asan_inited
) return internal_strlen(s
);
441 // strlen is called from malloc_default_purgeable_zone()
442 // in __asan::ReplaceSystemAlloc() on Mac.
443 if (asan_init_is_running
) {
444 return REAL(strlen
)(s
);
446 ENSURE_ASAN_INITED();
447 uptr length
= REAL(strlen
)(s
);
448 if (flags()->replace_str
) {
449 ASAN_READ_RANGE(s
, length
+ 1);
454 #if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
455 INTERCEPTOR(int, strcasecmp
, const char *s1
, const char *s2
) {
456 ENSURE_ASAN_INITED();
457 unsigned char c1
, c2
;
460 c1
= (unsigned char)s1
[i
];
461 c2
= (unsigned char)s2
[i
];
462 if (CharCaseCmp(c1
, c2
) != 0 || c1
== '\0') break;
464 ASAN_READ_RANGE(s1
, i
+ 1);
465 ASAN_READ_RANGE(s2
, i
+ 1);
466 return CharCaseCmp(c1
, c2
);
469 INTERCEPTOR(int, strncasecmp
, const char *s1
, const char *s2
, uptr n
) {
470 ENSURE_ASAN_INITED();
471 unsigned char c1
= 0, c2
= 0;
473 for (i
= 0; i
< n
; i
++) {
474 c1
= (unsigned char)s1
[i
];
475 c2
= (unsigned char)s2
[i
];
476 if (CharCaseCmp(c1
, c2
) != 0 || c1
== '\0') break;
478 ASAN_READ_RANGE(s1
, Min(i
+ 1, n
));
479 ASAN_READ_RANGE(s2
, Min(i
+ 1, n
));
480 return CharCaseCmp(c1
, c2
);
482 #endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
484 INTERCEPTOR(int, strncmp
, const char *s1
, const char *s2
, uptr size
) {
485 if (!asan_inited
) return internal_strncmp(s1
, s2
, size
);
486 // strncmp is called from malloc_default_purgeable_zone()
487 // in __asan::ReplaceSystemAlloc() on Mac.
488 if (asan_init_is_running
) {
489 return REAL(strncmp
)(s1
, s2
, size
);
491 ENSURE_ASAN_INITED();
492 unsigned char c1
= 0, c2
= 0;
494 for (i
= 0; i
< size
; i
++) {
495 c1
= (unsigned char)s1
[i
];
496 c2
= (unsigned char)s2
[i
];
497 if (c1
!= c2
|| c1
== '\0') break;
499 ASAN_READ_RANGE(s1
, Min(i
+ 1, size
));
500 ASAN_READ_RANGE(s2
, Min(i
+ 1, size
));
501 return CharCmp(c1
, c2
);
504 INTERCEPTOR(char*, strncpy
, char *to
, const char *from
, uptr size
) {
505 ENSURE_ASAN_INITED();
506 if (flags()->replace_str
) {
507 uptr from_size
= Min(size
, MaybeRealStrnlen(from
, size
) + 1);
508 CHECK_RANGES_OVERLAP("strncpy", to
, from_size
, from
, from_size
);
509 ASAN_READ_RANGE(from
, from_size
);
510 ASAN_WRITE_RANGE(to
, size
);
512 return REAL(strncpy
)(to
, from
, size
);
515 #if ASAN_INTERCEPT_STRNLEN
516 INTERCEPTOR(uptr
, strnlen
, const char *s
, uptr maxlen
) {
517 ENSURE_ASAN_INITED();
518 uptr length
= REAL(strnlen
)(s
, maxlen
);
519 if (flags()->replace_str
) {
520 ASAN_READ_RANGE(s
, Min(length
+ 1, maxlen
));
524 #endif // ASAN_INTERCEPT_STRNLEN
526 static inline bool IsValidStrtolBase(int base
) {
527 return (base
== 0) || (2 <= base
&& base
<= 36);
530 static inline void FixRealStrtolEndptr(const char *nptr
, char **endptr
) {
532 if (nptr
== *endptr
) {
533 // No digits were found at strtol call, we need to find out the last
534 // symbol accessed by strtoll on our own.
535 // We get this symbol by skipping leading blanks and optional +/- sign.
536 while (IsSpace(*nptr
)) nptr
++;
537 if (*nptr
== '+' || *nptr
== '-') nptr
++;
538 *endptr
= (char*)nptr
;
540 CHECK(*endptr
>= nptr
);
543 INTERCEPTOR(long, strtol
, const char *nptr
, // NOLINT
544 char **endptr
, int base
) {
545 ENSURE_ASAN_INITED();
546 if (!flags()->replace_str
) {
547 return REAL(strtol
)(nptr
, endptr
, base
);
550 long result
= REAL(strtol
)(nptr
, &real_endptr
, base
); // NOLINT
552 *endptr
= real_endptr
;
554 if (IsValidStrtolBase(base
)) {
555 FixRealStrtolEndptr(nptr
, &real_endptr
);
556 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
561 INTERCEPTOR(int, atoi
, const char *nptr
) {
562 #if MAC_INTERPOSE_FUNCTIONS
563 if (!asan_inited
) return REAL(atoi
)(nptr
);
565 ENSURE_ASAN_INITED();
566 if (!flags()->replace_str
) {
567 return REAL(atoi
)(nptr
);
570 // "man atoi" tells that behavior of atoi(nptr) is the same as
571 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
572 // parsed integer can't be stored in *long* type (even if it's
573 // different from int). So, we just imitate this behavior.
574 int result
= REAL(strtol
)(nptr
, &real_endptr
, 10);
575 FixRealStrtolEndptr(nptr
, &real_endptr
);
576 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
580 INTERCEPTOR(long, atol
, const char *nptr
) { // NOLINT
581 #if MAC_INTERPOSE_FUNCTIONS
582 if (!asan_inited
) return REAL(atol
)(nptr
);
584 ENSURE_ASAN_INITED();
585 if (!flags()->replace_str
) {
586 return REAL(atol
)(nptr
);
589 long result
= REAL(strtol
)(nptr
, &real_endptr
, 10); // NOLINT
590 FixRealStrtolEndptr(nptr
, &real_endptr
);
591 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
595 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
596 INTERCEPTOR(long long, strtoll
, const char *nptr
, // NOLINT
597 char **endptr
, int base
) {
598 ENSURE_ASAN_INITED();
599 if (!flags()->replace_str
) {
600 return REAL(strtoll
)(nptr
, endptr
, base
);
603 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, base
); // NOLINT
605 *endptr
= real_endptr
;
607 // If base has unsupported value, strtoll can exit with EINVAL
608 // without reading any characters. So do additional checks only
610 if (IsValidStrtolBase(base
)) {
611 FixRealStrtolEndptr(nptr
, &real_endptr
);
612 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
617 INTERCEPTOR(long long, atoll
, const char *nptr
) { // NOLINT
618 ENSURE_ASAN_INITED();
619 if (!flags()->replace_str
) {
620 return REAL(atoll
)(nptr
);
623 long long result
= REAL(strtoll
)(nptr
, &real_endptr
, 10); // NOLINT
624 FixRealStrtolEndptr(nptr
, &real_endptr
);
625 ASAN_READ_RANGE(nptr
, (real_endptr
- nptr
) + 1);
628 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
630 #define ASAN_INTERCEPT_FUNC(name) do { \
631 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
632 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
636 INTERCEPTOR_WINAPI(DWORD
, CreateThread
,
637 void* security
, uptr stack_size
,
638 DWORD (__stdcall
*start_routine
)(void*), void* arg
,
639 DWORD flags
, void* tid
) {
640 GET_STACK_TRACE_THREAD
;
641 u32 current_tid
= asanThreadRegistry().GetCurrentTidOrInvalid();
642 AsanThread
*t
= AsanThread::Create(current_tid
, start_routine
, arg
, &stack
);
643 asanThreadRegistry().RegisterThread(t
);
644 return REAL(CreateThread
)(security
, stack_size
,
645 asan_thread_start
, t
, flags
, tid
);
649 void InitializeWindowsInterceptors() {
650 ASAN_INTERCEPT_FUNC(CreateThread
);
653 } // namespace __asan
656 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
658 void InitializeAsanInterceptors() {
659 static bool was_called_once
;
660 CHECK(was_called_once
== false);
661 was_called_once
= true;
662 #if MAC_INTERPOSE_FUNCTIONS
666 SANITIZER_COMMON_INTERCEPTORS_INIT
;
668 // Intercept mem* functions.
669 ASAN_INTERCEPT_FUNC(memcmp
);
670 ASAN_INTERCEPT_FUNC(memmove
);
671 ASAN_INTERCEPT_FUNC(memset
);
672 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
) {
673 ASAN_INTERCEPT_FUNC(memcpy
);
675 #if !MAC_INTERPOSE_FUNCTIONS
676 // If we're using dynamic interceptors on Mac, these two are just plain
678 internal_memcpy(&REAL(memcpy
), &REAL(memmove
), sizeof(REAL(memmove
)));
682 // Intercept str* functions.
683 ASAN_INTERCEPT_FUNC(strcat
); // NOLINT
684 ASAN_INTERCEPT_FUNC(strchr
);
685 ASAN_INTERCEPT_FUNC(strcmp
);
686 ASAN_INTERCEPT_FUNC(strcpy
); // NOLINT
687 ASAN_INTERCEPT_FUNC(strlen
);
688 ASAN_INTERCEPT_FUNC(strncat
);
689 ASAN_INTERCEPT_FUNC(strncmp
);
690 ASAN_INTERCEPT_FUNC(strncpy
);
691 #if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
692 ASAN_INTERCEPT_FUNC(strcasecmp
);
693 ASAN_INTERCEPT_FUNC(strncasecmp
);
695 #if ASAN_INTERCEPT_STRDUP
696 ASAN_INTERCEPT_FUNC(strdup
);
698 #if ASAN_INTERCEPT_STRNLEN
699 ASAN_INTERCEPT_FUNC(strnlen
);
701 #if ASAN_INTERCEPT_INDEX
702 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
703 ASAN_INTERCEPT_FUNC(index
);
705 CHECK(OVERRIDE_FUNCTION(index
, WRAP(strchr
)));
709 ASAN_INTERCEPT_FUNC(atoi
);
710 ASAN_INTERCEPT_FUNC(atol
);
711 ASAN_INTERCEPT_FUNC(strtol
);
712 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
713 ASAN_INTERCEPT_FUNC(atoll
);
714 ASAN_INTERCEPT_FUNC(strtoll
);
717 #if ASAN_INTERCEPT_MLOCKX
718 // Intercept mlock/munlock.
719 ASAN_INTERCEPT_FUNC(mlock
);
720 ASAN_INTERCEPT_FUNC(munlock
);
721 ASAN_INTERCEPT_FUNC(mlockall
);
722 ASAN_INTERCEPT_FUNC(munlockall
);
725 // Intecept signal- and jump-related functions.
726 ASAN_INTERCEPT_FUNC(longjmp
);
727 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
728 ASAN_INTERCEPT_FUNC(sigaction
);
729 ASAN_INTERCEPT_FUNC(signal
);
731 #if ASAN_INTERCEPT_SWAPCONTEXT
732 ASAN_INTERCEPT_FUNC(swapcontext
);
734 #if ASAN_INTERCEPT__LONGJMP
735 ASAN_INTERCEPT_FUNC(_longjmp
);
737 #if ASAN_INTERCEPT_SIGLONGJMP
738 ASAN_INTERCEPT_FUNC(siglongjmp
);
741 // Intercept exception handling functions.
742 #if ASAN_INTERCEPT___CXA_THROW
743 INTERCEPT_FUNCTION(__cxa_throw
);
746 // Intercept threading-related functions
747 #if ASAN_INTERCEPT_PTHREAD_CREATE
748 ASAN_INTERCEPT_FUNC(pthread_create
);
751 // Some Windows-specific interceptors.
753 InitializeWindowsInterceptors();
756 // Some Mac-specific interceptors.
757 #if defined(__APPLE__)
758 InitializeMacInterceptors();
761 if (flags()->verbosity
> 0) {
762 Report("AddressSanitizer: libc interceptors initialized\n");
766 } // namespace __asan