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