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