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