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