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