asan_interceptors.cc revision 8bd5e74fa9d37a182088114918380e255e22e493
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" 207e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_report.h" 21487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_stack.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya 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); \ 471b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany uptr __bad = 0; \ 48a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808Kostya Serebryany if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ 491b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany (__bad = __asan_region_is_poisoned(__offset, __size))) { \ 50589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov GET_CURRENT_PC_BP_SP; \ 511b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \ 52589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov } \ 53589dcdaa520de1033a0f6112c9b67ab9eb7931afEvgeniy Stepanov } while (0) 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 55eb2809311c94b73c269ccef8d68ae368642e5754Kostya Serebryany#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false) 56341b9e63f63a8eacf1b699d4c79edee55241ebe6Evgeniy Stepanov#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true); 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Behavior of functions like "memcpy" or "strcpy" is undefined 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// if memory intervals overlap. We report error in this case. 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Macro is used to avoid creation of new frames. 613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic inline bool RangesOverlap(const char *offset1, uptr length1, 623f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany const char *offset2, uptr length2) { 630985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 65c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const char *offset1 = (const char*)_offset1; \ 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany const char *offset2 = (const char*)_offset2; \ 680985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (RangesOverlap(offset1, length1, offset2, length2)) { \ 69a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_FATAL_HERE; \ 70487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ 71487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov offset2, length2, &stack); \ 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } \ 73e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 75e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#define ENSURE_ASAN_INITED() do { \ 76e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany CHECK(!asan_init_is_running); \ 77e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (!asan_inited) { \ 78e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany __asan_init(); \ 79e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } \ 80e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany} while (0) 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 82c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonovstatic inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 8381a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN 843f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (REAL(strnlen) != 0) { 8509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strnlen)(s, maxlen); 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 87f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov#endif 88c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov return internal_strnlen(s, maxlen); 89a4ccf878e464d29a4a18756c5c4f626dc530a12eKostya Serebryany} 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 91c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryanyvoid SetThreadName(const char *name) { 9289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov AsanThread *t = asanThreadRegistry().GetCurrent(); 93c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany if (t) 94def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov t->summary()->set_name(name); 95c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany} 96c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany 978cde99fb9df913aaf7c1715cd134110dd5a15834Dmitry Vyukov} // namespace __asan 9814dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov 9914dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov// ---------------------- Wrappers ---------------- {{{1 10014dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukovusing namespace __asan; // NOLINT 10114dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukov 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(ptr, size) 1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany do { \ 10712eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov ctx = 0; \ 10812eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov (void)ctx; \ 10912eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov ENSURE_ASAN_INITED(); \ 110a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov } while (false) 111a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false) 112a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false) 113a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 114a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc" 115a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov 116a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 117a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov AsanThread *t = (AsanThread*)arg; 118a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov asanThreadRegistry().SetCurrent(t); 119a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov return t->ThreadStart(); 120a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov} 121a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov 122a537ea99d3dcc4b2dc0033aee7ad5cb1b378efc7Evgeniy Stepanov#if ASAN_INTERCEPT_PTHREAD_CREATE 1233fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread, 1243fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov void *attr, void *(*start_routine)(void*), void *arg) { 1253fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov GET_STACK_TRACE_THREAD; 12682a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 12782a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 128996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov asanThreadRegistry().RegisterThread(t); 129b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko return REAL(pthread_create)(thread, attr, asan_thread_start, t); 130b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko} 131b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko#endif // ASAN_INTERCEPT_PTHREAD_CREATE 132b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko 133b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 134b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander PotapenkoINTERCEPTOR(void*, signal, int signum, void *handler) { 135b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko if (!AsanInterceptsSignal(signum)) { 1369d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov return REAL(signal)(signum, handler); 1379d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov } 1389d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov return 0; 1399d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov} 1409d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov 1419d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy StepanovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 1429d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov struct sigaction *oldact) { 1439d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov if (!AsanInterceptsSignal(signum)) { 1449d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov return REAL(sigaction)(signum, act, oldact); 14582a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov } 146996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov return 0; 147e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov} 148e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov#elif ASAN_POSIX 149e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov// We need to have defined REAL(sigaction) on posix systems. 150e767e350b1a6461bc29cfea28af75f908d7da56eDmitry VyukovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 1515cf2c460e96e593b1c772f1b02d3a217f4837fdcDmitry Vyukov struct sigaction *oldact); 152e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 153e767e350b1a6461bc29cfea28af75f908d7da56eDmitry Vyukov 154e18e3f07802c420eb4b2da407e148084b75cecc9Evgeniy Stepanov#if ASAN_INTERCEPT_SWAPCONTEXT 15514dd980b384ad859099b499e12f320c4791fb674Dmitry Vyukovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 1564f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov // Align to page size. 1578530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany uptr PageSize = GetPageSizeCached(); 158881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov uptr bottom = stack & ~(PageSize - 1); 159881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov ssize += stack - bottom; 160ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov ssize = RoundUpTo(ssize, PageSize); 161ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 162dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov if (ssize && ssize <= kMaxSaneContextStackSize) { 163dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov PoisonShadow(bottom, ssize, 0); 164ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov } 165ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov} 166ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov 167dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy StepanovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 168dfab31b93e954ee42622a13dd79e9e1092346035Evgeniy Stepanov struct ucontext_t *ucp) { 169ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov static bool reported_warning = false; 170881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov if (!reported_warning) { 171881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 172600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov "functions and may produce false positives in some cases!\n"); 1734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany reported_warning = true; 17489c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov } 175def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // Clear shadow memory for new context (it may share stack 1764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany // with current context). 1774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany uptr stack, ssize; 178fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ReadContextStack(ucp, &stack, &ssize); 179b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov ClearShadowMemoryForContextStack(stack, ssize); 180b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov int res = REAL(swapcontext)(oucp, ucp); 181c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev // swapcontext technically does not return, but program may swap context to 182bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov // "oucp" later, that would look as if swapcontext() returned 0. 1839465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov // We need to clear shadow for ucp once again, as it may be in arbitrary 1849465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov // state. 185a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany ClearShadowMemoryForContextStack(stack, ssize); 186def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return res; 187def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 188bb6bc9a0ae534ada3c0c2c226462c351c078d761Evgeniy Stepanov#endif // ASAN_INTERCEPT_SWAPCONTEXT 189def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 19089c1384464848c1ad041becf8b97936fa10de21bAlexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) { 191def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov __asan_handle_no_return(); 192def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov REAL(longjmp)(env, val); 193def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 19409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov 1954803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#if ASAN_INTERCEPT__LONGJMP 196fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) { 1974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany __asan_handle_no_return(); 19834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov REAL(_longjmp)(env, val); 199f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov} 200332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov#endif 201034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko 2024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#if ASAN_INTERCEPT_SIGLONGJMP 2033f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void, siglongjmp, void *env, int val) { 2044803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany __asan_handle_no_return(); 2054803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany REAL(siglongjmp)(env, val); 206da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov} 207da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov#endif 208332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov 209034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko#if ASAN_INTERCEPT___CXA_THROW 2104803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya SerebryanyINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 211034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko CHECK(REAL(__cxa_throw)); 2124803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany __asan_handle_no_return(); 213e1ba0009d5be18d513ffd29c1b6fccea1a3bffa0Evgeniy Stepanov REAL(__cxa_throw)(a, b, c); 21434a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov} 21534a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif 216fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov 21734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// intercept mlock and friends. 2184803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 2190870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov// All functions return 0 (success). 22057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void MlockIsUnsupported() { 22157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov static bool printed = 0; 22257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov if (printed) return; 22357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov printed = true; 22457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 22557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov} 22657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov 227541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryanyextern "C" { 22857db4bae483e7268dd7fc5bc42b0e55564014048Alexey SamsonovINTERCEPTOR(int, mlock, const void *addr, uptr len) { 22957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov MlockIsUnsupported(); 23057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov return 0; 23157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov} 2320870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 2330870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, munlock, const void *addr, uptr len) { 2340870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov MlockIsUnsupported(); 2350870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov return 0; 2360870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} 2370870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 2380870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, mlockall, int flags) { 2390870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov MlockIsUnsupported(); 2400870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov return 0; 2410870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} 24257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov 24357db4bae483e7268dd7fc5bc42b0e55564014048Alexey SamsonovINTERCEPTOR(int, munlockall, void) { 24457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov MlockIsUnsupported(); 2450870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov return 0; 2460870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} 2470870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} // extern "C" 2480870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 2490870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonovstatic inline int CharCmp(unsigned char c1, unsigned char c2) { 25057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 2510870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} 2520870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 25357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic inline int CharCaseCmp(unsigned char c1, unsigned char c2) { 2540870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov int c1_low = ToLower(c1); 255f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov int c2_low = ToLower(c2); 256f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany return c1_low - c2_low; 25709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov} 2584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2594803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 260fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (!asan_inited) return internal_memcmp(a1, a2, size); 261f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov ENSURE_ASAN_INITED(); 262f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany if (flags()->replace_intrin) { 26309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov if (flags()->strict_memcmp) { 2644803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany // Check the entire regions even if the first bytes of the buffers are 265fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov // different. 2664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany ASAN_READ_RANGE(a1, size); 267fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_READ_RANGE(a2, size); 268f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov // Fallthrough to REAL(memcmp) below. 269f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany } else { 27009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov unsigned char c1 = 0, c2 = 0; 2714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany const unsigned char *s1 = (const unsigned char*)a1; 27207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov const unsigned char *s2 = (const unsigned char*)a2; 2734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany uptr i; 274fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov for (i = 0; i < size; i++) { 275f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov c1 = s1[i]; 27609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov c2 = s2[i]; 277f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany if (c1 != c2) break; 27809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov } 2794803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 2804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return CharCmp(c1, c2); 2824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 2834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 2844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return REAL(memcmp(a1, a2, size)); 2854803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2868d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov 2874803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 2884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (!asan_inited) return internal_memcpy(to, from, size); 2896866dba92ac842fc513ba339ba849a953ffb7507Dmitry Vyukov // memcpy is called during __asan_init() from the internals 290eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov // of printf(...). 291eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov if (asan_init_is_running) { 292eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov return REAL(memcpy)(to, from, size); 2934803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 2943389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov ENSURE_ASAN_INITED(); 29500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko if (flags()->replace_intrin) { 2964803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (to != from) { 2974803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany // We do not treat memcpy with to==from as a bug. 2984803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany // See http://llvm.org/bugs/show_bug.cgi?id=11763. 2993389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 30000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko } 3014803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany ASAN_READ_RANGE(from, size); 3024803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany ASAN_WRITE_RANGE(to, size); 3034803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 3043389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 30500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 3064803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return internal_memcpy(to, from, size); 3074803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 3084803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 3093389b8ea81f51a28365a421b2646d594bac490f5Alexey SamsonovINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 31000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko if (!asan_inited) return internal_memmove(to, from, size); 3114803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (asan_init_is_running) { 3124803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return REAL(memmove)(to, from, size); 3134803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 3144803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany ENSURE_ASAN_INITED(); 31552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany if (flags()->replace_intrin) { 31652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ASAN_READ_RANGE(from, size); 31752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ASAN_WRITE_RANGE(to, size); 31852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany } 3193f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 32050f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 32152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return internal_memmove(to, from, size); 3221b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany} 3238bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko 3248bd5e74fa9d37a182088114918380e255e22e493Alexander PotapenkoINTERCEPTOR(void*, memset, void *block, int c, uptr size) { 3258bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (!asan_inited) return internal_memset(block, c, size); 3268bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko // memset is called inside Printf. 3278bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (asan_init_is_running) { 3288bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko return REAL(memset)(block, c, size); 3298bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko } 3308bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko ENSURE_ASAN_INITED(); 3318bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (flags()->replace_intrin) { 3328bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko ASAN_WRITE_RANGE(block, size); 3338bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko } 3348bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko return REAL(memset)(block, c, size); 3358bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko} 3368bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko 3378bd5e74fa9d37a182088114918380e255e22e493Alexander PotapenkoINTERCEPTOR(char*, strchr, const char *str, int c) { 3388bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (!asan_inited) return internal_strchr(str, c); 3398bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 3408bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko // used. 3418bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (asan_init_is_running) { 3428bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko return REAL(strchr)(str, c); 34352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany } 3441b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany ENSURE_ASAN_INITED(); 34552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany char *result = REAL(strchr)(str, c); 34652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany if (flags()->replace_str) { 347d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 348d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko ASAN_READ_RANGE(str, bytes_read); 349d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko } 350d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko return result; 351d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko} 352d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko 353d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko#if ASAN_INTERCEPT_INDEX 354d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 355d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoINTERCEPTOR(char*, index, const char *string, int c) 356d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko ALIAS(WRAPPER_NAME(strchr)); 357d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# else 358d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# if defined(__APPLE__) 359d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoDECLARE_REAL(char*, index, const char *string, int c) 360d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoOVERRIDE_FUNCTION(index, strchr); 361d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# else 3623f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyDEFINE_REAL(char*, index, const char *string, int c); 363d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko# endif 36450f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko# endif 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif // ASAN_INTERCEPT_INDEX 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// For both strcat() and strncat() we need to check the validity of |to| 36809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov// argument irrespective of the |from| length. 3691e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 370e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 371cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 372c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany uptr from_length = REAL(strlen)(from); 373c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany ASAN_READ_RANGE(from, from_length + 1); 374c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany uptr to_length = REAL(strlen)(to); 375c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany ASAN_READ_RANGE(to, to_length); 376c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany ASAN_WRITE_RANGE(to + to_length, from_length + 1); 377c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko // If the copying actually happens, the |from| string should not overlap 378c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko // with the resulting string starting at |to|, which has a length of 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // to_length + from_length + 1. 380d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko if (from_length > 0) { 381d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 382f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko from, from_length + 1); 383f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko } 384d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko } 385d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko return REAL(strcat)(to, from); // NOLINT 386d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko} 387d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko 388d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander PotapenkoINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 389d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko ENSURE_ASAN_INITED(); 390d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko if (flags()->replace_str) { 391d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko uptr from_length = MaybeRealStrnlen(from, size); 392d4d7040ee026ab04502c42327ed5081f704a8e3cAlexander Potapenko uptr copy_length = Min(size, from_length + 1); 3931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, copy_length); 3941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uptr to_length = REAL(strlen)(to); 3953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany ASAN_READ_RANGE(to, to_length); 39650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko ASAN_WRITE_RANGE(to + to_length, from_length + 1); 397ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko if (from_length > 0) { 398e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 39909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov from, copy_length); 400e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } 401e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } 402cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov return REAL(strncat)(to, from, size); 4031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 40509672caefb5694f1981a1712fdefa44840a95e67Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 4061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!asan_inited) return internal_strcmp(s1, s2); 4071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 408f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov return REAL(strcmp)(s1, s2); 40950f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko } 4108d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko ENSURE_ASAN_INITED(); 4118d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko unsigned char c1, c2; 4128d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko uptr i; 4138d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko for (i = 0; ; i++) { 4148d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko c1 = (unsigned char)s1[i]; 415e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany c2 = (unsigned char)s2[i]; 41609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov if (c1 != c2 || c1 == '\0') break; 417cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov } 4183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany ASAN_READ_RANGE(s1, i + 1); 4191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s2, i + 1); 4201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 4211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4231e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 424fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if defined(__APPLE__) 425fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 4264b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy Stepanov#endif 42772bbfd4f3a442afde281476bc6bd41b3b2152a4eAlexander Potapenko // strcpy is called from malloc_default_purgeable_zone() 428fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov // in __asan::ReplaceSystemAlloc() on Mac. 42924e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov if (asan_init_is_running) { 43050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko return REAL(strcpy)(to, from); // NOLINT 43150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko } 43250a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko ENSURE_ASAN_INITED(); 433fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov if (flags()->replace_str) { 43450a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko uptr from_size = REAL(strlen)(from) + 1; 435fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 436fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_READ_RANGE(from, from_size); 437af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany ASAN_WRITE_RANGE(to, from_size); 43837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko } 43937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko return REAL(strcpy)(to, from); // NOLINT 440f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov} 4410985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany 442cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov#if ASAN_INTERCEPT_STRDUP 4433f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strdup, const char *s) { 4440985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany#if defined(__APPLE__) 44537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // FIXME: because internal_strdup() uses InternalAlloc(), which currently 44637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // just calls malloc() on Mac, we can't use internal_strdup() with the 44737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc 44837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // starts using mmap() instead. 44937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123. 45037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko if (!asan_inited) return REAL(strdup)(s); 4510985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany#endif 45237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko if (!asan_inited) return internal_strdup(s); 45337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ENSURE_ASAN_INITED(); 4540985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (flags()->replace_str) { 4550985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany uptr length = REAL(strlen)(s); 45609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov ASAN_READ_RANGE(s, length + 1); 4570985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 4580985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany return REAL(strdup)(s); 459c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov} 460c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov#endif 46137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko 462c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey SamsonovINTERCEPTOR(uptr, strlen, const char *s) { 46337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko if (!asan_inited) return internal_strlen(s); 46437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // strlen is called from malloc_default_purgeable_zone() 465c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov // in __asan::ReplaceSystemAlloc() on Mac. 466c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov if (asan_init_is_running) { 467c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov return REAL(strlen)(s); 468c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov } 46937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ENSURE_ASAN_INITED(); 47037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko uptr length = REAL(strlen)(s); 471c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov if (flags()->replace_str) { 472c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_READ_RANGE(s, length + 1); 473c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov } 474c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov return length; 475c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov} 476f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov 47724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 478beda44f87166f91dbeef3d174d77395653bead4dAlexander PotapenkoINTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { 4790ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko ENSURE_ASAN_INITED(); 4801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1, c2; 4811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uptr i; 4821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; ; i++) { 48309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov c1 = (unsigned char)s1[i]; 4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 485e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 486cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov } 4873f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany ASAN_READ_RANGE(s1, i + 1); 488c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany ASAN_READ_RANGE(s2, i + 1); 4891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCaseCmp(c1, c2); 4901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 49209672caefb5694f1981a1712fdefa44840a95e67Alexey SamsonovINTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) { 4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ENSURE_ASAN_INITED(); 4941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1 = 0, c2 = 0; 495fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov uptr i; 496f2598fc21bf651d23feab396a7581d48c01c3be5Alexey Samsonov for (i = 0; i < n; i++) { 49750f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko c1 = (unsigned char)s1[i]; 498e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany c2 = (unsigned char)s2[i]; 499d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; 500cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov } 5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, n)); 5021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, n)); 503d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov return CharCaseCmp(c1, c2); 504d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov} 505d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov#endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 506d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov 5071e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 508fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (!asan_inited) return internal_strncmp(s1, s2, size); 5091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strncmp is called from malloc_default_purgeable_zone() 5103f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 51150f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (asan_init_is_running) { 5121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return REAL(strncmp)(s1, s2, size); 5131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ENSURE_ASAN_INITED(); 51509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov unsigned char c1 = 0, c2 = 0; 5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uptr i; 517e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany for (i = 0; i < size; i++) { 5183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany c1 = (unsigned char)s1[i]; 519cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov c2 = (unsigned char)s2[i]; 5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 5211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 5231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 5241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 525b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner} 526b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner 527b99228de65b408b0acd9618b92774fb8add7e482Reid KlecknerINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 528b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner ENSURE_ASAN_INITED(); 529b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner if (flags()->replace_str) { 530b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 531b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 532b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner ASAN_READ_RANGE(from, from_size); 533b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner ASAN_WRITE_RANGE(to, size); 5343f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany } 535e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany return REAL(strncpy)(to, from, size); 536cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov} 537c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov 538c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany#if ASAN_INTERCEPT_STRNLEN 5391e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 5401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ENSURE_ASAN_INITED(); 5411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uptr length = REAL(strnlen)(s, maxlen); 54209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov if (flags()->replace_str) { 5431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 5441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 54581a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov return length; 5463f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany} 547e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany#endif // ASAN_INTERCEPT_STRNLEN 5483f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany 549cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) { 5502d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany return (base == 0) || (2 <= base && base <= 36); 5511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 55481a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov CHECK(endptr != 0); 555547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany if (nptr == *endptr) { 5568f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // No digits were found at strtol call, we need to find out the last 5578f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // symbol accessed by strtoll on our own. 5588f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // We get this symbol by skipping leading blanks and optional +/- sign. 5598f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov while (IsSpace(*nptr)) nptr++; 5608f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (*nptr == '+' || *nptr == '-') nptr++; 561a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany *endptr = (char*)nptr; 5628f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 5638f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov CHECK(*endptr >= nptr); 5648f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov} 5658f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov 5668f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey SamsonovINTERCEPTOR(long, strtol, const char *nptr, // NOLINT 5678f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov char **endptr, int base) { 5688f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ENSURE_ASAN_INITED(); 5698f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (!flags()->replace_str) { 5708f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov return REAL(strtol)(nptr, endptr, base); 57184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 57284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov char *real_endptr; 573847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 57484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov if (endptr != 0) { 57584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov *endptr = real_endptr; 576cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov } 577847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov if (IsValidStrtolBase(base)) { 57884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 57984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 580847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 5813f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return result; 58284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov} 58384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 5848f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) { 5858f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov#if defined(__APPLE__) 58684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov if (!asan_inited) return REAL(atoi)(nptr); 58784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif 58884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ENSURE_ASAN_INITED(); 58984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov if (!flags()->replace_str) { 59084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov return REAL(atoi)(nptr); 591847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 59224e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov char *real_endptr; 5930ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko // "man atoi" tells that behavior of atoi(nptr) is the same as 5940ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 595847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // parsed integer can't be stored in *long* type (even if it's 596cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov // different from int). So, we just imitate this behavior. 597847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov int result = REAL(strtol)(nptr, &real_endptr, 10); 598847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 599847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 600847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 6013f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany} 602847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 603847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) { // NOLINT 604847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if defined(__APPLE__) 605847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov if (!asan_inited) return REAL(atol)(nptr); 606847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif 607847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 608847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov if (!flags()->replace_str) { 609847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atol)(nptr); 610847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 61124e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov char *real_endptr; 6120ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 6130ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko FixRealStrtolEndptr(nptr, &real_endptr); 614847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 615cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov return result; 616847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 617847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 618847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 619847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 620847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char **endptr, int base) { 621847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 622847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov if (!flags()->replace_str) { 623847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(strtoll)(nptr, endptr, base); 624847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 625847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 626847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 6278f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (endptr != 0) { 6288f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov *endptr = real_endptr; 629cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov } 630847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // If base has unsupported value, strtoll can exit with EINVAL 6318f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // without reading any characters. So do additional checks only 6328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // if base is valid. 633847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov if (IsValidStrtolBase(base)) { 6343f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany FixRealStrtolEndptr(nptr, &real_endptr); 6358f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 6368f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 637847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 638847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 639847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 6408f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 6418f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ENSURE_ASAN_INITED(); 6428f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (!flags()->replace_str) { 6438f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov return REAL(atoll)(nptr); 6448f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 6458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov char *real_endptr; 6468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 647847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 648847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 649cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov return result; 650847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 651847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 652847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 653847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#define ASAN_INTERCEPT_FUNC(name) do { \ 654847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 655847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 656847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } while (0) 657847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 658847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if defined(_WIN32) 659847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR_WINAPI(DWORD, CreateThread, 66046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov void* security, uptr stack_size, 66146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov DWORD (__stdcall *start_routine)(void*), void* arg, 66246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov DWORD flags, void* tid) { 66346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov GET_STACK_TRACE_THREAD; 66446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); 66546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); 66646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov asanThreadRegistry().RegisterThread(t); 66746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov return REAL(CreateThread)(security, stack_size, 668b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko asan_thread_start, t, flags, tid); 669b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko} 670b527f7de80001569542e3f0ef4c7f4b0cb15cb67Alexander Potapenko 67146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovnamespace __asan { 67246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovvoid InitializeWindowsInterceptors() { 67346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov ASAN_INTERCEPT_FUNC(CreateThread); 67446efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov} 67546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov 67646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov} // namespace __asan 67746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif 67824e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov 679600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov// ---------------------- InitializeAsanInterceptors ---------------- {{{1 6803f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanynamespace __asan { 681600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeAsanInterceptors() { 682b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov static bool was_called_once; 683bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov CHECK(was_called_once == false); 6849465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov was_called_once = true; 6859465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov#if defined(__APPLE__) 686a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany return; 68789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov#else 688dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov SANITIZER_COMMON_INTERCEPTORS_INIT; 689dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov 6908d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov // Intercept mem* functions. 691dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov ASAN_INTERCEPT_FUNC(memcmp); 692600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(memmove); 693b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov ASAN_INTERCEPT_FUNC(memset); 694600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 695600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(memcpy); 696600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov } 697600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 698580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov // Intercept str* functions. 699600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(strcat); // NOLINT 700600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(strchr); 701600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(strcmp); 702600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 703600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(strlen); 704547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany ASAN_INTERCEPT_FUNC(strncat); 705547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany ASAN_INTERCEPT_FUNC(strncmp); 706547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany ASAN_INTERCEPT_FUNC(strncpy); 707fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 708fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany ASAN_INTERCEPT_FUNC(strcasecmp); 709fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany ASAN_INTERCEPT_FUNC(strncasecmp); 7108530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#endif 7118530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany#if ASAN_INTERCEPT_STRDUP 71207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov ASAN_INTERCEPT_FUNC(strdup); 713580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif 714580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_STRNLEN 715580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strnlen); 71638dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov#endif 717580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 718573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko ASAN_INTERCEPT_FUNC(index); 71907bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 72007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov 721580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atoi); 722580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atol); 723580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strtol); 724580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 725b99228de65b408b0acd9618b92774fb8add7e482Reid Kleckner ASAN_INTERCEPT_FUNC(atoll); 726c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_INTERCEPT_FUNC(strtoll); 727580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif 728fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov 729fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_MLOCKX 730fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov // Intercept mlock/munlock. 731fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(mlock); 732fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(munlock); 733fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(mlockall); 73469563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko ASAN_INTERCEPT_FUNC(munlockall); 735580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif 73607bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov 7375b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov // Intecept signal- and jump-related functions. 738580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(longjmp); 739580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 740580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(sigaction); 741847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_INTERCEPT_FUNC(signal); 742580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#endif 743580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if ASAN_INTERCEPT_SWAPCONTEXT 74484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ASAN_INTERCEPT_FUNC(swapcontext); 74584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif 746f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT__LONGJMP 74700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(_longjmp); 74800f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko#endif 74900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko#if ASAN_INTERCEPT_SIGLONGJMP 75000f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(siglongjmp); 75100f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko#endif 752f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko 75300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko // Intercept exception handling functions. 75407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#if ASAN_INTERCEPT___CXA_THROW 755580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov INTERCEPT_FUNCTION(__cxa_throw); 75634a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif 757580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov 758580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov // Intercept threading-related functions 759919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#if ASAN_INTERCEPT_PTHREAD_CREATE 7600870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov ASAN_INTERCEPT_FUNC(pthread_create); 7610870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif 7620870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 763fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov // Some Windows-specific interceptors. 764580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#if defined(_WIN32) 765fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov InitializeWindowsInterceptors(); 766fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 767580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov 768fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (flags()->verbosity > 0) { 769fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov Report("AddressSanitizer: libc interceptors initialized\n"); 770fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov } 771fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif // __APPLE__ 772fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov} 7733e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 7743e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov} // namespace __asan 77507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov