asan_interceptors.cc revision bdd0966deb04068ea94cf416c7fb46516013bd26
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 97static void DisableStrictInitOrderChecker() { 98 if (flags()->strict_init_order) 99 flags()->check_initialization_order = false; 100} 101 102} // namespace __asan 103 104// ---------------------- Wrappers ---------------- {{{1 105using namespace __asan; // NOLINT 106 107#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 108 ASAN_WRITE_RANGE(ptr, size) 109#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 110#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 111 do { \ 112 if (asan_init_is_running) \ 113 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) do { } while (false) 119#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false) 120#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 121#include "sanitizer_common/sanitizer_common_interceptors.inc" 122 123#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s) 124#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s) 125#define COMMON_SYSCALL_POST_READ_RANGE(p, s) 126#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) 127#include "sanitizer_common/sanitizer_common_syscalls.inc" 128 129static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 130 AsanThread *t = (AsanThread*)arg; 131 SetCurrentThread(t); 132 return t->ThreadStart(GetTid()); 133} 134 135#if ASAN_INTERCEPT_PTHREAD_CREATE 136extern "C" int pthread_attr_getdetachstate(void *attr, int *v); 137 138INTERCEPTOR(int, pthread_create, void *thread, 139 void *attr, void *(*start_routine)(void*), void *arg) { 140 // Strict init-order checking in thread-hostile. 141 DisableStrictInitOrderChecker(); 142 GET_STACK_TRACE_THREAD; 143 int detached = 0; 144 if (attr != 0) 145 pthread_attr_getdetachstate(attr, &detached); 146 147 u32 current_tid = GetCurrentTidOrInvalid(); 148 AsanThread *t = AsanThread::Create(start_routine, arg); 149 CreateThreadContextArgs args = { t, &stack }; 150 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 151 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 152} 153#endif // ASAN_INTERCEPT_PTHREAD_CREATE 154 155#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 156INTERCEPTOR(void*, signal, int signum, void *handler) { 157 if (!AsanInterceptsSignal(signum)) { 158 return REAL(signal)(signum, handler); 159 } 160 return 0; 161} 162 163INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 164 struct sigaction *oldact) { 165 if (!AsanInterceptsSignal(signum)) { 166 return REAL(sigaction)(signum, act, oldact); 167 } 168 return 0; 169} 170#elif SANITIZER_POSIX 171// We need to have defined REAL(sigaction) on posix systems. 172DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 173 struct sigaction *oldact); 174#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 175 176#if ASAN_INTERCEPT_SWAPCONTEXT 177static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 178 // Align to page size. 179 uptr PageSize = GetPageSizeCached(); 180 uptr bottom = stack & ~(PageSize - 1); 181 ssize += stack - bottom; 182 ssize = RoundUpTo(ssize, PageSize); 183 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 184 if (ssize && ssize <= kMaxSaneContextStackSize) { 185 PoisonShadow(bottom, ssize, 0); 186 } 187} 188 189INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 190 struct ucontext_t *ucp) { 191 static bool reported_warning = false; 192 if (!reported_warning) { 193 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 194 "functions and may produce false positives in some cases!\n"); 195 reported_warning = true; 196 } 197 // Clear shadow memory for new context (it may share stack 198 // with current context). 199 uptr stack, ssize; 200 ReadContextStack(ucp, &stack, &ssize); 201 ClearShadowMemoryForContextStack(stack, ssize); 202 int res = REAL(swapcontext)(oucp, ucp); 203 // swapcontext technically does not return, but program may swap context to 204 // "oucp" later, that would look as if swapcontext() returned 0. 205 // We need to clear shadow for ucp once again, as it may be in arbitrary 206 // state. 207 ClearShadowMemoryForContextStack(stack, ssize); 208 return res; 209} 210#endif // ASAN_INTERCEPT_SWAPCONTEXT 211 212INTERCEPTOR(void, longjmp, void *env, int val) { 213 __asan_handle_no_return(); 214 REAL(longjmp)(env, val); 215} 216 217#if ASAN_INTERCEPT__LONGJMP 218INTERCEPTOR(void, _longjmp, void *env, int val) { 219 __asan_handle_no_return(); 220 REAL(_longjmp)(env, val); 221} 222#endif 223 224#if ASAN_INTERCEPT_SIGLONGJMP 225INTERCEPTOR(void, siglongjmp, void *env, int val) { 226 __asan_handle_no_return(); 227 REAL(siglongjmp)(env, val); 228} 229#endif 230 231#if ASAN_INTERCEPT___CXA_THROW 232INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 233 CHECK(REAL(__cxa_throw)); 234 __asan_handle_no_return(); 235 REAL(__cxa_throw)(a, b, c); 236} 237#endif 238 239// intercept mlock and friends. 240// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 241// All functions return 0 (success). 242static void MlockIsUnsupported() { 243 static bool printed = 0; 244 if (printed) return; 245 printed = true; 246 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 247} 248 249extern "C" { 250INTERCEPTOR(int, mlock, const void *addr, uptr len) { 251 MlockIsUnsupported(); 252 return 0; 253} 254 255INTERCEPTOR(int, munlock, const void *addr, uptr len) { 256 MlockIsUnsupported(); 257 return 0; 258} 259 260INTERCEPTOR(int, mlockall, int flags) { 261 MlockIsUnsupported(); 262 return 0; 263} 264 265INTERCEPTOR(int, munlockall, void) { 266 MlockIsUnsupported(); 267 return 0; 268} 269} // extern "C" 270 271static inline int CharCmp(unsigned char c1, unsigned char c2) { 272 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 273} 274 275INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 276 if (!asan_inited) return internal_memcmp(a1, a2, size); 277 ENSURE_ASAN_INITED(); 278 if (flags()->replace_intrin) { 279 if (flags()->strict_memcmp) { 280 // Check the entire regions even if the first bytes of the buffers are 281 // different. 282 ASAN_READ_RANGE(a1, size); 283 ASAN_READ_RANGE(a2, size); 284 // Fallthrough to REAL(memcmp) below. 285 } else { 286 unsigned char c1 = 0, c2 = 0; 287 const unsigned char *s1 = (const unsigned char*)a1; 288 const unsigned char *s2 = (const unsigned char*)a2; 289 uptr i; 290 for (i = 0; i < size; i++) { 291 c1 = s1[i]; 292 c2 = s2[i]; 293 if (c1 != c2) break; 294 } 295 ASAN_READ_RANGE(s1, Min(i + 1, size)); 296 ASAN_READ_RANGE(s2, Min(i + 1, size)); 297 return CharCmp(c1, c2); 298 } 299 } 300 return REAL(memcmp(a1, a2, size)); 301} 302 303INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 304 if (!asan_inited) return internal_memcpy(to, from, size); 305 // memcpy is called during __asan_init() from the internals 306 // of printf(...). 307 if (asan_init_is_running) { 308 return REAL(memcpy)(to, from, size); 309 } 310 ENSURE_ASAN_INITED(); 311 if (flags()->replace_intrin) { 312 if (to != from) { 313 // We do not treat memcpy with to==from as a bug. 314 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 315 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 316 } 317 ASAN_READ_RANGE(from, size); 318 ASAN_WRITE_RANGE(to, size); 319 } 320 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 321 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 322 return internal_memcpy(to, from, size); 323} 324 325INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 326 if (!asan_inited) return internal_memmove(to, from, size); 327 if (asan_init_is_running) { 328 return REAL(memmove)(to, from, size); 329 } 330 ENSURE_ASAN_INITED(); 331 if (flags()->replace_intrin) { 332 ASAN_READ_RANGE(from, size); 333 ASAN_WRITE_RANGE(to, size); 334 } 335 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 336 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 337 return internal_memmove(to, from, size); 338} 339 340INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 341 if (!asan_inited) return internal_memset(block, c, size); 342 // memset is called inside Printf. 343 if (asan_init_is_running) { 344 return REAL(memset)(block, c, size); 345 } 346 ENSURE_ASAN_INITED(); 347 if (flags()->replace_intrin) { 348 ASAN_WRITE_RANGE(block, size); 349 } 350 return REAL(memset)(block, c, size); 351} 352 353INTERCEPTOR(char*, strchr, const char *str, int c) { 354 if (!asan_inited) return internal_strchr(str, c); 355 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 356 // used. 357 if (asan_init_is_running) { 358 return REAL(strchr)(str, c); 359 } 360 ENSURE_ASAN_INITED(); 361 char *result = REAL(strchr)(str, c); 362 if (flags()->replace_str) { 363 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 364 ASAN_READ_RANGE(str, bytes_read); 365 } 366 return result; 367} 368 369#if ASAN_INTERCEPT_INDEX 370# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 371INTERCEPTOR(char*, index, const char *string, int c) 372 ALIAS(WRAPPER_NAME(strchr)); 373# else 374# if SANITIZER_MAC 375DECLARE_REAL(char*, index, const char *string, int c) 376OVERRIDE_FUNCTION(index, strchr); 377# else 378DEFINE_REAL(char*, index, const char *string, int c); 379# endif 380# endif 381#endif // ASAN_INTERCEPT_INDEX 382 383// For both strcat() and strncat() we need to check the validity of |to| 384// argument irrespective of the |from| length. 385INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 386 ENSURE_ASAN_INITED(); 387 if (flags()->replace_str) { 388 uptr from_length = REAL(strlen)(from); 389 ASAN_READ_RANGE(from, from_length + 1); 390 uptr to_length = REAL(strlen)(to); 391 ASAN_READ_RANGE(to, to_length); 392 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 393 // If the copying actually happens, the |from| string should not overlap 394 // with the resulting string starting at |to|, which has a length of 395 // to_length + from_length + 1. 396 if (from_length > 0) { 397 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 398 from, from_length + 1); 399 } 400 } 401 return REAL(strcat)(to, from); // NOLINT 402} 403 404INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 405 ENSURE_ASAN_INITED(); 406 if (flags()->replace_str) { 407 uptr from_length = MaybeRealStrnlen(from, size); 408 uptr copy_length = Min(size, from_length + 1); 409 ASAN_READ_RANGE(from, copy_length); 410 uptr to_length = REAL(strlen)(to); 411 ASAN_READ_RANGE(to, to_length); 412 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 413 if (from_length > 0) { 414 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 415 from, copy_length); 416 } 417 } 418 return REAL(strncat)(to, from, size); 419} 420 421INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 422 if (!asan_inited) return internal_strcmp(s1, s2); 423 if (asan_init_is_running) { 424 return REAL(strcmp)(s1, s2); 425 } 426 ENSURE_ASAN_INITED(); 427 unsigned char c1, c2; 428 uptr i; 429 for (i = 0; ; i++) { 430 c1 = (unsigned char)s1[i]; 431 c2 = (unsigned char)s2[i]; 432 if (c1 != c2 || c1 == '\0') break; 433 } 434 ASAN_READ_RANGE(s1, i + 1); 435 ASAN_READ_RANGE(s2, i + 1); 436 return CharCmp(c1, c2); 437} 438 439INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 440#if SANITIZER_MAC 441 if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 442#endif 443 // strcpy is called from malloc_default_purgeable_zone() 444 // in __asan::ReplaceSystemAlloc() on Mac. 445 if (asan_init_is_running) { 446 return REAL(strcpy)(to, from); // NOLINT 447 } 448 ENSURE_ASAN_INITED(); 449 if (flags()->replace_str) { 450 uptr from_size = REAL(strlen)(from) + 1; 451 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 452 ASAN_READ_RANGE(from, from_size); 453 ASAN_WRITE_RANGE(to, from_size); 454 } 455 return REAL(strcpy)(to, from); // NOLINT 456} 457 458#if ASAN_INTERCEPT_STRDUP 459INTERCEPTOR(char*, strdup, const char *s) { 460#if SANITIZER_MAC 461 // FIXME: because internal_strdup() uses InternalAlloc(), which currently 462 // just calls malloc() on Mac, we can't use internal_strdup() with the 463 // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc 464 // starts using mmap() instead. 465 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123. 466 if (!asan_inited) return REAL(strdup)(s); 467#endif 468 if (!asan_inited) return internal_strdup(s); 469 ENSURE_ASAN_INITED(); 470 if (flags()->replace_str) { 471 uptr length = REAL(strlen)(s); 472 ASAN_READ_RANGE(s, length + 1); 473 } 474 return REAL(strdup)(s); 475} 476#endif 477 478INTERCEPTOR(uptr, strlen, const char *s) { 479 if (!asan_inited) return internal_strlen(s); 480 // strlen is called from malloc_default_purgeable_zone() 481 // in __asan::ReplaceSystemAlloc() on Mac. 482 if (asan_init_is_running) { 483 return REAL(strlen)(s); 484 } 485 ENSURE_ASAN_INITED(); 486 uptr length = REAL(strlen)(s); 487 if (flags()->replace_str) { 488 ASAN_READ_RANGE(s, length + 1); 489 } 490 return length; 491} 492 493INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 494 if (!asan_inited) return internal_strncmp(s1, s2, size); 495 // strncmp is called from malloc_default_purgeable_zone() 496 // in __asan::ReplaceSystemAlloc() on Mac. 497 if (asan_init_is_running) { 498 return REAL(strncmp)(s1, s2, size); 499 } 500 ENSURE_ASAN_INITED(); 501 unsigned char c1 = 0, c2 = 0; 502 uptr i; 503 for (i = 0; i < size; i++) { 504 c1 = (unsigned char)s1[i]; 505 c2 = (unsigned char)s2[i]; 506 if (c1 != c2 || c1 == '\0') break; 507 } 508 ASAN_READ_RANGE(s1, Min(i + 1, size)); 509 ASAN_READ_RANGE(s2, Min(i + 1, size)); 510 return CharCmp(c1, c2); 511} 512 513INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 514 ENSURE_ASAN_INITED(); 515 if (flags()->replace_str) { 516 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 517 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 518 ASAN_READ_RANGE(from, from_size); 519 ASAN_WRITE_RANGE(to, size); 520 } 521 return REAL(strncpy)(to, from, size); 522} 523 524#if ASAN_INTERCEPT_STRNLEN 525INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 526 ENSURE_ASAN_INITED(); 527 uptr length = REAL(strnlen)(s, maxlen); 528 if (flags()->replace_str) { 529 ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 530 } 531 return length; 532} 533#endif // ASAN_INTERCEPT_STRNLEN 534 535static inline bool IsValidStrtolBase(int base) { 536 return (base == 0) || (2 <= base && base <= 36); 537} 538 539static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 540 CHECK(endptr); 541 if (nptr == *endptr) { 542 // No digits were found at strtol call, we need to find out the last 543 // symbol accessed by strtoll on our own. 544 // We get this symbol by skipping leading blanks and optional +/- sign. 545 while (IsSpace(*nptr)) nptr++; 546 if (*nptr == '+' || *nptr == '-') nptr++; 547 *endptr = (char*)nptr; 548 } 549 CHECK(*endptr >= nptr); 550} 551 552INTERCEPTOR(long, strtol, const char *nptr, // NOLINT 553 char **endptr, int base) { 554 ENSURE_ASAN_INITED(); 555 if (!flags()->replace_str) { 556 return REAL(strtol)(nptr, endptr, base); 557 } 558 char *real_endptr; 559 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 560 if (endptr != 0) { 561 *endptr = real_endptr; 562 } 563 if (IsValidStrtolBase(base)) { 564 FixRealStrtolEndptr(nptr, &real_endptr); 565 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 566 } 567 return result; 568} 569 570INTERCEPTOR(int, atoi, const char *nptr) { 571#if SANITIZER_MAC 572 if (!asan_inited) return REAL(atoi)(nptr); 573#endif 574 ENSURE_ASAN_INITED(); 575 if (!flags()->replace_str) { 576 return REAL(atoi)(nptr); 577 } 578 char *real_endptr; 579 // "man atoi" tells that behavior of atoi(nptr) is the same as 580 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 581 // parsed integer can't be stored in *long* type (even if it's 582 // different from int). So, we just imitate this behavior. 583 int result = REAL(strtol)(nptr, &real_endptr, 10); 584 FixRealStrtolEndptr(nptr, &real_endptr); 585 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 586 return result; 587} 588 589INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 590#if SANITIZER_MAC 591 if (!asan_inited) return REAL(atol)(nptr); 592#endif 593 ENSURE_ASAN_INITED(); 594 if (!flags()->replace_str) { 595 return REAL(atol)(nptr); 596 } 597 char *real_endptr; 598 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 599 FixRealStrtolEndptr(nptr, &real_endptr); 600 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 601 return result; 602} 603 604#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 605INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 606 char **endptr, int base) { 607 ENSURE_ASAN_INITED(); 608 if (!flags()->replace_str) { 609 return REAL(strtoll)(nptr, endptr, base); 610 } 611 char *real_endptr; 612 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 613 if (endptr != 0) { 614 *endptr = real_endptr; 615 } 616 // If base has unsupported value, strtoll can exit with EINVAL 617 // without reading any characters. So do additional checks only 618 // if base is valid. 619 if (IsValidStrtolBase(base)) { 620 FixRealStrtolEndptr(nptr, &real_endptr); 621 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 622 } 623 return result; 624} 625 626INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 627 ENSURE_ASAN_INITED(); 628 if (!flags()->replace_str) { 629 return REAL(atoll)(nptr); 630 } 631 char *real_endptr; 632 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 633 FixRealStrtolEndptr(nptr, &real_endptr); 634 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 635 return result; 636} 637#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 638 639#define ASAN_INTERCEPT_FUNC(name) do { \ 640 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 641 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 642 } while (0) 643 644#if SANITIZER_WINDOWS 645INTERCEPTOR_WINAPI(DWORD, CreateThread, 646 void* security, uptr stack_size, 647 DWORD (__stdcall *start_routine)(void*), void* arg, 648 DWORD flags, void* tid) { 649 // Strict init-order checking in thread-hostile. 650 DisableStrictInitOrderChecker(); 651 GET_STACK_TRACE_THREAD; 652 u32 current_tid = GetCurrentTidOrInvalid(); 653 AsanThread *t = AsanThread::Create(start_routine, arg); 654 CreateThreadContextArgs args = { t, &stack }; 655 int detached = 0; // FIXME: how can we determine it on Windows? 656 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 657 return REAL(CreateThread)(security, stack_size, 658 asan_thread_start, t, flags, tid); 659} 660 661namespace __asan { 662void InitializeWindowsInterceptors() { 663 ASAN_INTERCEPT_FUNC(CreateThread); 664} 665 666} // namespace __asan 667#endif 668 669// ---------------------- InitializeAsanInterceptors ---------------- {{{1 670namespace __asan { 671void InitializeAsanInterceptors() { 672 static bool was_called_once; 673 CHECK(was_called_once == false); 674 was_called_once = true; 675#if SANITIZER_MAC 676 return; 677#else 678 SANITIZER_COMMON_INTERCEPTORS_INIT; 679 680 // Intercept mem* functions. 681 ASAN_INTERCEPT_FUNC(memcmp); 682 ASAN_INTERCEPT_FUNC(memmove); 683 ASAN_INTERCEPT_FUNC(memset); 684 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 685 ASAN_INTERCEPT_FUNC(memcpy); 686 } 687 688 // Intercept str* functions. 689 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 690 ASAN_INTERCEPT_FUNC(strchr); 691 ASAN_INTERCEPT_FUNC(strcmp); 692 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 693 ASAN_INTERCEPT_FUNC(strlen); 694 ASAN_INTERCEPT_FUNC(strncat); 695 ASAN_INTERCEPT_FUNC(strncmp); 696 ASAN_INTERCEPT_FUNC(strncpy); 697#if ASAN_INTERCEPT_STRDUP 698 ASAN_INTERCEPT_FUNC(strdup); 699#endif 700#if ASAN_INTERCEPT_STRNLEN 701 ASAN_INTERCEPT_FUNC(strnlen); 702#endif 703#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 704 ASAN_INTERCEPT_FUNC(index); 705#endif 706 707 ASAN_INTERCEPT_FUNC(atoi); 708 ASAN_INTERCEPT_FUNC(atol); 709 ASAN_INTERCEPT_FUNC(strtol); 710#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 711 ASAN_INTERCEPT_FUNC(atoll); 712 ASAN_INTERCEPT_FUNC(strtoll); 713#endif 714 715#if ASAN_INTERCEPT_MLOCKX 716 // Intercept mlock/munlock. 717 ASAN_INTERCEPT_FUNC(mlock); 718 ASAN_INTERCEPT_FUNC(munlock); 719 ASAN_INTERCEPT_FUNC(mlockall); 720 ASAN_INTERCEPT_FUNC(munlockall); 721#endif 722 723 // Intecept signal- and jump-related functions. 724 ASAN_INTERCEPT_FUNC(longjmp); 725#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 726 ASAN_INTERCEPT_FUNC(sigaction); 727 ASAN_INTERCEPT_FUNC(signal); 728#endif 729#if ASAN_INTERCEPT_SWAPCONTEXT 730 ASAN_INTERCEPT_FUNC(swapcontext); 731#endif 732#if ASAN_INTERCEPT__LONGJMP 733 ASAN_INTERCEPT_FUNC(_longjmp); 734#endif 735#if ASAN_INTERCEPT_SIGLONGJMP 736 ASAN_INTERCEPT_FUNC(siglongjmp); 737#endif 738 739 // Intercept exception handling functions. 740#if ASAN_INTERCEPT___CXA_THROW 741 INTERCEPT_FUNCTION(__cxa_throw); 742#endif 743 744 // Intercept threading-related functions 745#if ASAN_INTERCEPT_PTHREAD_CREATE 746 ASAN_INTERCEPT_FUNC(pthread_create); 747#endif 748 749 // Some Windows-specific interceptors. 750#if SANITIZER_WINDOWS 751 InitializeWindowsInterceptors(); 752#endif 753 754 if (flags()->verbosity > 0) { 755 Report("AddressSanitizer: libc interceptors initialized\n"); 756 } 757#endif // SANITIZER_MAC 758} 759 760} // namespace __asan 761