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