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