asan_interceptors.cc revision a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808
1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_interceptors.cc ----------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 12d47189c1b63a4de755d7ec071f8d56c8d01cc667Kostya Serebryany// Intercept various libc functions. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 1705bf9a51dfeac0f84f6dbc2dacf987249c0fc612Alexander Potapenko#include "asan_intercepted_functions.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 20487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_report.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h" 234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#include "asan_thread_registry.h" 245b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov#include "interception/interception.h" 25c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 26c0d78c1de1f2607c874020d27b72cf989c5ce092Alexey Samsonov 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 29a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany// Return true if we can quickly decide that the region is unpoisoned. 30a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryanystatic inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { 31a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany if (size == 0) return true; 32a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany if (size <= 32) 33a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany return !AddressIsPoisoned(beg) && 34a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany !AddressIsPoisoned(beg + size - 1) && 35a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany !AddressIsPoisoned(beg + size / 2); 36a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany return false; 37a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany} 38a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// and ASAN_WRITE_RANGE as macro instead of function so 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// that no extra frames are created, and stack trace contains 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// relevant information only. 43eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany// We check all shadow bytes. 44589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 45589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov uptr __offset = (uptr)(offset); \ 46589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov uptr __size = (uptr)(size); \ 47a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ 48a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany __asan_region_is_poisoned(__offset, __size)) { \ 49589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov GET_CURRENT_PC_BP_SP; \ 50589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \ 51589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov } \ 52589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov } while (0) 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 54eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false) 55eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true); 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case. 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames. 603f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, uptr length1, 613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany const char *offset2, uptr length2) { 620985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 64c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const char *offset1 = (const char*)_offset1; \ 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const char *offset2 = (const char*)_offset2; \ 670985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (RangesOverlap(offset1, length1, offset2, length2)) { \ 68a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FATAL_HERE; \ 69487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ 70487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov offset2, length2, &stack); \ 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } \ 72e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 74e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \ 75e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany CHECK(!asan_init_is_running); \ 76e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (!asan_inited) { \ 77e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany __asan_init(); \ 78e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } \ 79e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 81c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 8281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN 833f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (REAL(strnlen) != 0) { 8409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strnlen)(s, maxlen); 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 86f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif 87c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov return internal_strnlen(s, maxlen); 88a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany} 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 90c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid SetThreadName(const char *name) { 91c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany AsanThread *t = asanThreadRegistry().GetCurrent(); 92c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany if (t) 93c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany t->summary()->set_name(name); 94c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany} 95c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 10182a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 10282a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov ASAN_WRITE_RANGE(ptr, size) 103996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 104bee7415a86d9437659d09f034c346794bf15c2abEvgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 10582a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov do { \ 10682a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov ctx = 0; \ 10782a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov (void)ctx; \ 10882a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov ENSURE_ASAN_INITED(); \ 10982a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov } while (false) 110996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false) 111996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false) 112996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 1134f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc" 1148530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany 115600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 1164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany AsanThread *t = (AsanThread*)arg; 1174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany asanThreadRegistry().SetCurrent(t); 1184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return t->ThreadStart(); 1194803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 1204803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 121fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE 122b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread, 123b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov void *attr, void *(*start_routine)(void*), void *arg) { 124a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 125e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 12655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 12755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov asanThreadRegistry().RegisterThread(t); 12809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(pthread_create)(thread, attr, asan_thread_start, t); 1294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 130fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif // ASAN_INTERCEPT_PTHREAD_CREATE 1314803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 13234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 133f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) { 134034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko if (!AsanInterceptsSignal(signum)) { 135034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko return REAL(signal)(signum, handler); 1364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 1373f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 1384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 1394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 140da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 141da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov struct sigaction *oldact) { 142034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko if (!AsanInterceptsSignal(signum)) { 143034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko return REAL(sigaction)(signum, act, oldact); 1444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 145034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko return 0; 1464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 14734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#elif ASAN_POSIX 14834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// We need to have defined REAL(sigaction) on posix systems. 14934a3202a2c22816a6da66959e266a2d078ded37bAlexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 15034a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov struct sigaction *oldact); 15134a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 1530870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT 15457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 15557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov // Align to page size. 15657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov uptr PageSize = GetPageSizeCached(); 15757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov uptr bottom = stack & ~(PageSize - 1); 15857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ssize += stack - bottom; 15957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ssize = RoundUpTo(ssize, PageSize); 16057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 161541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany if (ssize && ssize <= kMaxSaneContextStackSize) { 16257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov PoisonShadow(bottom, ssize, 0); 16357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov } 16457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov} 16557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov 1660870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 1670870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov struct ucontext_t *ucp) { 1680870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov static bool reported_warning = false; 1690870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov if (!reported_warning) { 1700870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 1710870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov "functions and may produce false positives in some cases!\n"); 1720870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov reported_warning = true; 1730870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov } 1740870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // Clear shadow memory for new context (it may share stack 1750870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // with current context). 17657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov uptr stack, ssize; 17757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ReadContextStack(ucp, &stack, &ssize); 17857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ClearShadowMemoryForContextStack(stack, ssize); 1790870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov int res = REAL(swapcontext)(oucp, ucp); 1800870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // swapcontext technically does not return, but program may swap context to 1810870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // "oucp" later, that would look as if swapcontext() returned 0. 1820870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // We need to clear shadow for ucp once again, as it may be in arbitrary 1830870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // state. 18457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ClearShadowMemoryForContextStack(stack, ssize); 1850870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov return res; 1860870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} 18757db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov#endif // ASAN_INTERCEPT_SWAPCONTEXT 1880870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 189f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) { 190f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 19109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(longjmp)(env, val); 1924803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 1934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 194fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP 195f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) { 196f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 19709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(_longjmp)(env, val); 1984803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 199fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 2004803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 201fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP 202f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) { 203f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 20409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(siglongjmp)(env, val); 2054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 20607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 2074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 208fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW 209f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 21009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov CHECK(REAL(__cxa_throw)); 211f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 21209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(__cxa_throw)(a, b, c); 2134803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2144803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif 2154803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2164803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends. 2174803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 2184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success). 2194803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() { 2204803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany static bool printed = 0; 2214803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (printed) return; 2224803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany printed = true; 2234803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 2244803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2253389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 226f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonovextern "C" { 22700f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlock, const void *addr, uptr len) { 2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2304803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2313389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 23200f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlock, const void *addr, uptr len) { 2334803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2354803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2363389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 23700f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlockall, int flags) { 2384803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2394803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2404803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2413389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 24200f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlockall, void) { 2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2464803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} // extern "C" 2474803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 24852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) { 24952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 25052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 25152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 25252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) { 2538898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov int c1_low = ToLower(c1); 2548898102a6b1479a9af65857ccbbc1c329a4d9187Alexey Samsonov int c2_low = ToLower(c2); 25552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return c1_low - c2_low; 25652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 25752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 2583f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 25950f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_memcmp(a1, a2, size); 26052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ENSURE_ASAN_INITED(); 26152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany unsigned char c1 = 0, c2 = 0; 26252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany const unsigned char *s1 = (const unsigned char*)a1; 26352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany const unsigned char *s2 = (const unsigned char*)a2; 2643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr i; 26552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany for (i = 0; i < size; i++) { 26652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany c1 = s1[i]; 26752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany c2 = s2[i]; 26852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany if (c1 != c2) break; 26952fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany } 27052fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 27152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 27252fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return CharCmp(c1, c2); 27352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 27452fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 2753f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 27650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_memcpy(to, from, size); 2771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // memcpy is called during __asan_init() from the internals 2781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // of printf(...). 2791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 28009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(memcpy)(to, from, size); 2811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 282e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 283cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_intrin) { 284c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany if (to != from) { 285c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany // We do not treat memcpy with to==from as a bug. 286c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany // See http://llvm.org/bugs/show_bug.cgi?id=11763. 287c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 288c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany } 289c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_READ_RANGE(from, size); 290c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_WRITE_RANGE(to, size); 2911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 292f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 293f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 294f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko return internal_memcpy(to, from, size); 2951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 2973f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 2983e8458ab54c7cbaec45e367b2da909c6f94b291cAlexander Potapenko if (!asan_inited) return internal_memmove(to, from, size); 299a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov if (asan_init_is_running) { 300a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov return REAL(memmove)(to, from, size); 301a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov } 302e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 303cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_intrin) { 304c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_READ_RANGE(from, size); 305c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_WRITE_RANGE(to, size); 3061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 307f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 308f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 309f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko return internal_memmove(to, from, size); 3101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3123f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memset, void *block, int c, uptr size) { 31350f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_memset(block, c, size); 314ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko // memset is called inside Printf. 315e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (asan_init_is_running) { 31609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(memset)(block, c, size); 317e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } 318e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 319cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_intrin) { 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(block, size); 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 32209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(memset)(block, c, size); 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 325f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) { 32650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strchr(str, c); 3278d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 3288d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko // used. 3298d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko if (asan_init_is_running) { 3308d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko return REAL(strchr)(str, c); 3318d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko } 332e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 33309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov char *result = REAL(strchr)(str, c); 334cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 3353f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 3361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(str, bytes_read); 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return result; 3391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 341fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX 342fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 3434b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c) 344adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov ALIAS(WRAPPER_NAME(strchr)); 345fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else 346b4fefa713da3dabda1cd83ae4182c71f1683f02cAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c) 347fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif 348fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif // ASAN_INTERCEPT_INDEX 349af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany 35037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to| 35137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length. 352f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 3530985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ENSURE_ASAN_INITED(); 354cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 3553f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr from_length = REAL(strlen)(from); 3560985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ASAN_READ_RANGE(from, from_length + 1); 35737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko uptr to_length = REAL(strlen)(to); 35837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ASAN_READ_RANGE(to, to_length); 35937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ASAN_WRITE_RANGE(to + to_length, from_length + 1); 36037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // If the copying actually happens, the |from| string should not overlap 36137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // with the resulting string starting at |to|, which has a length of 36237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // to_length + from_length + 1. 3630985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (from_length > 0) { 36437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 36537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko from, from_length + 1); 3660985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 3670985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 36809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strcat)(to, from); // NOLINT 3690985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany} 3700985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany 371c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 372c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ENSURE_ASAN_INITED(); 37337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko if (flags()->replace_str) { 374c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov uptr from_length = MaybeRealStrnlen(from, size); 37537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko uptr copy_length = Min(size, from_length + 1); 37637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ASAN_READ_RANGE(from, copy_length); 377c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov uptr to_length = REAL(strlen)(to); 378c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_READ_RANGE(to, to_length); 379c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_WRITE_RANGE(to + to_length, from_length + 1); 380c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov if (from_length > 0) { 38137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 38237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko from, copy_length); 383c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov } 384c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov } 385c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov return REAL(strncat)(to, from, size); 386c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov} 387c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov 388f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 38950f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strcmp(s1, s2); 390fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (asan_init_is_running) { 391fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov return REAL(strcmp)(s1, s2); 3921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3938648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany ENSURE_ASAN_INITED(); 3941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1, c2; 3953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr i; 3961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; ; i++) { 3971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c1 = (unsigned char)s1[i]; 3981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 3991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 4001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s1, i + 1); 4021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s2, i + 1); 4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 406f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 40769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__) 408beda44f87166f91dbeef3d174d77395653bead4dAlexander Potapenko if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 4090ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 4101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strcpy is called from malloc_default_purgeable_zone() 4111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 4121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 41309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strcpy)(to, from); // NOLINT 4141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 415e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 416cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4173f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr from_size = REAL(strlen)(from) + 1; 418c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, from_size); 4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(to, from_size); 4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 42209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strcpy)(to, from); // NOLINT 4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 425fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP 426f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) { 42769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__) 42871578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko // FIXME: because internal_strdup() uses InternalAlloc(), which currently 42971578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko // just calls malloc() on Mac, we can't use internal_strdup() with the 43071578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc 43171578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko // starts using mmap() instead. 43271578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123. 43371578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko if (!asan_inited) return REAL(strdup)(s); 43471578faf4eb8e61aefb3121e1945cc47f07cea0dAlexander Potapenko#endif 43550f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strdup(s); 436e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 437cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4383f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr length = REAL(strlen)(s); 4391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, length + 1); 4401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 44109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strdup)(s); 4421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 443fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 4441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4453f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strlen, const char *s) { 44650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strlen(s); 4471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strlen is called from malloc_default_purgeable_zone() 4481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 45009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strlen)(s); 4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 452e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 4533f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr length = REAL(strlen)(s); 454cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, length + 1); 4561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return length; 4581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 460fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 461fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey SamsonovINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { 462fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ENSURE_ASAN_INITED(); 463fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov unsigned char c1, c2; 464fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov uptr i; 465fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov for (i = 0; ; i++) { 466fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov c1 = (unsigned char)s1[i]; 467fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov c2 = (unsigned char)s2[i]; 468fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 469fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov } 470fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_READ_RANGE(s1, i + 1); 471fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_READ_RANGE(s2, i + 1); 472fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov return CharCaseCmp(c1, c2); 473fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov} 474fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov 4753f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) { 476af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany ENSURE_ASAN_INITED(); 477af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany unsigned char c1 = 0, c2 = 0; 4783f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr i; 479f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov for (i = 0; i < n; i++) { 480af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany c1 = (unsigned char)s1[i]; 481af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany c2 = (unsigned char)s2[i]; 482af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 483af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany } 484f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov ASAN_READ_RANGE(s1, Min(i + 1, n)); 485f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov ASAN_READ_RANGE(s2, Min(i + 1, n)); 486af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany return CharCaseCmp(c1, c2); 487af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany} 488fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 489af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany 4903f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 49150f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strncmp(s1, s2, size); 4921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strncmp is called from malloc_default_purgeable_zone() 4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 4941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 49509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strncmp)(s1, s2, size); 4961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4978648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany ENSURE_ASAN_INITED(); 4981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1 = 0, c2 = 0; 4993f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr i; 5001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; i < size; i++) { 5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c1 = (unsigned char)s1[i]; 5021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 5031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 5041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5052d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 5062d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 5071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 5081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5103f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 511e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 512cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 513c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 514c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 5151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, from_size); 5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(to, size); 5171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 51809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strncpy)(to, from, size); 5191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 52181a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN 5223f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 523e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 5243f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr length = REAL(strnlen)(s, maxlen); 525cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 5262d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 5271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return length; 5291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 53081a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif // ASAN_INTERCEPT_STRNLEN 531547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 5328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) { 5338f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov return (base == 0) || (2 <= base && base <= 36); 5348f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov} 5358f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov 5368f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 5373f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(endptr != 0); 5388f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (nptr == *endptr) { 5398f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // No digits were found at strtol call, we need to find out the last 5408f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // symbol accessed by strtoll on our own. 5418f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // We get this symbol by skipping leading blanks and optional +/- sign. 5428f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov while (IsSpace(*nptr)) nptr++; 5438f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (*nptr == '+' || *nptr == '-') nptr++; 5448f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov *endptr = (char*)nptr; 5458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 5468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov CHECK(*endptr >= nptr); 54784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov} 54884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 549847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr, // NOLINT 55084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov char **endptr, int base) { 55184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ENSURE_ASAN_INITED(); 552cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 553847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(strtol)(nptr, endptr, base); 55484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 55584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov char *real_endptr; 556847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 5573f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (endptr != 0) { 55884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov *endptr = real_endptr; 55984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 5608f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (IsValidStrtolBase(base)) { 5618f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 56284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 56384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 56484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov return result; 56584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov} 56684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 567847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) { 56869563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__) 5690ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko if (!asan_inited) return REAL(atoi)(nptr); 5700ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 571847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 572cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 573847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atoi)(nptr); 574847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 575847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 576847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // "man atoi" tells that behavior of atoi(nptr) is the same as 5773f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 578847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // parsed integer can't be stored in *long* type (even if it's 579847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // different from int). So, we just imitate this behavior. 580847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov int result = REAL(strtol)(nptr, &real_endptr, 10); 581847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 582847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 583847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 584847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 585847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 586847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) { // NOLINT 58769563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__) 5880ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko if (!asan_inited) return REAL(atol)(nptr); 5890ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 590847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 591cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 592847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atol)(nptr); 593847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 594847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 595847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 596847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 597847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 598847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 599847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 600847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 601847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 602847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 6038f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov char **endptr, int base) { 6048f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ENSURE_ASAN_INITED(); 605cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 606847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(strtoll)(nptr, endptr, base); 6078f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 6088f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov char *real_endptr; 609847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 6103f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (endptr != 0) { 6118f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov *endptr = real_endptr; 6128f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 613847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // If base has unsupported value, strtoll can exit with EINVAL 614847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // without reading any characters. So do additional checks only 615847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // if base is valid. 6168f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (IsValidStrtolBase(base)) { 6178f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 6188f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 6198f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 6208f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov return result; 6218f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov} 6228f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov 623847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 624847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 625cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 626847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atoll)(nptr); 627847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 628847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 629847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 630847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 631847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 632847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 633847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 634847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 635847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 636580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#define ASAN_INTERCEPT_FUNC(name) do { \ 637cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 638580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 639580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov } while (0) 640580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov 641600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32) 642600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread, 6433f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany void* security, uptr stack_size, 644600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov DWORD (__stdcall *start_routine)(void*), void* arg, 645600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov DWORD flags, void* tid) { 646a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 647e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 648600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 649600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov asanThreadRegistry().RegisterThread(t); 650600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov return REAL(CreateThread)(security, stack_size, 651600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov asan_thread_start, t, flags, tid); 652600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov} 653600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 654600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan { 655600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() { 656580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(CreateThread); 657600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov} 658600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 659600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov} // namespace __asan 660600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif 661600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 662547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1 663547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan { 664547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() { 665fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany static bool was_called_once; 666fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany CHECK(was_called_once == false); 667fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany was_called_once = true; 66869563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if defined(__APPLE__) 6690ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko return; 67069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#else 6718530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany SANITIZER_COMMON_INTERCEPTORS_INIT; 6728530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany 67307bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intercept mem* functions. 674580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memcmp); 675580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memmove); 676580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memset); 67738dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 678580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memcpy); 679573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko } 68007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov 68107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intercept str* functions. 682580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcat); // NOLINT 683580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strchr); 684580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcmp); 685580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 686580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strlen); 687c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_INTERCEPT_FUNC(strncat); 688580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strncmp); 689580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strncpy); 690fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 691580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcasecmp); 692580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strncasecmp); 693fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 694fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP 695fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(strdup); 696fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 697fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN 698fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(strnlen); 699fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 70069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 701580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(index); 70207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 7035b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov 704580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atoi); 705580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atol); 706580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strtol); 707847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 708580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atoll); 709580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strtoll); 71084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif 71184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 712f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT_MLOCKX 71300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko // Intercept mlock/munlock. 71400f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(mlock); 71500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(munlock); 71600f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(mlockall); 71700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(munlockall); 718f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#endif 71900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko 72007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intecept signal- and jump-related functions. 721580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(longjmp); 72234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 723580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(sigaction); 724580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(signal); 725919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif 7260870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT 7270870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov ASAN_INTERCEPT_FUNC(swapcontext); 7280870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif 729fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP 730580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(_longjmp); 731fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 732fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP 733580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(siglongjmp); 734fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 735fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov 736fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov // Intercept exception handling functions. 737fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW 738fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov INTERCEPT_FUNCTION(__cxa_throw); 7393e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif 7403e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 74107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intercept threading-related functions 742fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE 743580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(pthread_create); 74407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 74507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov 746600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov // Some Windows-specific interceptors. 747600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#if defined(_WIN32) 748600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov InitializeWindowsInterceptors(); 749600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif 750600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 751cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity > 0) { 7522962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko Report("AddressSanitizer: libc interceptors initialized\n"); 753547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany } 7542673fd8406197c42f16cede6d287f72169298c2eKostya Serebryany#endif // __APPLE__ 755547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany} 756547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 757547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany} // namespace __asan 758