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