asan_interceptors.cc revision e0cff0bc20ae51790c8edfbceb817e18ebf5355e
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_interface.h" 18#include "asan_internal.h" 19#include "asan_mapping.h" 20#include "asan_stack.h" 21#include "asan_stats.h" 22#include "asan_thread_registry.h" 23#include "interception/interception.h" 24#include "sanitizer_common/sanitizer_libc.h" 25 26// Use macro to describe if specific function should be 27// intercepted on a given platform. 28#if !defined(_WIN32) 29# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1 30#else 31# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0 32#endif 33 34#if !defined(__APPLE__) 35# define ASAN_INTERCEPT_STRNLEN 1 36#else 37# define ASAN_INTERCEPT_STRNLEN 0 38#endif 39 40#if defined(ANDROID) || defined(_WIN32) 41# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0 42#else 43# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1 44#endif 45 46// Use extern declarations of intercepted functions on Mac and Windows 47// to avoid including system headers. 48#if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL)) 49extern "C" { 50// signal.h 51# if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 52struct sigaction; 53int sigaction(int sig, const struct sigaction *act, 54 struct sigaction *oldact); 55void *signal(int signum, void *handler); 56# endif 57 58// setjmp.h 59void longjmp(void* env, int value); 60# if !defined(_WIN32) 61void _longjmp(void *env, int value); 62# endif 63 64// string.h / strings.h 65int memcmp(const void *a1, const void *a2, uptr size); 66void* memmove(void *to, const void *from, uptr size); 67void* memcpy(void *to, const void *from, uptr size); 68void* memset(void *block, int c, uptr size); 69char* strchr(const char *str, int c); 70# if defined(__APPLE__) 71char* index(const char *string, int c); 72# endif 73char* strcat(char *to, const char* from); // NOLINT 74char* strcpy(char *to, const char* from); // NOLINT 75char* strncpy(char *to, const char* from, uptr size); 76int strcmp(const char *s1, const char* s2); 77int strncmp(const char *s1, const char* s2, uptr size); 78# if !defined(_WIN32) 79int strcasecmp(const char *s1, const char *s2); 80int strncasecmp(const char *s1, const char *s2, uptr n); 81char* strdup(const char *s); 82# endif 83uptr strlen(const char *s); 84# if ASAN_INTERCEPT_STRNLEN 85uptr strnlen(const char *s, uptr maxlen); 86# endif 87 88// stdlib.h 89int atoi(const char *nptr); 90long atol(const char *nptr); // NOLINT 91long strtol(const char *nptr, char **endptr, int base); // NOLINT 92# if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 93long long atoll(const char *nptr); // NOLINT 94long long strtoll(const char *nptr, char **endptr, int base); // NOLINT 95# endif 96 97// Windows threads. 98# if defined(_WIN32) 99__declspec(dllimport) 100void* __stdcall CreateThread(void *sec, uptr st, void* start, 101 void *arg, DWORD fl, DWORD *id); 102# endif 103 104// Posix threads. 105# if !defined(_WIN32) 106int pthread_create(void *thread, void *attr, void *(*start_routine)(void*), 107 void *arg); 108# endif 109} // extern "C" 110#endif 111 112namespace __asan { 113 114// Instruments read/write access to a single byte in memory. 115// On error calls __asan_report_error, which aborts the program. 116#define ACCESS_ADDRESS(address, isWrite) do { \ 117 if (AddressIsPoisoned(address)) { \ 118 GET_CURRENT_PC_BP_SP; \ 119 __asan_report_error(pc, bp, sp, address, isWrite, /* access_size */ 1); \ 120 } \ 121} while (0) 122 123// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 124// and ASAN_WRITE_RANGE as macro instead of function so 125// that no extra frames are created, and stack trace contains 126// relevant information only. 127 128// Instruments read/write access to a memory range. 129// More complex implementation is possible, for now just 130// checking the first and the last byte of a range. 131#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 132 if (size > 0) { \ 133 uptr ptr = (uptr)(offset); \ 134 ACCESS_ADDRESS(ptr, isWrite); \ 135 ACCESS_ADDRESS(ptr + (size) - 1, isWrite); \ 136 } \ 137} while (0) 138 139#define ASAN_READ_RANGE(offset, size) do { \ 140 ACCESS_MEMORY_RANGE(offset, size, false); \ 141} while (0) 142 143#define ASAN_WRITE_RANGE(offset, size) do { \ 144 ACCESS_MEMORY_RANGE(offset, size, true); \ 145} while (0) 146 147// Behavior of functions like "memcpy" or "strcpy" is undefined 148// if memory intervals overlap. We report error in this case. 149// Macro is used to avoid creation of new frames. 150static inline bool RangesOverlap(const char *offset1, uptr length1, 151 const char *offset2, uptr length2) { 152 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 153} 154#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 155 const char *offset1 = (const char*)_offset1; \ 156 const char *offset2 = (const char*)_offset2; \ 157 if (RangesOverlap(offset1, length1, offset2, length2)) { \ 158 AsanReport("ERROR: AddressSanitizer %s-param-overlap: " \ 159 "memory ranges [%p,%p) and [%p, %p) overlap\n", \ 160 name, offset1, offset1 + length1, offset2, offset2 + length2); \ 161 PRINT_CURRENT_STACK(); \ 162 ShowStatsAndAbort(); \ 163 } \ 164} while (0) 165 166#define ENSURE_ASAN_INITED() do { \ 167 CHECK(!asan_init_is_running); \ 168 if (!asan_inited) { \ 169 __asan_init(); \ 170 } \ 171} while (0) 172 173static inline bool IsSpace(int c) { 174 return (c == ' ') || (c == '\n') || (c == '\t') || 175 (c == '\f') || (c == '\r') || (c == '\v'); 176} 177 178static inline bool IsDigit(int c) { 179 return (c >= '0') && (c <= '9'); 180} 181 182static inline int ToLower(int c) { 183 return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; 184} 185 186// ---------------------- Internal string functions ---------------- {{{1 187 188s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) { 189 CHECK(base == 10); 190 while (IsSpace(*nptr)) nptr++; 191 int sgn = 1; 192 u64 res = 0; 193 bool have_digits = false; 194 char *old_nptr = (char*)nptr; 195 if (*nptr == '+') { 196 sgn = 1; 197 nptr++; 198 } else if (*nptr == '-') { 199 sgn = -1; 200 nptr++; 201 } 202 while (IsDigit(*nptr)) { 203 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX; 204 int digit = ((*nptr) - '0'); 205 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX; 206 have_digits = true; 207 nptr++; 208 } 209 if (endptr != 0) { 210 *endptr = (have_digits) ? (char*)nptr : old_nptr; 211 } 212 if (sgn > 0) { 213 return (s64)(Min((u64)INT64_MAX, res)); 214 } else { 215 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1); 216 } 217} 218 219s64 internal_atoll(const char *nptr) { 220 return internal_simple_strtoll(nptr, (char**)0, 10); 221} 222 223uptr internal_strnlen(const char *s, uptr maxlen) { 224#if ASAN_INTERCEPT_STRNLEN 225 if (REAL(strnlen) != 0) { 226 return REAL(strnlen)(s, maxlen); 227 } 228#endif 229 uptr i = 0; 230 while (i < maxlen && s[i]) i++; 231 return i; 232} 233 234char* internal_strchr(const char *s, int c) { 235 while (true) { 236 if (*s == (char)c) 237 return (char*)s; 238 if (*s == 0) 239 return 0; 240 s++; 241 } 242} 243 244int internal_memcmp(const void* s1, const void* s2, uptr n) { 245 const char* t1 = (char*)s1; 246 const char* t2 = (char*)s2; 247 for (uptr i = 0; i < n; ++i, ++t1, ++t2) 248 if (*t1 != *t2) 249 return *t1 < *t2 ? -1 : 1; 250 return 0; 251} 252 253// Should not be used in performance-critical places. 254void* internal_memset(void* s, int c, uptr n) { 255 // The next line prevents Clang from making a call to memset() instead of the 256 // loop below. 257 // FIXME: building the runtime with -ffreestanding is a better idea. However 258 // there currently are linktime problems due to PR12396. 259 char volatile *t = (char*)s; 260 for (uptr i = 0; i < n; ++i, ++t) { 261 *t = c; 262 } 263 return s; 264} 265 266char *internal_strstr(const char *haystack, const char *needle) { 267 // This is O(N^2), but we are not using it in hot places. 268 uptr len1 = internal_strlen(haystack); 269 uptr len2 = internal_strlen(needle); 270 if (len1 < len2) return 0; 271 for (uptr pos = 0; pos <= len1 - len2; pos++) { 272 if (internal_memcmp(haystack + pos, needle, len2) == 0) 273 return (char*)haystack + pos; 274 } 275 return 0; 276} 277 278char *internal_strncat(char *dst, const char *src, uptr n) { 279 uptr len = internal_strlen(dst); 280 uptr i; 281 for (i = 0; i < n && src[i]; i++) 282 dst[len + i] = src[i]; 283 dst[len + i] = 0; 284 return dst; 285} 286 287} // namespace __asan 288 289// ---------------------- Wrappers ---------------- {{{1 290using namespace __asan; // NOLINT 291 292static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 293 AsanThread *t = (AsanThread*)arg; 294 asanThreadRegistry().SetCurrent(t); 295 return t->ThreadStart(); 296} 297 298#ifndef _WIN32 299INTERCEPTOR(int, pthread_create, void *thread, 300 void *attr, void *(*start_routine)(void*), void *arg) { 301 GET_STACK_TRACE_HERE(kStackTraceMax); 302 u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 303 AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 304 asanThreadRegistry().RegisterThread(t); 305 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 306} 307#endif // !_WIN32 308 309#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 310INTERCEPTOR(void*, signal, int signum, void *handler) { 311 if (!AsanInterceptsSignal(signum)) { 312 return REAL(signal)(signum, handler); 313 } 314 return 0; 315} 316 317INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 318 struct sigaction *oldact) { 319 if (!AsanInterceptsSignal(signum)) { 320 return REAL(sigaction)(signum, act, oldact); 321 } 322 return 0; 323} 324#elif ASAN_POSIX 325// We need to have defined REAL(sigaction) on posix systems. 326DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 327 struct sigaction *oldact); 328#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 329 330INTERCEPTOR(void, longjmp, void *env, int val) { 331 __asan_handle_no_return(); 332 REAL(longjmp)(env, val); 333} 334 335#if !defined(_WIN32) 336INTERCEPTOR(void, _longjmp, void *env, int val) { 337 __asan_handle_no_return(); 338 REAL(_longjmp)(env, val); 339} 340 341INTERCEPTOR(void, siglongjmp, void *env, int val) { 342 __asan_handle_no_return(); 343 REAL(siglongjmp)(env, val); 344} 345#endif 346 347#if ASAN_HAS_EXCEPTIONS == 1 348#ifdef __APPLE__ 349extern "C" void __cxa_throw(void *a, void *b, void *c); 350#endif // __APPLE__ 351 352INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 353 CHECK(REAL(__cxa_throw)); 354 __asan_handle_no_return(); 355 REAL(__cxa_throw)(a, b, c); 356} 357#endif 358 359// intercept mlock and friends. 360// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 361// All functions return 0 (success). 362static void MlockIsUnsupported() { 363 static bool printed = 0; 364 if (printed) return; 365 printed = true; 366 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 367} 368 369extern "C" { 370INTERCEPTOR_ATTRIBUTE 371int mlock(const void *addr, uptr len) { 372 MlockIsUnsupported(); 373 return 0; 374} 375 376INTERCEPTOR_ATTRIBUTE 377int munlock(const void *addr, uptr len) { 378 MlockIsUnsupported(); 379 return 0; 380} 381 382INTERCEPTOR_ATTRIBUTE 383int mlockall(int flags) { 384 MlockIsUnsupported(); 385 return 0; 386} 387 388INTERCEPTOR_ATTRIBUTE 389int munlockall(void) { 390 MlockIsUnsupported(); 391 return 0; 392} 393} // extern "C" 394 395static inline int CharCmp(unsigned char c1, unsigned char c2) { 396 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 397} 398 399static inline int CharCaseCmp(unsigned char c1, unsigned char c2) { 400 int c1_low = ToLower(c1); 401 int c2_low = ToLower(c2); 402 return c1_low - c2_low; 403} 404 405INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 406 ENSURE_ASAN_INITED(); 407 unsigned char c1 = 0, c2 = 0; 408 const unsigned char *s1 = (const unsigned char*)a1; 409 const unsigned char *s2 = (const unsigned char*)a2; 410 uptr i; 411 for (i = 0; i < size; i++) { 412 c1 = s1[i]; 413 c2 = s2[i]; 414 if (c1 != c2) break; 415 } 416 ASAN_READ_RANGE(s1, Min(i + 1, size)); 417 ASAN_READ_RANGE(s2, Min(i + 1, size)); 418 return CharCmp(c1, c2); 419} 420 421INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 422 // memcpy is called during __asan_init() from the internals 423 // of printf(...). 424 if (asan_init_is_running) { 425 return REAL(memcpy)(to, from, size); 426 } 427 ENSURE_ASAN_INITED(); 428 if (FLAG_replace_intrin) { 429 if (to != from) { 430 // We do not treat memcpy with to==from as a bug. 431 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 432 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 433 } 434 ASAN_WRITE_RANGE(from, size); 435 ASAN_READ_RANGE(to, size); 436 } 437 return REAL(memcpy)(to, from, size); 438} 439 440INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 441 ENSURE_ASAN_INITED(); 442 if (FLAG_replace_intrin) { 443 ASAN_WRITE_RANGE(from, size); 444 ASAN_READ_RANGE(to, size); 445 } 446 return REAL(memmove)(to, from, size); 447} 448 449INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 450 // memset is called inside Printf. 451 if (asan_init_is_running) { 452 return REAL(memset)(block, c, size); 453 } 454 ENSURE_ASAN_INITED(); 455 if (FLAG_replace_intrin) { 456 ASAN_WRITE_RANGE(block, size); 457 } 458 return REAL(memset)(block, c, size); 459} 460 461INTERCEPTOR(char*, strchr, const char *str, int c) { 462 ENSURE_ASAN_INITED(); 463 char *result = REAL(strchr)(str, c); 464 if (FLAG_replace_str) { 465 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 466 ASAN_READ_RANGE(str, bytes_read); 467 } 468 return result; 469} 470 471#ifdef __linux__ 472INTERCEPTOR(char*, index, const char *string, int c) 473 ALIAS(WRAPPER_NAME(strchr)); 474#else 475DEFINE_REAL(char*, index, const char *string, int c); 476#endif 477 478INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { 479 ENSURE_ASAN_INITED(); 480 unsigned char c1, c2; 481 uptr i; 482 for (i = 0; ; i++) { 483 c1 = (unsigned char)s1[i]; 484 c2 = (unsigned char)s2[i]; 485 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 486 } 487 ASAN_READ_RANGE(s1, i + 1); 488 ASAN_READ_RANGE(s2, i + 1); 489 return CharCaseCmp(c1, c2); 490} 491 492INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 493 ENSURE_ASAN_INITED(); 494 if (FLAG_replace_str) { 495 uptr from_length = REAL(strlen)(from); 496 ASAN_READ_RANGE(from, from_length + 1); 497 if (from_length > 0) { 498 uptr to_length = REAL(strlen)(to); 499 ASAN_READ_RANGE(to, to_length); 500 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 501 CHECK_RANGES_OVERLAP("strcat", to, to_length + 1, from, from_length + 1); 502 } 503 } 504 return REAL(strcat)(to, from); // NOLINT 505} 506 507INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 508 if (!asan_inited) { 509 return internal_strcmp(s1, s2); 510 } 511 unsigned char c1, c2; 512 uptr i; 513 for (i = 0; ; i++) { 514 c1 = (unsigned char)s1[i]; 515 c2 = (unsigned char)s2[i]; 516 if (c1 != c2 || c1 == '\0') break; 517 } 518 ASAN_READ_RANGE(s1, i + 1); 519 ASAN_READ_RANGE(s2, i + 1); 520 return CharCmp(c1, c2); 521} 522 523INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 524 // strcpy is called from malloc_default_purgeable_zone() 525 // in __asan::ReplaceSystemAlloc() on Mac. 526 if (asan_init_is_running) { 527 return REAL(strcpy)(to, from); // NOLINT 528 } 529 ENSURE_ASAN_INITED(); 530 if (FLAG_replace_str) { 531 uptr from_size = REAL(strlen)(from) + 1; 532 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 533 ASAN_READ_RANGE(from, from_size); 534 ASAN_WRITE_RANGE(to, from_size); 535 } 536 return REAL(strcpy)(to, from); // NOLINT 537} 538 539INTERCEPTOR(char*, strdup, const char *s) { 540 ENSURE_ASAN_INITED(); 541 if (FLAG_replace_str) { 542 uptr length = REAL(strlen)(s); 543 ASAN_READ_RANGE(s, length + 1); 544 } 545 return REAL(strdup)(s); 546} 547 548INTERCEPTOR(uptr, strlen, const char *s) { 549 // strlen is called from malloc_default_purgeable_zone() 550 // in __asan::ReplaceSystemAlloc() on Mac. 551 if (asan_init_is_running) { 552 return REAL(strlen)(s); 553 } 554 ENSURE_ASAN_INITED(); 555 uptr length = REAL(strlen)(s); 556 if (FLAG_replace_str) { 557 ASAN_READ_RANGE(s, length + 1); 558 } 559 return length; 560} 561 562INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) { 563 ENSURE_ASAN_INITED(); 564 unsigned char c1 = 0, c2 = 0; 565 uptr i; 566 for (i = 0; i < n; i++) { 567 c1 = (unsigned char)s1[i]; 568 c2 = (unsigned char)s2[i]; 569 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 570 } 571 ASAN_READ_RANGE(s1, Min(i + 1, n)); 572 ASAN_READ_RANGE(s2, Min(i + 1, n)); 573 return CharCaseCmp(c1, c2); 574} 575 576INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 577 // strncmp is called from malloc_default_purgeable_zone() 578 // in __asan::ReplaceSystemAlloc() on Mac. 579 if (asan_init_is_running) { 580 return REAL(strncmp)(s1, s2, size); 581 } 582 unsigned char c1 = 0, c2 = 0; 583 uptr i; 584 for (i = 0; i < size; i++) { 585 c1 = (unsigned char)s1[i]; 586 c2 = (unsigned char)s2[i]; 587 if (c1 != c2 || c1 == '\0') break; 588 } 589 ASAN_READ_RANGE(s1, Min(i + 1, size)); 590 ASAN_READ_RANGE(s2, Min(i + 1, size)); 591 return CharCmp(c1, c2); 592} 593 594INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 595 ENSURE_ASAN_INITED(); 596 if (FLAG_replace_str) { 597 uptr from_size = Min(size, internal_strnlen(from, size) + 1); 598 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 599 ASAN_READ_RANGE(from, from_size); 600 ASAN_WRITE_RANGE(to, size); 601 } 602 return REAL(strncpy)(to, from, size); 603} 604 605#if ASAN_INTERCEPT_STRNLEN 606INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 607 ENSURE_ASAN_INITED(); 608 uptr length = REAL(strnlen)(s, maxlen); 609 if (FLAG_replace_str) { 610 ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 611 } 612 return length; 613} 614#endif // ASAN_INTERCEPT_STRNLEN 615 616static inline bool IsValidStrtolBase(int base) { 617 return (base == 0) || (2 <= base && base <= 36); 618} 619 620static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 621 CHECK(endptr != 0); 622 if (nptr == *endptr) { 623 // No digits were found at strtol call, we need to find out the last 624 // symbol accessed by strtoll on our own. 625 // We get this symbol by skipping leading blanks and optional +/- sign. 626 while (IsSpace(*nptr)) nptr++; 627 if (*nptr == '+' || *nptr == '-') nptr++; 628 *endptr = (char*)nptr; 629 } 630 CHECK(*endptr >= nptr); 631} 632 633INTERCEPTOR(long, strtol, const char *nptr, // NOLINT 634 char **endptr, int base) { 635 ENSURE_ASAN_INITED(); 636 if (!FLAG_replace_str) { 637 return REAL(strtol)(nptr, endptr, base); 638 } 639 char *real_endptr; 640 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 641 if (endptr != 0) { 642 *endptr = real_endptr; 643 } 644 if (IsValidStrtolBase(base)) { 645 FixRealStrtolEndptr(nptr, &real_endptr); 646 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 647 } 648 return result; 649} 650 651INTERCEPTOR(int, atoi, const char *nptr) { 652 ENSURE_ASAN_INITED(); 653 if (!FLAG_replace_str) { 654 return REAL(atoi)(nptr); 655 } 656 char *real_endptr; 657 // "man atoi" tells that behavior of atoi(nptr) is the same as 658 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 659 // parsed integer can't be stored in *long* type (even if it's 660 // different from int). So, we just imitate this behavior. 661 int result = REAL(strtol)(nptr, &real_endptr, 10); 662 FixRealStrtolEndptr(nptr, &real_endptr); 663 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 664 return result; 665} 666 667INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 668 ENSURE_ASAN_INITED(); 669 if (!FLAG_replace_str) { 670 return REAL(atol)(nptr); 671 } 672 char *real_endptr; 673 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 674 FixRealStrtolEndptr(nptr, &real_endptr); 675 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 676 return result; 677} 678 679#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 680INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 681 char **endptr, int base) { 682 ENSURE_ASAN_INITED(); 683 if (!FLAG_replace_str) { 684 return REAL(strtoll)(nptr, endptr, base); 685 } 686 char *real_endptr; 687 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 688 if (endptr != 0) { 689 *endptr = real_endptr; 690 } 691 // If base has unsupported value, strtoll can exit with EINVAL 692 // without reading any characters. So do additional checks only 693 // if base is valid. 694 if (IsValidStrtolBase(base)) { 695 FixRealStrtolEndptr(nptr, &real_endptr); 696 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 697 } 698 return result; 699} 700 701INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 702 ENSURE_ASAN_INITED(); 703 if (!FLAG_replace_str) { 704 return REAL(atoll)(nptr); 705 } 706 char *real_endptr; 707 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 708 FixRealStrtolEndptr(nptr, &real_endptr); 709 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 710 return result; 711} 712#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 713 714#define ASAN_INTERCEPT_FUNC(name) do { \ 715 if (!INTERCEPT_FUNCTION(name) && FLAG_v > 0) \ 716 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 717 } while (0) 718 719#if defined(_WIN32) 720INTERCEPTOR_WINAPI(DWORD, CreateThread, 721 void* security, uptr stack_size, 722 DWORD (__stdcall *start_routine)(void*), void* arg, 723 DWORD flags, void* tid) { 724 GET_STACK_TRACE_HERE(kStackTraceMax); 725 u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 726 AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 727 asanThreadRegistry().RegisterThread(t); 728 return REAL(CreateThread)(security, stack_size, 729 asan_thread_start, t, flags, tid); 730} 731 732namespace __asan { 733void InitializeWindowsInterceptors() { 734 ASAN_INTERCEPT_FUNC(CreateThread); 735} 736 737} // namespace __asan 738#endif 739 740// ---------------------- InitializeAsanInterceptors ---------------- {{{1 741namespace __asan { 742void InitializeAsanInterceptors() { 743 static bool was_called_once; 744 CHECK(was_called_once == false); 745 was_called_once = true; 746 // Intercept mem* functions. 747 ASAN_INTERCEPT_FUNC(memcmp); 748 ASAN_INTERCEPT_FUNC(memmove); 749 ASAN_INTERCEPT_FUNC(memset); 750 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 751 ASAN_INTERCEPT_FUNC(memcpy); 752 } else { 753 REAL(memcpy) = REAL(memmove); 754 } 755 756 // Intercept str* functions. 757 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 758 ASAN_INTERCEPT_FUNC(strchr); 759 ASAN_INTERCEPT_FUNC(strcmp); 760 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 761 ASAN_INTERCEPT_FUNC(strlen); 762 ASAN_INTERCEPT_FUNC(strncmp); 763 ASAN_INTERCEPT_FUNC(strncpy); 764#if !defined(_WIN32) 765 ASAN_INTERCEPT_FUNC(strcasecmp); 766 ASAN_INTERCEPT_FUNC(strdup); 767 ASAN_INTERCEPT_FUNC(strncasecmp); 768# ifndef __APPLE__ 769 ASAN_INTERCEPT_FUNC(index); 770# else 771 CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr))); 772# endif 773#endif 774#if ASAN_INTERCEPT_STRNLEN 775 ASAN_INTERCEPT_FUNC(strnlen); 776#endif 777 778 ASAN_INTERCEPT_FUNC(atoi); 779 ASAN_INTERCEPT_FUNC(atol); 780 ASAN_INTERCEPT_FUNC(strtol); 781#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 782 ASAN_INTERCEPT_FUNC(atoll); 783 ASAN_INTERCEPT_FUNC(strtoll); 784#endif 785 786 // Intecept signal- and jump-related functions. 787 ASAN_INTERCEPT_FUNC(longjmp); 788#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 789 ASAN_INTERCEPT_FUNC(sigaction); 790 ASAN_INTERCEPT_FUNC(signal); 791#endif 792 793#if !defined(_WIN32) 794 ASAN_INTERCEPT_FUNC(_longjmp); 795 INTERCEPT_FUNCTION(__cxa_throw); 796# if !defined(__APPLE__) 797 // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it 798 // there. 799 ASAN_INTERCEPT_FUNC(siglongjmp); 800# endif 801#endif 802 803 // Intercept threading-related functions 804#if !defined(_WIN32) 805 ASAN_INTERCEPT_FUNC(pthread_create); 806#endif 807 808 // Some Windows-specific interceptors. 809#if defined(_WIN32) 810 InitializeWindowsInterceptors(); 811#endif 812 813 // Some Mac-specific interceptors. 814#if defined(__APPLE__) 815 InitializeMacInterceptors(); 816#endif 817 818 if (FLAG_v > 0) { 819 Report("AddressSanitizer: libc interceptors initialized\n"); 820 } 821} 822 823} // namespace __asan 824