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