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