2013-02-04 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libsanitizer / asan / asan_interceptors.cc
blob98329f38e61b7ec7ce28ca744fbaeb42b17f9310
1 //===-- asan_interceptors.cc ----------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of AddressSanitizer, an address sanity checker.
9 //
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"
26 namespace __asan {
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); \
37 } \
38 } while (0)
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); \
57 } \
58 } while (0)
60 #define ENSURE_ASAN_INITED() do { \
61 CHECK(!asan_init_is_running); \
62 if (!asan_inited) { \
63 __asan_init(); \
64 } \
65 } while (0)
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);
72 #endif
73 return internal_strnlen(s, maxlen);
76 void SetThreadName(const char *name) {
77 AsanThread *t = asanThreadRegistry().GetCurrent();
78 if (t)
79 t->summary()->set_name(name);
82 } // namespace __asan
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, ...) \
91 do { \
92 ctx = 0; \
93 (void)ctx; \
94 ENSURE_ASAN_INITED(); \
95 } while (false)
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);
123 return 0;
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);
131 return 0;
133 #elif ASAN_POSIX
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).
162 uptr stack, ssize;
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
169 // state.
170 ClearShadowMemoryForContextStack(stack, ssize);
171 return res;
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);
185 #endif
187 #if ASAN_INTERCEPT_SIGLONGJMP
188 INTERCEPTOR(void, siglongjmp, void *env, int val) {
189 __asan_handle_no_return();
190 REAL(siglongjmp)(env, val);
192 #endif
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);
200 #endif
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;
207 if (printed) return;
208 printed = true;
209 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
212 extern "C" {
213 INTERCEPTOR(int, mlock, const void *addr, uptr len) {
214 MlockIsUnsupported();
215 return 0;
218 INTERCEPTOR(int, munlock, const void *addr, uptr len) {
219 MlockIsUnsupported();
220 return 0;
223 INTERCEPTOR(int, mlockall, int flags) {
224 MlockIsUnsupported();
225 return 0;
228 INTERCEPTOR(int, munlockall, void) {
229 MlockIsUnsupported();
230 return 0;
232 } // extern "C"
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;
250 uptr i;
251 for (i = 0; i < size; i++) {
252 c1 = s1[i];
253 c2 = s2[i];
254 if (c1 != c2) break;
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
264 // of printf(...).
265 if (asan_init_is_running) {
266 return REAL(memcpy)(to, from, size);
268 ENSURE_ASAN_INITED();
269 if (flags()->replace_intrin) {
270 if (to != from) {
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);
282 #else
283 return REAL(memcpy)(to, from, size);
284 #endif
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);
301 #else
302 return REAL(memmove)(to, from, size);
303 #endif
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
322 // used.
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);
332 return result;
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));
339 # else
340 DEFINE_REAL(char*, index, const char *string, int c)
341 # endif
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,
376 from, copy_length);
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;
389 uptr i;
390 for (i = 0; ; i++) {
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
403 #endif
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);
428 #endif
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);
437 #endif
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);
451 return length;
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;
458 uptr i;
459 for (i = 0; ; i++) {
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;
472 uptr i;
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;
493 uptr i;
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));
522 return length;
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) {
531 CHECK(endptr != 0);
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);
549 char *real_endptr;
550 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
551 if (endptr != 0) {
552 *endptr = real_endptr;
554 if (IsValidStrtolBase(base)) {
555 FixRealStrtolEndptr(nptr, &real_endptr);
556 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
558 return result;
561 INTERCEPTOR(int, atoi, const char *nptr) {
562 #if MAC_INTERPOSE_FUNCTIONS
563 if (!asan_inited) return REAL(atoi)(nptr);
564 #endif
565 ENSURE_ASAN_INITED();
566 if (!flags()->replace_str) {
567 return REAL(atoi)(nptr);
569 char *real_endptr;
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);
577 return result;
580 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
581 #if MAC_INTERPOSE_FUNCTIONS
582 if (!asan_inited) return REAL(atol)(nptr);
583 #endif
584 ENSURE_ASAN_INITED();
585 if (!flags()->replace_str) {
586 return REAL(atol)(nptr);
588 char *real_endptr;
589 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
590 FixRealStrtolEndptr(nptr, &real_endptr);
591 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
592 return result;
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);
602 char *real_endptr;
603 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
604 if (endptr != 0) {
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
609 // if base is valid.
610 if (IsValidStrtolBase(base)) {
611 FixRealStrtolEndptr(nptr, &real_endptr);
612 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
614 return result;
617 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
618 ENSURE_ASAN_INITED();
619 if (!flags()->replace_str) {
620 return REAL(atoll)(nptr);
622 char *real_endptr;
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);
626 return result;
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"); \
633 } while (0)
635 #if defined(_WIN32)
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);
648 namespace __asan {
649 void InitializeWindowsInterceptors() {
650 ASAN_INTERCEPT_FUNC(CreateThread);
653 } // namespace __asan
654 #endif
656 // ---------------------- InitializeAsanInterceptors ---------------- {{{1
657 namespace __asan {
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
663 return;
664 #endif
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);
674 } else {
675 #if !MAC_INTERPOSE_FUNCTIONS
676 // If we're using dynamic interceptors on Mac, these two are just plain
677 // functions.
678 internal_memcpy(&REAL(memcpy), &REAL(memmove), sizeof(REAL(memmove)));
679 #endif
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);
694 #endif
695 #if ASAN_INTERCEPT_STRDUP
696 ASAN_INTERCEPT_FUNC(strdup);
697 #endif
698 #if ASAN_INTERCEPT_STRNLEN
699 ASAN_INTERCEPT_FUNC(strnlen);
700 #endif
701 #if ASAN_INTERCEPT_INDEX
702 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
703 ASAN_INTERCEPT_FUNC(index);
704 # else
705 CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
706 # endif
707 #endif
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);
715 #endif
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);
723 #endif
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);
730 #endif
731 #if ASAN_INTERCEPT_SWAPCONTEXT
732 ASAN_INTERCEPT_FUNC(swapcontext);
733 #endif
734 #if ASAN_INTERCEPT__LONGJMP
735 ASAN_INTERCEPT_FUNC(_longjmp);
736 #endif
737 #if ASAN_INTERCEPT_SIGLONGJMP
738 ASAN_INTERCEPT_FUNC(siglongjmp);
739 #endif
741 // Intercept exception handling functions.
742 #if ASAN_INTERCEPT___CXA_THROW
743 INTERCEPT_FUNCTION(__cxa_throw);
744 #endif
746 // Intercept threading-related functions
747 #if ASAN_INTERCEPT_PTHREAD_CREATE
748 ASAN_INTERCEPT_FUNC(pthread_create);
749 #endif
751 // Some Windows-specific interceptors.
752 #if defined(_WIN32)
753 InitializeWindowsInterceptors();
754 #endif
756 // Some Mac-specific interceptors.
757 #if defined(__APPLE__)
758 InitializeMacInterceptors();
759 #endif
761 if (flags()->verbosity > 0) {
762 Report("AddressSanitizer: libc interceptors initialized\n");
766 } // namespace __asan