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