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