asan_interceptors.cc revision d4d7040ee026ab04502c42327ed5081f704a8e3c
1//===-- asan_interceptors.cc ----------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of AddressSanitizer, an address sanity checker. 11// 12// Intercept various libc functions. 13//===----------------------------------------------------------------------===// 14#include "asan_interceptors.h" 15 16#include "asan_allocator.h" 17#include "asan_intercepted_functions.h" 18#include "asan_internal.h" 19#include "asan_mapping.h" 20#include "asan_poisoning.h" 21#include "asan_report.h" 22#include "asan_stack.h" 23#include "asan_stats.h" 24#include "interception/interception.h" 25#include "sanitizer_common/sanitizer_libc.h" 26 27namespace __asan { 28 29// Return true if we can quickly decide that the region is unpoisoned. 30static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { 31 if (size == 0) return true; 32 if (size <= 32) 33 return !AddressIsPoisoned(beg) && 34 !AddressIsPoisoned(beg + size - 1) && 35 !AddressIsPoisoned(beg + size / 2); 36 return false; 37} 38 39// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 40// and ASAN_WRITE_RANGE as macro instead of function so 41// that no extra frames are created, and stack trace contains 42// relevant information only. 43// We check all shadow bytes. 44#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 45 uptr __offset = (uptr)(offset); \ 46 uptr __size = (uptr)(size); \ 47 uptr __bad = 0; \ 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); \ 52 } \ 53 } while (0) 54 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) 57 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. 61static inline bool RangesOverlap(const char *offset1, uptr length1, 62 const char *offset2, uptr length2) { 63 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 64} 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); \ 72 } \ 73} while (0) 74 75#define ENSURE_ASAN_INITED() do { \ 76 CHECK(!asan_init_is_running); \ 77 if (!asan_inited) { \ 78 __asan_init(); \ 79 } \ 80} while (0) 81 82static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 83#if ASAN_INTERCEPT_STRNLEN 84 if (REAL(strnlen) != 0) { 85 return REAL(strnlen)(s, maxlen); 86 } 87#endif 88 return internal_strnlen(s, maxlen); 89} 90 91void SetThreadName(const char *name) { 92 AsanThread *t = GetCurrentThread(); 93 if (t) 94 asanThreadRegistry().SetThreadName(t->tid(), name); 95} 96 97} // namespace __asan 98 99// ---------------------- Wrappers ---------------- {{{1 100using namespace __asan; // NOLINT 101 102DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 103DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) 104 105#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ 106 do { \ 107 } while (false) 108#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 109 ASAN_WRITE_RANGE(ptr, size) 110#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 111#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 112 do { \ 113 if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \ 114 ctx = 0; \ 115 (void) ctx; \ 116 ENSURE_ASAN_INITED(); \ 117 } while (false) 118#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 119 do { \ 120 } while (false) 121#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 122 do { \ 123 } while (false) 124#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 125 do { \ 126 } while (false) 127#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 128#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 129#include "sanitizer_common/sanitizer_common_interceptors.inc" 130 131#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s) 132#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s) 133#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 134 do { \ 135 } while (false) 136#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 137 do { \ 138 } while (false) 139#include "sanitizer_common/sanitizer_common_syscalls.inc" 140 141static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 142 AsanThread *t = (AsanThread*)arg; 143 SetCurrentThread(t); 144 return t->ThreadStart(GetTid()); 145} 146 147#if ASAN_INTERCEPT_PTHREAD_CREATE 148extern "C" int pthread_attr_getdetachstate(void *attr, int *v); 149 150INTERCEPTOR(int, pthread_create, void *thread, 151 void *attr, void *(*start_routine)(void*), void *arg) { 152 EnsureMainThreadIDIsCorrect(); 153 // Strict init-order checking in thread-hostile. 154 if (flags()->strict_init_order) 155 StopInitOrderChecking(); 156 GET_STACK_TRACE_THREAD; 157 int detached = 0; 158 if (attr != 0) 159 pthread_attr_getdetachstate(attr, &detached); 160 161 u32 current_tid = GetCurrentTidOrInvalid(); 162 AsanThread *t = AsanThread::Create(start_routine, arg); 163 CreateThreadContextArgs args = { t, &stack }; 164 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 165 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 166} 167#endif // ASAN_INTERCEPT_PTHREAD_CREATE 168 169#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 170INTERCEPTOR(void*, signal, int signum, void *handler) { 171 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 172 return REAL(signal)(signum, handler); 173 } 174 return 0; 175} 176 177INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 178 struct sigaction *oldact) { 179 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 180 return REAL(sigaction)(signum, act, oldact); 181 } 182 return 0; 183} 184#elif SANITIZER_POSIX 185// We need to have defined REAL(sigaction) on posix systems. 186DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 187 struct sigaction *oldact) 188#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 189 190#if ASAN_INTERCEPT_SWAPCONTEXT 191static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 192 // Align to page size. 193 uptr PageSize = GetPageSizeCached(); 194 uptr bottom = stack & ~(PageSize - 1); 195 ssize += stack - bottom; 196 ssize = RoundUpTo(ssize, PageSize); 197 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 198 if (ssize && ssize <= kMaxSaneContextStackSize) { 199 PoisonShadow(bottom, ssize, 0); 200 } 201} 202 203INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 204 struct ucontext_t *ucp) { 205 static bool reported_warning = false; 206 if (!reported_warning) { 207 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 208 "functions and may produce false positives in some cases!\n"); 209 reported_warning = true; 210 } 211 // Clear shadow memory for new context (it may share stack 212 // with current context). 213 uptr stack, ssize; 214 ReadContextStack(ucp, &stack, &ssize); 215 ClearShadowMemoryForContextStack(stack, ssize); 216 int res = REAL(swapcontext)(oucp, ucp); 217 // swapcontext technically does not return, but program may swap context to 218 // "oucp" later, that would look as if swapcontext() returned 0. 219 // We need to clear shadow for ucp once again, as it may be in arbitrary 220 // state. 221 ClearShadowMemoryForContextStack(stack, ssize); 222 return res; 223} 224#endif // ASAN_INTERCEPT_SWAPCONTEXT 225 226INTERCEPTOR(void, longjmp, void *env, int val) { 227 __asan_handle_no_return(); 228 REAL(longjmp)(env, val); 229} 230 231#if ASAN_INTERCEPT__LONGJMP 232INTERCEPTOR(void, _longjmp, void *env, int val) { 233 __asan_handle_no_return(); 234 REAL(_longjmp)(env, val); 235} 236#endif 237 238#if ASAN_INTERCEPT_SIGLONGJMP 239INTERCEPTOR(void, siglongjmp, void *env, int val) { 240 __asan_handle_no_return(); 241 REAL(siglongjmp)(env, val); 242} 243#endif 244 245#if ASAN_INTERCEPT___CXA_THROW 246INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 247 CHECK(REAL(__cxa_throw)); 248 __asan_handle_no_return(); 249 REAL(__cxa_throw)(a, b, c); 250} 251#endif 252 253// intercept mlock and friends. 254// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 255// All functions return 0 (success). 256static void MlockIsUnsupported() { 257 static bool printed = false; 258 if (printed) return; 259 printed = true; 260 if (flags()->verbosity > 0) { 261 Printf("INFO: AddressSanitizer ignores " 262 "mlock/mlockall/munlock/munlockall\n"); 263 } 264} 265 266INTERCEPTOR(int, mlock, const void *addr, uptr len) { 267 MlockIsUnsupported(); 268 return 0; 269} 270 271INTERCEPTOR(int, munlock, const void *addr, uptr len) { 272 MlockIsUnsupported(); 273 return 0; 274} 275 276INTERCEPTOR(int, mlockall, int flags) { 277 MlockIsUnsupported(); 278 return 0; 279} 280 281INTERCEPTOR(int, munlockall, void) { 282 MlockIsUnsupported(); 283 return 0; 284} 285 286static inline int CharCmp(unsigned char c1, unsigned char c2) { 287 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 288} 289 290INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 291 if (!asan_inited) return internal_memcmp(a1, a2, size); 292 ENSURE_ASAN_INITED(); 293 if (flags()->replace_intrin) { 294 if (flags()->strict_memcmp) { 295 // Check the entire regions even if the first bytes of the buffers are 296 // different. 297 ASAN_READ_RANGE(a1, size); 298 ASAN_READ_RANGE(a2, size); 299 // Fallthrough to REAL(memcmp) below. 300 } else { 301 unsigned char c1 = 0, c2 = 0; 302 const unsigned char *s1 = (const unsigned char*)a1; 303 const unsigned char *s2 = (const unsigned char*)a2; 304 uptr i; 305 for (i = 0; i < size; i++) { 306 c1 = s1[i]; 307 c2 = s2[i]; 308 if (c1 != c2) break; 309 } 310 ASAN_READ_RANGE(s1, Min(i + 1, size)); 311 ASAN_READ_RANGE(s2, Min(i + 1, size)); 312 return CharCmp(c1, c2); 313 } 314 } 315 return REAL(memcmp(a1, a2, size)); 316} 317 318#define MEMMOVE_BODY { \ 319 if (!asan_inited) return internal_memmove(to, from, size); \ 320 if (asan_init_is_running) { \ 321 return REAL(memmove)(to, from, size); \ 322 } \ 323 ENSURE_ASAN_INITED(); \ 324 if (flags()->replace_intrin) { \ 325 ASAN_READ_RANGE(from, size); \ 326 ASAN_WRITE_RANGE(to, size); \ 327 } \ 328 /* Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. \ 329 See also \ 330 http://code.google.com/p/address-sanitizer/issues/detail?id=116. */ \ 331 return internal_memmove(to, from, size); \ 332} 333 334INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) MEMMOVE_BODY 335 336INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 337#if !SANITIZER_MAC 338 if (!asan_inited) return internal_memcpy(to, from, size); 339 // memcpy is called during __asan_init() from the internals 340 // of printf(...). 341 if (asan_init_is_running) { 342 return REAL(memcpy)(to, from, size); 343 } 344 ENSURE_ASAN_INITED(); 345 if (flags()->replace_intrin) { 346 if (to != from) { 347 // We do not treat memcpy with to==from as a bug. 348 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 349 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 350 } 351 ASAN_READ_RANGE(from, size); 352 ASAN_WRITE_RANGE(to, size); 353 } 354 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8, so 355 // calling REAL(memcpy) here leads to infinite recursion. 356 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 357 return internal_memcpy(to, from, size); 358#else 359 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced 360 // with WRAP(memcpy). As a result, false positives are reported for memmove() 361 // calls. If we just disable error reporting with 362 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with 363 // internal_memcpy(), which may lead to crashes, see 364 // http://llvm.org/bugs/show_bug.cgi?id=16362. 365 MEMMOVE_BODY 366#endif // !SANITIZER_MAC 367} 368 369INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 370 if (!asan_inited) return internal_memset(block, c, size); 371 // memset is called inside Printf. 372 if (asan_init_is_running) { 373 return REAL(memset)(block, c, size); 374 } 375 ENSURE_ASAN_INITED(); 376 if (flags()->replace_intrin) { 377 ASAN_WRITE_RANGE(block, size); 378 } 379 return REAL(memset)(block, c, size); 380} 381 382INTERCEPTOR(char*, strchr, const char *str, int c) { 383 if (!asan_inited) return internal_strchr(str, c); 384 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 385 // used. 386 if (asan_init_is_running) { 387 return REAL(strchr)(str, c); 388 } 389 ENSURE_ASAN_INITED(); 390 char *result = REAL(strchr)(str, c); 391 if (flags()->replace_str) { 392 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 393 ASAN_READ_RANGE(str, bytes_read); 394 } 395 return result; 396} 397 398#if ASAN_INTERCEPT_INDEX 399# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 400INTERCEPTOR(char*, index, const char *string, int c) 401 ALIAS(WRAPPER_NAME(strchr)); 402# else 403# if SANITIZER_MAC 404DECLARE_REAL(char*, index, const char *string, int c) 405OVERRIDE_FUNCTION(index, strchr); 406# else 407DEFINE_REAL(char*, index, const char *string, int c) 408# endif 409# endif 410#endif // ASAN_INTERCEPT_INDEX 411 412// For both strcat() and strncat() we need to check the validity of |to| 413// argument irrespective of the |from| length. 414INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 415 ENSURE_ASAN_INITED(); 416 if (flags()->replace_str) { 417 uptr from_length = REAL(strlen)(from); 418 ASAN_READ_RANGE(from, from_length + 1); 419 uptr to_length = REAL(strlen)(to); 420 ASAN_READ_RANGE(to, to_length); 421 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 422 // If the copying actually happens, the |from| string should not overlap 423 // with the resulting string starting at |to|, which has a length of 424 // to_length + from_length + 1. 425 if (from_length > 0) { 426 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 427 from, from_length + 1); 428 } 429 } 430 return REAL(strcat)(to, from); // NOLINT 431} 432 433INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 434 ENSURE_ASAN_INITED(); 435 if (flags()->replace_str) { 436 uptr from_length = MaybeRealStrnlen(from, size); 437 uptr copy_length = Min(size, from_length + 1); 438 ASAN_READ_RANGE(from, copy_length); 439 uptr to_length = REAL(strlen)(to); 440 ASAN_READ_RANGE(to, to_length); 441 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 442 if (from_length > 0) { 443 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 444 from, copy_length); 445 } 446 } 447 return REAL(strncat)(to, from, size); 448} 449 450INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 451#if SANITIZER_MAC 452 if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 453#endif 454 // strcpy is called from malloc_default_purgeable_zone() 455 // in __asan::ReplaceSystemAlloc() on Mac. 456 if (asan_init_is_running) { 457 return REAL(strcpy)(to, from); // NOLINT 458 } 459 ENSURE_ASAN_INITED(); 460 if (flags()->replace_str) { 461 uptr from_size = REAL(strlen)(from) + 1; 462 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 463 ASAN_READ_RANGE(from, from_size); 464 ASAN_WRITE_RANGE(to, from_size); 465 } 466 return REAL(strcpy)(to, from); // NOLINT 467} 468 469#if ASAN_INTERCEPT_STRDUP 470INTERCEPTOR(char*, strdup, const char *s) { 471 if (!asan_inited) return internal_strdup(s); 472 ENSURE_ASAN_INITED(); 473 uptr length = REAL(strlen)(s); 474 if (flags()->replace_str) { 475 ASAN_READ_RANGE(s, length + 1); 476 } 477 GET_STACK_TRACE_MALLOC; 478 void *new_mem = asan_malloc(length + 1, &stack); 479 REAL(memcpy)(new_mem, s, length + 1); 480 return reinterpret_cast<char*>(new_mem); 481} 482#endif 483 484INTERCEPTOR(uptr, strlen, const char *s) { 485 if (!asan_inited) return internal_strlen(s); 486 // strlen is called from malloc_default_purgeable_zone() 487 // in __asan::ReplaceSystemAlloc() on Mac. 488 if (asan_init_is_running) { 489 return REAL(strlen)(s); 490 } 491 ENSURE_ASAN_INITED(); 492 uptr length = REAL(strlen)(s); 493 if (flags()->replace_str) { 494 ASAN_READ_RANGE(s, length + 1); 495 } 496 return length; 497} 498 499INTERCEPTOR(uptr, wcslen, const wchar_t *s) { 500 uptr length = REAL(wcslen)(s); 501 if (!asan_init_is_running) { 502 ENSURE_ASAN_INITED(); 503 ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t)); 504 } 505 return length; 506} 507 508INTERCEPTOR(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); 515 } 516 return REAL(strncpy)(to, from, size); 517} 518 519#if ASAN_INTERCEPT_STRNLEN 520INTERCEPTOR(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)); 525 } 526 return length; 527} 528#endif // ASAN_INTERCEPT_STRNLEN 529 530static inline bool IsValidStrtolBase(int base) { 531 return (base == 0) || (2 <= base && base <= 36); 532} 533 534static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 535 CHECK(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; 543 } 544 CHECK(*endptr >= nptr); 545} 546 547INTERCEPTOR(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); 552 } 553 char *real_endptr; 554 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 555 if (endptr != 0) { 556 *endptr = real_endptr; 557 } 558 if (IsValidStrtolBase(base)) { 559 FixRealStrtolEndptr(nptr, &real_endptr); 560 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 561 } 562 return result; 563} 564 565INTERCEPTOR(int, atoi, const char *nptr) { 566#if SANITIZER_MAC 567 if (!asan_inited) return REAL(atoi)(nptr); 568#endif 569 ENSURE_ASAN_INITED(); 570 if (!flags()->replace_str) { 571 return REAL(atoi)(nptr); 572 } 573 char *real_endptr; 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); 581 return result; 582} 583 584INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 585#if SANITIZER_MAC 586 if (!asan_inited) return REAL(atol)(nptr); 587#endif 588 ENSURE_ASAN_INITED(); 589 if (!flags()->replace_str) { 590 return REAL(atol)(nptr); 591 } 592 char *real_endptr; 593 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 594 FixRealStrtolEndptr(nptr, &real_endptr); 595 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 596 return result; 597} 598 599#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 600INTERCEPTOR(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); 605 } 606 char *real_endptr; 607 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 608 if (endptr != 0) { 609 *endptr = real_endptr; 610 } 611 // If base has unsupported value, strtoll can exit with EINVAL 612 // without reading any characters. So do additional checks only 613 // if base is valid. 614 if (IsValidStrtolBase(base)) { 615 FixRealStrtolEndptr(nptr, &real_endptr); 616 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 617 } 618 return result; 619} 620 621INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 622 ENSURE_ASAN_INITED(); 623 if (!flags()->replace_str) { 624 return REAL(atoll)(nptr); 625 } 626 char *real_endptr; 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); 630 return result; 631} 632#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 633 634static void AtCxaAtexit(void *unused) { 635 (void)unused; 636 StopInitOrderChecking(); 637} 638 639#if ASAN_INTERCEPT___CXA_ATEXIT 640INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 641 void *dso_handle) { 642 ENSURE_ASAN_INITED(); 643 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 644 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0); 645 return res; 646} 647#endif // ASAN_INTERCEPT___CXA_ATEXIT 648 649#if !SANITIZER_MAC 650#define ASAN_INTERCEPT_FUNC(name) do { \ 651 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 652 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 653 } while (0) 654#else 655// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. 656#define ASAN_INTERCEPT_FUNC(name) 657#endif // SANITIZER_MAC 658 659#if SANITIZER_WINDOWS 660INTERCEPTOR_WINAPI(DWORD, CreateThread, 661 void* security, uptr stack_size, 662 DWORD (__stdcall *start_routine)(void*), void* arg, 663 DWORD thr_flags, void* tid) { 664 // Strict init-order checking in thread-hostile. 665 if (flags()->strict_init_order) 666 StopInitOrderChecking(); 667 GET_STACK_TRACE_THREAD; 668 u32 current_tid = GetCurrentTidOrInvalid(); 669 AsanThread *t = AsanThread::Create(start_routine, arg); 670 CreateThreadContextArgs args = { t, &stack }; 671 bool detached = false; // FIXME: how can we determine it on Windows? 672 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 673 return REAL(CreateThread)(security, stack_size, 674 asan_thread_start, t, thr_flags, tid); 675} 676 677namespace __asan { 678void InitializeWindowsInterceptors() { 679 ASAN_INTERCEPT_FUNC(CreateThread); 680} 681 682} // namespace __asan 683#endif 684 685// ---------------------- InitializeAsanInterceptors ---------------- {{{1 686namespace __asan { 687void InitializeAsanInterceptors() { 688 static bool was_called_once; 689 CHECK(was_called_once == false); 690 was_called_once = true; 691 SANITIZER_COMMON_INTERCEPTORS_INIT; 692 693 // Intercept mem* functions. 694 ASAN_INTERCEPT_FUNC(memcmp); 695 ASAN_INTERCEPT_FUNC(memmove); 696 ASAN_INTERCEPT_FUNC(memset); 697 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 698 ASAN_INTERCEPT_FUNC(memcpy); 699 } 700 701 // Intercept str* functions. 702 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 703 ASAN_INTERCEPT_FUNC(strchr); 704 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 705 ASAN_INTERCEPT_FUNC(strlen); 706 ASAN_INTERCEPT_FUNC(wcslen); 707 ASAN_INTERCEPT_FUNC(strncat); 708 ASAN_INTERCEPT_FUNC(strncpy); 709#if ASAN_INTERCEPT_STRDUP 710 ASAN_INTERCEPT_FUNC(strdup); 711#endif 712#if ASAN_INTERCEPT_STRNLEN 713 ASAN_INTERCEPT_FUNC(strnlen); 714#endif 715#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 716 ASAN_INTERCEPT_FUNC(index); 717#endif 718 719 ASAN_INTERCEPT_FUNC(atoi); 720 ASAN_INTERCEPT_FUNC(atol); 721 ASAN_INTERCEPT_FUNC(strtol); 722#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 723 ASAN_INTERCEPT_FUNC(atoll); 724 ASAN_INTERCEPT_FUNC(strtoll); 725#endif 726 727#if ASAN_INTERCEPT_MLOCKX 728 // Intercept mlock/munlock. 729 ASAN_INTERCEPT_FUNC(mlock); 730 ASAN_INTERCEPT_FUNC(munlock); 731 ASAN_INTERCEPT_FUNC(mlockall); 732 ASAN_INTERCEPT_FUNC(munlockall); 733#endif 734 735 // Intecept signal- and jump-related functions. 736 ASAN_INTERCEPT_FUNC(longjmp); 737#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 738 ASAN_INTERCEPT_FUNC(sigaction); 739 ASAN_INTERCEPT_FUNC(signal); 740#endif 741#if ASAN_INTERCEPT_SWAPCONTEXT 742 ASAN_INTERCEPT_FUNC(swapcontext); 743#endif 744#if ASAN_INTERCEPT__LONGJMP 745 ASAN_INTERCEPT_FUNC(_longjmp); 746#endif 747#if ASAN_INTERCEPT_SIGLONGJMP 748 ASAN_INTERCEPT_FUNC(siglongjmp); 749#endif 750 751 // Intercept exception handling functions. 752#if ASAN_INTERCEPT___CXA_THROW 753 INTERCEPT_FUNCTION(__cxa_throw); 754#endif 755 756 // Intercept threading-related functions 757#if ASAN_INTERCEPT_PTHREAD_CREATE 758 ASAN_INTERCEPT_FUNC(pthread_create); 759#endif 760 761 // Intercept atexit function. 762#if ASAN_INTERCEPT___CXA_ATEXIT 763 ASAN_INTERCEPT_FUNC(__cxa_atexit); 764#endif 765 766 // Some Windows-specific interceptors. 767#if SANITIZER_WINDOWS 768 InitializeWindowsInterceptors(); 769#endif 770 771 if (flags()->verbosity > 0) { 772 Report("AddressSanitizer: libc interceptors initialized\n"); 773 } 774} 775 776} // namespace __asan 777