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