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