asan_interceptors.cc revision 716e2f25123bf9b20fbc6b582803a3929b78b96d
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 101static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 102 AsanThread *t = (AsanThread*)arg; 103 asanThreadRegistry().SetCurrent(t); 104 return t->ThreadStart(); 105} 106 107#if ASAN_INTERCEPT_PTHREAD_CREATE 108INTERCEPTOR(int, pthread_create, void *thread, 109 void *attr, void *(*start_routine)(void*), void *arg) { 110 GET_STACK_TRACE_HERE(kStackTraceMax); 111 u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 112 AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 113 asanThreadRegistry().RegisterThread(t); 114 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 115} 116#endif // ASAN_INTERCEPT_PTHREAD_CREATE 117 118#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 119INTERCEPTOR(void*, signal, int signum, void *handler) { 120 if (!AsanInterceptsSignal(signum)) { 121 return REAL(signal)(signum, handler); 122 } 123 return 0; 124} 125 126INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 127 struct sigaction *oldact) { 128 if (!AsanInterceptsSignal(signum)) { 129 return REAL(sigaction)(signum, act, oldact); 130 } 131 return 0; 132} 133#elif ASAN_POSIX 134// We need to have defined REAL(sigaction) on posix systems. 135DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 136 struct sigaction *oldact); 137#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 138 139#if ASAN_INTERCEPT_SWAPCONTEXT 140INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 141 struct ucontext_t *ucp) { 142 static bool reported_warning = false; 143 if (!reported_warning) { 144 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 145 "functions and may produce false positives in some cases!\n"); 146 reported_warning = true; 147 } 148 // Clear shadow memory for new context (it may share stack 149 // with current context). 150 ClearShadowMemoryForContext(ucp); 151 int res = REAL(swapcontext)(oucp, ucp); 152 // swapcontext technically does not return, but program may swap context to 153 // "oucp" later, that would look as if swapcontext() returned 0. 154 // We need to clear shadow for ucp once again, as it may be in arbitrary 155 // state. 156 ClearShadowMemoryForContext(ucp); 157 return res; 158} 159#endif 160 161INTERCEPTOR(void, longjmp, void *env, int val) { 162 __asan_handle_no_return(); 163 REAL(longjmp)(env, val); 164} 165 166#if ASAN_INTERCEPT__LONGJMP 167INTERCEPTOR(void, _longjmp, void *env, int val) { 168 __asan_handle_no_return(); 169 REAL(_longjmp)(env, val); 170} 171#endif 172 173#if ASAN_INTERCEPT_SIGLONGJMP 174INTERCEPTOR(void, siglongjmp, void *env, int val) { 175 __asan_handle_no_return(); 176 REAL(siglongjmp)(env, val); 177} 178#endif 179 180#define PR_SET_NAME 15 181 182INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3, 183 unsigned long arg4, unsigned long arg5) { 184 int res = REAL(prctl(option, arg2, arg3, arg4, arg5)); 185 if (option == PR_SET_NAME) { 186 AsanThread *t = asanThreadRegistry().GetCurrent(); 187 if (t) { 188 char buff[17]; 189 internal_strncpy(buff, (char*)arg2, 16); 190 buff[16] = 0; 191 t->summary()->set_name(buff); 192 } 193 } 194 return res; 195} 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_WRITE_RANGE(from, size); 279 ASAN_READ_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_WRITE_RANGE(from, size); 298 ASAN_READ_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_HERE(kStackTraceMax); 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 // Intercept mem* functions. 669 ASAN_INTERCEPT_FUNC(memcmp); 670 ASAN_INTERCEPT_FUNC(memmove); 671 ASAN_INTERCEPT_FUNC(memset); 672 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 673 ASAN_INTERCEPT_FUNC(memcpy); 674 } else { 675#if !MAC_INTERPOSE_FUNCTIONS 676 // If we're using dynamic interceptors on Mac, these two are just plain 677 // functions. 678 internal_memcpy(&REAL(memcpy), &REAL(memmove), sizeof(REAL(memmove))); 679#endif 680 } 681 682 // Intercept str* functions. 683 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 684 ASAN_INTERCEPT_FUNC(strchr); 685 ASAN_INTERCEPT_FUNC(strcmp); 686 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 687 ASAN_INTERCEPT_FUNC(strlen); 688 ASAN_INTERCEPT_FUNC(strncat); 689 ASAN_INTERCEPT_FUNC(strncmp); 690 ASAN_INTERCEPT_FUNC(strncpy); 691#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 692 ASAN_INTERCEPT_FUNC(strcasecmp); 693 ASAN_INTERCEPT_FUNC(strncasecmp); 694#endif 695#if ASAN_INTERCEPT_STRDUP 696 ASAN_INTERCEPT_FUNC(strdup); 697#endif 698#if ASAN_INTERCEPT_STRNLEN 699 ASAN_INTERCEPT_FUNC(strnlen); 700#endif 701#if ASAN_INTERCEPT_INDEX 702# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 703 ASAN_INTERCEPT_FUNC(index); 704# else 705 CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr))); 706# endif 707#endif 708 709 ASAN_INTERCEPT_FUNC(atoi); 710 ASAN_INTERCEPT_FUNC(atol); 711 ASAN_INTERCEPT_FUNC(strtol); 712#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 713 ASAN_INTERCEPT_FUNC(atoll); 714 ASAN_INTERCEPT_FUNC(strtoll); 715#endif 716 717#if ASAN_INTERCEPT_MLOCKX 718 // Intercept mlock/munlock. 719 ASAN_INTERCEPT_FUNC(mlock); 720 ASAN_INTERCEPT_FUNC(munlock); 721 ASAN_INTERCEPT_FUNC(mlockall); 722 ASAN_INTERCEPT_FUNC(munlockall); 723#endif 724 725 // Intecept signal- and jump-related functions. 726 ASAN_INTERCEPT_FUNC(longjmp); 727#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 728 ASAN_INTERCEPT_FUNC(sigaction); 729 ASAN_INTERCEPT_FUNC(signal); 730#endif 731#if ASAN_INTERCEPT_SWAPCONTEXT 732 ASAN_INTERCEPT_FUNC(swapcontext); 733#endif 734#if ASAN_INTERCEPT__LONGJMP 735 ASAN_INTERCEPT_FUNC(_longjmp); 736#endif 737#if ASAN_INTERCEPT_SIGLONGJMP 738 ASAN_INTERCEPT_FUNC(siglongjmp); 739#endif 740 ASAN_INTERCEPT_FUNC(prctl); 741 742 // Intercept exception handling functions. 743#if ASAN_INTERCEPT___CXA_THROW 744 INTERCEPT_FUNCTION(__cxa_throw); 745#endif 746 747 // Intercept threading-related functions 748#if ASAN_INTERCEPT_PTHREAD_CREATE 749 ASAN_INTERCEPT_FUNC(pthread_create); 750#endif 751 752 // Some Windows-specific interceptors. 753#if defined(_WIN32) 754 InitializeWindowsInterceptors(); 755#endif 756 757 // Some Mac-specific interceptors. 758#if defined(__APPLE__) 759 InitializeMacInterceptors(); 760#endif 761 762 if (flags()->verbosity > 0) { 763 Report("AddressSanitizer: libc interceptors initialized\n"); 764 } 765} 766 767} // namespace __asan 768