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