1 //===-- asan_interceptors.cc ----------------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file is a part of AddressSanitizer, an address sanity checker. 9 // 10 // Intercept various libc functions. 11 //===----------------------------------------------------------------------===// 12 #include "asan_interceptors.h" 13 14 #include "asan_allocator.h" 15 #include "asan_internal.h" 16 #include "asan_mapping.h" 17 #include "asan_poisoning.h" 18 #include "asan_report.h" 19 #include "asan_stack.h" 20 #include "asan_stats.h" 21 #include "sanitizer_common/sanitizer_libc.h" 22 23 namespace __asan { 24 25 // Return true if we can quickly decide that the region is unpoisoned. 26 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { 27 if (size == 0) return true; 28 if (size <= 32) 29 return !AddressIsPoisoned(beg) && 30 !AddressIsPoisoned(beg + size - 1) && 31 !AddressIsPoisoned(beg + size / 2); 32 return false; 33 } 34 35 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 36 // and ASAN_WRITE_RANGE as macro instead of function so 37 // that no extra frames are created, and stack trace contains 38 // relevant information only. 39 // We check all shadow bytes. 40 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 41 uptr __offset = (uptr)(offset); \ 42 uptr __size = (uptr)(size); \ 43 uptr __bad = 0; \ 44 if (__offset > __offset + __size) { \ 45 GET_STACK_TRACE_FATAL_HERE; \ 46 ReportStringFunctionSizeOverflow(__offset, __size, &stack); \ 47 } \ 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. 61 static 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 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 76 #if ASAN_INTERCEPT_STRNLEN 77 if (REAL(strnlen) != 0) { 78 return REAL(strnlen)(s, maxlen); 79 } 80 #endif 81 return internal_strnlen(s, maxlen); 82 } 83 84 void SetThreadName(const char *name) { 85 AsanThread *t = GetCurrentThread(); 86 if (t) 87 asanThreadRegistry().SetThreadName(t->tid(), name); 88 } 89 90 int OnExit() { 91 // FIXME: ask frontend whether we need to return failure. 92 return 0; 93 } 94 95 } // namespace __asan 96 97 // ---------------------- Wrappers ---------------- {{{1 98 using namespace __asan; // NOLINT 99 100 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 101 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) 102 103 #if !SANITIZER_MAC 104 #define ASAN_INTERCEPT_FUNC(name) \ 105 do { \ 106 if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ 107 VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ 108 } while (0) 109 #else 110 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. 111 #define ASAN_INTERCEPT_FUNC(name) 112 #endif // SANITIZER_MAC 113 114 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name) 115 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 116 ASAN_WRITE_RANGE(ptr, size) 117 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 118 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 119 do { \ 120 if (asan_init_is_running) \ 121 return REAL(func)(__VA_ARGS__); \ 122 ctx = 0; \ 123 (void) ctx; \ 124 if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \ 125 return REAL(func)(__VA_ARGS__); \ 126 ENSURE_ASAN_INITED(); \ 127 } while (false) 128 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 129 do { \ 130 } while (false) 131 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 132 do { \ 133 } while (false) 134 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 135 do { \ 136 } while (false) 137 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 138 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name) 139 // But asan does not remember UserId's for threads (pthread_t); 140 // and remembers all ever existed threads, so the linear search by UserId 141 // can be slow. 142 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ 143 do { \ 144 } while (false) 145 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 146 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() 147 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res) CovUpdateMapping() 148 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CovUpdateMapping() 149 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) 150 #include "sanitizer_common/sanitizer_common_interceptors.inc" 151 152 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s) 153 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s) 154 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 155 do { \ 156 (void)(p); \ 157 (void)(s); \ 158 } while (false) 159 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 160 do { \ 161 (void)(p); \ 162 (void)(s); \ 163 } while (false) 164 #include "sanitizer_common/sanitizer_common_syscalls.inc" 165 166 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 167 AsanThread *t = (AsanThread*)arg; 168 SetCurrentThread(t); 169 return t->ThreadStart(GetTid()); 170 } 171 172 #if ASAN_INTERCEPT_PTHREAD_CREATE 173 INTERCEPTOR(int, pthread_create, void *thread, 174 void *attr, void *(*start_routine)(void*), void *arg) { 175 EnsureMainThreadIDIsCorrect(); 176 // Strict init-order checking in thread-hostile. 177 if (flags()->strict_init_order) 178 StopInitOrderChecking(); 179 GET_STACK_TRACE_THREAD; 180 int detached = 0; 181 if (attr != 0) 182 REAL(pthread_attr_getdetachstate)(attr, &detached); 183 184 u32 current_tid = GetCurrentTidOrInvalid(); 185 AsanThread *t = AsanThread::Create(start_routine, arg); 186 CreateThreadContextArgs args = { t, &stack }; 187 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 188 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 189 } 190 #endif // ASAN_INTERCEPT_PTHREAD_CREATE 191 192 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 193 194 #if SANITIZER_ANDROID 195 INTERCEPTOR(void*, bsd_signal, int signum, void *handler) { 196 if (!AsanInterceptsSignal(signum) || 197 common_flags()->allow_user_segv_handler) { 198 return REAL(bsd_signal)(signum, handler); 199 } 200 return 0; 201 } 202 #else 203 INTERCEPTOR(void*, signal, int signum, void *handler) { 204 if (!AsanInterceptsSignal(signum) || 205 common_flags()->allow_user_segv_handler) { 206 return REAL(signal)(signum, handler); 207 } 208 return 0; 209 } 210 #endif 211 212 INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 213 struct sigaction *oldact) { 214 if (!AsanInterceptsSignal(signum) || 215 common_flags()->allow_user_segv_handler) { 216 return REAL(sigaction)(signum, act, oldact); 217 } 218 return 0; 219 } 220 221 namespace __sanitizer { 222 int real_sigaction(int signum, const void *act, void *oldact) { 223 return REAL(sigaction)(signum, 224 (struct sigaction *)act, (struct sigaction *)oldact); 225 } 226 } // namespace __sanitizer 227 228 #elif SANITIZER_POSIX 229 // We need to have defined REAL(sigaction) on posix systems. 230 DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 231 struct sigaction *oldact) 232 #endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 233 234 #if ASAN_INTERCEPT_SWAPCONTEXT 235 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 236 // Align to page size. 237 uptr PageSize = GetPageSizeCached(); 238 uptr bottom = stack & ~(PageSize - 1); 239 ssize += stack - bottom; 240 ssize = RoundUpTo(ssize, PageSize); 241 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 242 if (ssize && ssize <= kMaxSaneContextStackSize) { 243 PoisonShadow(bottom, ssize, 0); 244 } 245 } 246 247 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 248 struct ucontext_t *ucp) { 249 static bool reported_warning = false; 250 if (!reported_warning) { 251 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 252 "functions and may produce false positives in some cases!\n"); 253 reported_warning = true; 254 } 255 // Clear shadow memory for new context (it may share stack 256 // with current context). 257 uptr stack, ssize; 258 ReadContextStack(ucp, &stack, &ssize); 259 ClearShadowMemoryForContextStack(stack, ssize); 260 int res = REAL(swapcontext)(oucp, ucp); 261 // swapcontext technically does not return, but program may swap context to 262 // "oucp" later, that would look as if swapcontext() returned 0. 263 // We need to clear shadow for ucp once again, as it may be in arbitrary 264 // state. 265 ClearShadowMemoryForContextStack(stack, ssize); 266 return res; 267 } 268 #endif // ASAN_INTERCEPT_SWAPCONTEXT 269 270 #if SANITIZER_NETBSD 271 #define longjmp __longjmp14 272 #define siglongjmp __siglongjmp14 273 #endif 274 275 INTERCEPTOR(void, longjmp, void *env, int val) { 276 __asan_handle_no_return(); 277 REAL(longjmp)(env, val); 278 } 279 280 #if ASAN_INTERCEPT__LONGJMP 281 INTERCEPTOR(void, _longjmp, void *env, int val) { 282 __asan_handle_no_return(); 283 REAL(_longjmp)(env, val); 284 } 285 #endif 286 287 #if ASAN_INTERCEPT_SIGLONGJMP 288 INTERCEPTOR(void, siglongjmp, void *env, int val) { 289 __asan_handle_no_return(); 290 REAL(siglongjmp)(env, val); 291 } 292 #endif 293 294 #if ASAN_INTERCEPT___CXA_THROW 295 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 296 CHECK(REAL(__cxa_throw)); 297 __asan_handle_no_return(); 298 REAL(__cxa_throw)(a, b, c); 299 } 300 #endif 301 302 #if SANITIZER_WINDOWS 303 INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) { 304 CHECK(REAL(RaiseException)); 305 __asan_handle_no_return(); 306 REAL(RaiseException)(a, b, c, d); 307 } 308 309 INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) { 310 CHECK(REAL(_except_handler3)); 311 __asan_handle_no_return(); 312 return REAL(_except_handler3)(a, b, c, d); 313 } 314 315 #if ASAN_DYNAMIC 316 // This handler is named differently in -MT and -MD CRTs. 317 #define _except_handler4 _except_handler4_common 318 #endif 319 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { 320 CHECK(REAL(_except_handler4)); 321 __asan_handle_no_return(); 322 return REAL(_except_handler4)(a, b, c, d); 323 } 324 #endif 325 326 static inline int CharCmp(unsigned char c1, unsigned char c2) { 327 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 328 } 329 330 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 331 if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size); 332 ENSURE_ASAN_INITED(); 333 if (flags()->replace_intrin) { 334 if (flags()->strict_memcmp) { 335 // Check the entire regions even if the first bytes of the buffers are 336 // different. 337 ASAN_READ_RANGE(a1, size); 338 ASAN_READ_RANGE(a2, size); 339 // Fallthrough to REAL(memcmp) below. 340 } else { 341 unsigned char c1 = 0, c2 = 0; 342 const unsigned char *s1 = (const unsigned char*)a1; 343 const unsigned char *s2 = (const unsigned char*)a2; 344 uptr i; 345 for (i = 0; i < size; i++) { 346 c1 = s1[i]; 347 c2 = s2[i]; 348 if (c1 != c2) break; 349 } 350 ASAN_READ_RANGE(s1, Min(i + 1, size)); 351 ASAN_READ_RANGE(s2, Min(i + 1, size)); 352 return CharCmp(c1, c2); 353 } 354 } 355 return REAL(memcmp(a1, a2, size)); 356 } 357 358 void *__asan_memcpy(void *to, const void *from, uptr size) { 359 if (UNLIKELY(!asan_inited)) return internal_memcpy(to, from, size); 360 // memcpy is called during __asan_init() from the internals 361 // of printf(...). 362 if (asan_init_is_running) { 363 return REAL(memcpy)(to, from, size); 364 } 365 ENSURE_ASAN_INITED(); 366 if (flags()->replace_intrin) { 367 if (to != from) { 368 // We do not treat memcpy with to==from as a bug. 369 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 370 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 371 } 372 ASAN_READ_RANGE(from, size); 373 ASAN_WRITE_RANGE(to, size); 374 } 375 return REAL(memcpy)(to, from, size); 376 } 377 378 void *__asan_memset(void *block, int c, uptr size) { 379 if (UNLIKELY(!asan_inited)) return internal_memset(block, c, size); 380 // memset is called inside Printf. 381 if (asan_init_is_running) { 382 return REAL(memset)(block, c, size); 383 } 384 ENSURE_ASAN_INITED(); 385 if (flags()->replace_intrin) { 386 ASAN_WRITE_RANGE(block, size); 387 } 388 return REAL(memset)(block, c, size); 389 } 390 391 void *__asan_memmove(void *to, const void *from, uptr size) { 392 if (UNLIKELY(!asan_inited)) 393 return internal_memmove(to, from, size); 394 ENSURE_ASAN_INITED(); 395 if (flags()->replace_intrin) { 396 ASAN_READ_RANGE(from, size); 397 ASAN_WRITE_RANGE(to, size); 398 } 399 return internal_memmove(to, from, size); 400 } 401 402 INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 403 return __asan_memmove(to, from, size); 404 } 405 406 INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 407 #if !SANITIZER_MAC 408 return __asan_memcpy(to, from, size); 409 #else 410 // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced 411 // with WRAP(memcpy). As a result, false positives are reported for memmove() 412 // calls. If we just disable error reporting with 413 // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with 414 // internal_memcpy(), which may lead to crashes, see 415 // http://llvm.org/bugs/show_bug.cgi?id=16362. 416 return __asan_memmove(to, from, size); 417 #endif // !SANITIZER_MAC 418 } 419 420 INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 421 return __asan_memset(block, c, size); 422 } 423 424 INTERCEPTOR(char*, strchr, const char *str, int c) { 425 if (UNLIKELY(!asan_inited)) return internal_strchr(str, c); 426 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 427 // used. 428 if (asan_init_is_running) { 429 return REAL(strchr)(str, c); 430 } 431 ENSURE_ASAN_INITED(); 432 char *result = REAL(strchr)(str, c); 433 if (flags()->replace_str) { 434 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 435 ASAN_READ_RANGE(str, bytes_read); 436 } 437 return result; 438 } 439 440 #if ASAN_INTERCEPT_INDEX 441 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 442 INTERCEPTOR(char*, index, const char *string, int c) 443 ALIAS(WRAPPER_NAME(strchr)); 444 # else 445 # if SANITIZER_MAC 446 DECLARE_REAL(char*, index, const char *string, int c) 447 OVERRIDE_FUNCTION(index, strchr); 448 # else 449 DEFINE_REAL(char*, index, const char *string, int c) 450 # endif 451 # endif 452 #endif // ASAN_INTERCEPT_INDEX 453 454 // For both strcat() and strncat() we need to check the validity of |to| 455 // argument irrespective of the |from| length. 456 INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 457 ENSURE_ASAN_INITED(); 458 if (flags()->replace_str) { 459 uptr from_length = REAL(strlen)(from); 460 ASAN_READ_RANGE(from, from_length + 1); 461 uptr to_length = REAL(strlen)(to); 462 ASAN_READ_RANGE(to, to_length); 463 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 464 // If the copying actually happens, the |from| string should not overlap 465 // with the resulting string starting at |to|, which has a length of 466 // to_length + from_length + 1. 467 if (from_length > 0) { 468 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 469 from, from_length + 1); 470 } 471 } 472 return REAL(strcat)(to, from); // NOLINT 473 } 474 475 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 476 ENSURE_ASAN_INITED(); 477 if (flags()->replace_str) { 478 uptr from_length = MaybeRealStrnlen(from, size); 479 uptr copy_length = Min(size, from_length + 1); 480 ASAN_READ_RANGE(from, copy_length); 481 uptr to_length = REAL(strlen)(to); 482 ASAN_READ_RANGE(to, to_length); 483 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 484 if (from_length > 0) { 485 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 486 from, copy_length); 487 } 488 } 489 return REAL(strncat)(to, from, size); 490 } 491 492 INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 493 #if SANITIZER_MAC 494 if (UNLIKELY(!asan_inited)) return REAL(strcpy)(to, from); // NOLINT 495 #endif 496 // strcpy is called from malloc_default_purgeable_zone() 497 // in __asan::ReplaceSystemAlloc() on Mac. 498 if (asan_init_is_running) { 499 return REAL(strcpy)(to, from); // NOLINT 500 } 501 ENSURE_ASAN_INITED(); 502 if (flags()->replace_str) { 503 uptr from_size = REAL(strlen)(from) + 1; 504 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 505 ASAN_READ_RANGE(from, from_size); 506 ASAN_WRITE_RANGE(to, from_size); 507 } 508 return REAL(strcpy)(to, from); // NOLINT 509 } 510 511 #if ASAN_INTERCEPT_STRDUP 512 INTERCEPTOR(char*, strdup, const char *s) { 513 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 514 ENSURE_ASAN_INITED(); 515 uptr length = REAL(strlen)(s); 516 if (flags()->replace_str) { 517 ASAN_READ_RANGE(s, length + 1); 518 } 519 GET_STACK_TRACE_MALLOC; 520 void *new_mem = asan_malloc(length + 1, &stack); 521 REAL(memcpy)(new_mem, s, length + 1); 522 return reinterpret_cast<char*>(new_mem); 523 } 524 #endif 525 526 INTERCEPTOR(SIZE_T, strlen, const char *s) { 527 if (UNLIKELY(!asan_inited)) return internal_strlen(s); 528 // strlen is called from malloc_default_purgeable_zone() 529 // in __asan::ReplaceSystemAlloc() on Mac. 530 if (asan_init_is_running) { 531 return REAL(strlen)(s); 532 } 533 ENSURE_ASAN_INITED(); 534 SIZE_T length = REAL(strlen)(s); 535 if (flags()->replace_str) { 536 ASAN_READ_RANGE(s, length + 1); 537 } 538 return length; 539 } 540 541 INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { 542 SIZE_T length = REAL(wcslen)(s); 543 if (!asan_init_is_running) { 544 ENSURE_ASAN_INITED(); 545 ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t)); 546 } 547 return length; 548 } 549 550 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 551 ENSURE_ASAN_INITED(); 552 if (flags()->replace_str) { 553 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 554 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 555 ASAN_READ_RANGE(from, from_size); 556 ASAN_WRITE_RANGE(to, size); 557 } 558 return REAL(strncpy)(to, from, size); 559 } 560 561 #if ASAN_INTERCEPT_STRNLEN 562 INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 563 ENSURE_ASAN_INITED(); 564 uptr length = REAL(strnlen)(s, maxlen); 565 if (flags()->replace_str) { 566 ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 567 } 568 return length; 569 } 570 #endif // ASAN_INTERCEPT_STRNLEN 571 572 static inline bool IsValidStrtolBase(int base) { 573 return (base == 0) || (2 <= base && base <= 36); 574 } 575 576 static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 577 CHECK(endptr); 578 if (nptr == *endptr) { 579 // No digits were found at strtol call, we need to find out the last 580 // symbol accessed by strtoll on our own. 581 // We get this symbol by skipping leading blanks and optional +/- sign. 582 while (IsSpace(*nptr)) nptr++; 583 if (*nptr == '+' || *nptr == '-') nptr++; 584 *endptr = (char*)nptr; 585 } 586 CHECK(*endptr >= nptr); 587 } 588 589 INTERCEPTOR(long, strtol, const char *nptr, // NOLINT 590 char **endptr, int base) { 591 ENSURE_ASAN_INITED(); 592 if (!flags()->replace_str) { 593 return REAL(strtol)(nptr, endptr, base); 594 } 595 char *real_endptr; 596 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 597 if (endptr != 0) { 598 *endptr = real_endptr; 599 } 600 if (IsValidStrtolBase(base)) { 601 FixRealStrtolEndptr(nptr, &real_endptr); 602 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 603 } 604 return result; 605 } 606 607 INTERCEPTOR(int, atoi, const char *nptr) { 608 #if SANITIZER_MAC 609 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); 610 #endif 611 ENSURE_ASAN_INITED(); 612 if (!flags()->replace_str) { 613 return REAL(atoi)(nptr); 614 } 615 char *real_endptr; 616 // "man atoi" tells that behavior of atoi(nptr) is the same as 617 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 618 // parsed integer can't be stored in *long* type (even if it's 619 // different from int). So, we just imitate this behavior. 620 int result = REAL(strtol)(nptr, &real_endptr, 10); 621 FixRealStrtolEndptr(nptr, &real_endptr); 622 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 623 return result; 624 } 625 626 INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 627 #if SANITIZER_MAC 628 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); 629 #endif 630 ENSURE_ASAN_INITED(); 631 if (!flags()->replace_str) { 632 return REAL(atol)(nptr); 633 } 634 char *real_endptr; 635 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 636 FixRealStrtolEndptr(nptr, &real_endptr); 637 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 638 return result; 639 } 640 641 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 642 INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 643 char **endptr, int base) { 644 ENSURE_ASAN_INITED(); 645 if (!flags()->replace_str) { 646 return REAL(strtoll)(nptr, endptr, base); 647 } 648 char *real_endptr; 649 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 650 if (endptr != 0) { 651 *endptr = real_endptr; 652 } 653 // If base has unsupported value, strtoll can exit with EINVAL 654 // without reading any characters. So do additional checks only 655 // if base is valid. 656 if (IsValidStrtolBase(base)) { 657 FixRealStrtolEndptr(nptr, &real_endptr); 658 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 659 } 660 return result; 661 } 662 663 INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 664 ENSURE_ASAN_INITED(); 665 if (!flags()->replace_str) { 666 return REAL(atoll)(nptr); 667 } 668 char *real_endptr; 669 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 670 FixRealStrtolEndptr(nptr, &real_endptr); 671 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 672 return result; 673 } 674 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 675 676 static void AtCxaAtexit(void *unused) { 677 (void)unused; 678 StopInitOrderChecking(); 679 } 680 681 #if ASAN_INTERCEPT___CXA_ATEXIT 682 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 683 void *dso_handle) { 684 #if SANITIZER_MAC 685 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); 686 #endif 687 ENSURE_ASAN_INITED(); 688 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 689 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0); 690 return res; 691 } 692 #endif // ASAN_INTERCEPT___CXA_ATEXIT 693 694 #if ASAN_INTERCEPT_FORK 695 INTERCEPTOR(int, fork, void) { 696 ENSURE_ASAN_INITED(); 697 if (common_flags()->coverage) CovBeforeFork(); 698 int pid = REAL(fork)(); 699 if (common_flags()->coverage) CovAfterFork(pid); 700 return pid; 701 } 702 #endif // ASAN_INTERCEPT_FORK 703 704 #if SANITIZER_WINDOWS 705 INTERCEPTOR_WINAPI(DWORD, CreateThread, 706 void* security, uptr stack_size, 707 DWORD (__stdcall *start_routine)(void*), void* arg, 708 DWORD thr_flags, void* tid) { 709 // Strict init-order checking in thread-hostile. 710 if (flags()->strict_init_order) 711 StopInitOrderChecking(); 712 GET_STACK_TRACE_THREAD; 713 u32 current_tid = GetCurrentTidOrInvalid(); 714 AsanThread *t = AsanThread::Create(start_routine, arg); 715 CreateThreadContextArgs args = { t, &stack }; 716 bool detached = false; // FIXME: how can we determine it on Windows? 717 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 718 return REAL(CreateThread)(security, stack_size, 719 asan_thread_start, t, thr_flags, tid); 720 } 721 722 namespace __asan { 723 void InitializeWindowsInterceptors() { 724 ASAN_INTERCEPT_FUNC(CreateThread); 725 ASAN_INTERCEPT_FUNC(RaiseException); 726 ASAN_INTERCEPT_FUNC(_except_handler3); 727 ASAN_INTERCEPT_FUNC(_except_handler4); 728 } 729 730 } // namespace __asan 731 #endif 732 733 // ---------------------- InitializeAsanInterceptors ---------------- {{{1 734 namespace __asan { 735 void InitializeAsanInterceptors() { 736 static bool was_called_once; 737 CHECK(was_called_once == false); 738 was_called_once = true; 739 InitializeCommonInterceptors(); 740 741 // Intercept mem* functions. 742 ASAN_INTERCEPT_FUNC(memcmp); 743 ASAN_INTERCEPT_FUNC(memmove); 744 ASAN_INTERCEPT_FUNC(memset); 745 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 746 ASAN_INTERCEPT_FUNC(memcpy); 747 } 748 749 // Intercept str* functions. 750 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 751 ASAN_INTERCEPT_FUNC(strchr); 752 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 753 ASAN_INTERCEPT_FUNC(strlen); 754 ASAN_INTERCEPT_FUNC(wcslen); 755 ASAN_INTERCEPT_FUNC(strncat); 756 ASAN_INTERCEPT_FUNC(strncpy); 757 #if ASAN_INTERCEPT_STRDUP 758 ASAN_INTERCEPT_FUNC(strdup); 759 #endif 760 #if ASAN_INTERCEPT_STRNLEN 761 ASAN_INTERCEPT_FUNC(strnlen); 762 #endif 763 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 764 ASAN_INTERCEPT_FUNC(index); 765 #endif 766 767 ASAN_INTERCEPT_FUNC(atoi); 768 ASAN_INTERCEPT_FUNC(atol); 769 ASAN_INTERCEPT_FUNC(strtol); 770 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 771 ASAN_INTERCEPT_FUNC(atoll); 772 ASAN_INTERCEPT_FUNC(strtoll); 773 #endif 774 775 // Intecept signal- and jump-related functions. 776 ASAN_INTERCEPT_FUNC(longjmp); 777 #if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 778 ASAN_INTERCEPT_FUNC(sigaction); 779 #if SANITIZER_ANDROID 780 ASAN_INTERCEPT_FUNC(bsd_signal); 781 #else 782 ASAN_INTERCEPT_FUNC(signal); 783 #endif 784 #endif 785 #if ASAN_INTERCEPT_SWAPCONTEXT 786 ASAN_INTERCEPT_FUNC(swapcontext); 787 #endif 788 #if ASAN_INTERCEPT__LONGJMP 789 ASAN_INTERCEPT_FUNC(_longjmp); 790 #endif 791 #if ASAN_INTERCEPT_SIGLONGJMP 792 ASAN_INTERCEPT_FUNC(siglongjmp); 793 #endif 794 795 // Intercept exception handling functions. 796 #if ASAN_INTERCEPT___CXA_THROW 797 ASAN_INTERCEPT_FUNC(__cxa_throw); 798 #endif 799 800 // Intercept threading-related functions 801 #if ASAN_INTERCEPT_PTHREAD_CREATE 802 ASAN_INTERCEPT_FUNC(pthread_create); 803 #endif 804 805 // Intercept atexit function. 806 #if ASAN_INTERCEPT___CXA_ATEXIT 807 ASAN_INTERCEPT_FUNC(__cxa_atexit); 808 #endif 809 810 #if ASAN_INTERCEPT_FORK 811 ASAN_INTERCEPT_FUNC(fork); 812 #endif 813 814 // Some Windows-specific interceptors. 815 #if SANITIZER_WINDOWS 816 InitializeWindowsInterceptors(); 817 #endif 818 819 VReport(1, "AddressSanitizer: libc interceptors initialized\n"); 820 } 821 822 } // namespace __asan 823