asan_interceptors.cc revision eaca82cf249021afa31dbc970278f2f28ea2a1aa
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_poisoning.h" 21487fee7f6f7497906a00d7d2fe2c75e6d5d4feb1Alexey Samsonov#include "asan_report.h" 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.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 = GetCurrentThread(); 93c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany if (t) 94def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().SetThreadName(t->tid(), name); 95c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany} 96c20b321d49f0eff60f1394d56e623d8ca94f24d7Kostya Serebryany 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Wrappers ---------------- {{{1 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan; // NOLINT 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 10212eb79dd701d9d40551759330a9257316601373bEvgeniy StepanovDECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 10312eb79dd701d9d40551759330a9257316601373bEvgeniy StepanovDECLARE_REAL_AND_INTERCEPTOR(void, free, void *) 10412eb79dd701d9d40551759330a9257316601373bEvgeniy Stepanov 1053fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ 1063fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov do { \ 1073fa122e6a8e12db6583793861f6cf776fe1c98a0Evgeniy Stepanov } while (false) 10882a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 10982a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov ASAN_WRITE_RANGE(ptr, size) 110996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 1119d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 1129d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov do { \ 1139d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \ 1149d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov ctx = 0; \ 1159d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov (void) ctx; \ 1169d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov ENSURE_ASAN_INITED(); \ 1179d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov } while (false) 1189d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 1199d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov do { \ 1209d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov } while (false) 1219d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 1229d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov do { \ 1239d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov } while (false) 1249d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 1259d1525ec52430d0b8ffd6d0893b7f5529105b321Evgeniy Stepanov do { \ 12682a9080eaff95d69b270cd863e9df63e3b4e59adEvgeniy Stepanov } while (false) 127996c4f2fa53cce8f9d7b517073f38569460de505Evgeniy Stepanov#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 1284f32c0beaa83ffbb84db23d2e6205bee57c39ce1Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_interceptors.inc" 1298530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany 130881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s) 131881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s) 132ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 133ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov do { \ 134ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov } while (false) 135ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 136ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov do { \ 137ae4e6fd0300b13812a02a779619b1a451478cdd1Evgeniy Stepanov } while (false) 138881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov#include "sanitizer_common/sanitizer_common_syscalls.inc" 139881b677c189e65872fd315a75a0e56f077339189Evgeniy Stepanov 140600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovstatic thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 1414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany AsanThread *t = (AsanThread*)arg; 14289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov SetCurrentThread(t); 143def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return t->ThreadStart(GetTid()); 1444803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 1454803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 146fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE 147def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovextern "C" int pthread_attr_getdetachstate(void *attr, int *v); 148def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 149b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy StepanovINTERCEPTOR(int, pthread_create, void *thread, 150b8ef925563f8dde5be837c4b0569082867c5f14cEvgeniy Stepanov void *attr, void *(*start_routine)(void*), void *arg) { 151c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev EnsureMainThreadIDIsCorrect(); 152bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov // Strict init-order checking in thread-hostile. 1539465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov if (flags()->strict_init_order) 1549465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov StopInitOrderChecking(); 155a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 156def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov int detached = 0; 157def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (attr != 0) 158def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov pthread_attr_getdetachstate(attr, &detached); 159def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 16089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov u32 current_tid = GetCurrentTidOrInvalid(); 161def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThread *t = AsanThread::Create(start_routine, arg); 162def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CreateThreadContextArgs args = { t, &stack }; 163def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 16409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(pthread_create)(thread, attr, asan_thread_start, t); 1654803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 166fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif // ASAN_INTERCEPT_PTHREAD_CREATE 1674803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 16834a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 169f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void*, signal, int signum, void *handler) { 170332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 171034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko return REAL(signal)(signum, handler); 1724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 1733f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany return 0; 1744803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 1754803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 176da13ba833b046553f50b54538e4828287ddbf5c0Alexey SamsonovINTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 177da13ba833b046553f50b54538e4828287ddbf5c0Alexey Samsonov struct sigaction *oldact) { 178332bf3340435a85d39d6abefbf4d6a145e17da1cAlexey Samsonov if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 179034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko return REAL(sigaction)(signum, act, oldact); 1804803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany } 181034bda5eab7cda14fac0bed3a39de4a3dbce3cffAlexander Potapenko return 0; 1824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 183e1ba0009d5be18d513ffd29c1b6fccea1a3bffa0Evgeniy Stepanov#elif SANITIZER_POSIX 18434a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov// We need to have defined REAL(sigaction) on posix systems. 18534a3202a2c22816a6da66959e266a2d078ded37bAlexey SamsonovDEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 186fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey Samsonov struct sigaction *oldact) 18734a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1884803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 1890870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT 19057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonovstatic void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 19157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov // Align to page size. 19257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov uptr PageSize = GetPageSizeCached(); 19357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov uptr bottom = stack & ~(PageSize - 1); 19457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ssize += stack - bottom; 19557db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ssize = RoundUpTo(ssize, PageSize); 19657db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 197541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany if (ssize && ssize <= kMaxSaneContextStackSize) { 19857db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov PoisonShadow(bottom, ssize, 0); 19957db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov } 20057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov} 20157db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov 2020870028410087e67a0049c76cb7c64f02c260d24Alexey SamsonovINTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 2030870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov struct ucontext_t *ucp) { 2040870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov static bool reported_warning = false; 2050870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov if (!reported_warning) { 2060870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 2070870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov "functions and may produce false positives in some cases!\n"); 2080870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov reported_warning = true; 2090870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov } 2100870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // Clear shadow memory for new context (it may share stack 2110870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // with current context). 21257db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov uptr stack, ssize; 21357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ReadContextStack(ucp, &stack, &ssize); 21457db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ClearShadowMemoryForContextStack(stack, ssize); 2150870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov int res = REAL(swapcontext)(oucp, ucp); 2160870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // swapcontext technically does not return, but program may swap context to 2170870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // "oucp" later, that would look as if swapcontext() returned 0. 2180870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // We need to clear shadow for ucp once again, as it may be in arbitrary 2190870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov // state. 22057db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov ClearShadowMemoryForContextStack(stack, ssize); 2210870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov return res; 2220870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov} 22357db4bae483e7268dd7fc5bc42b0e55564014048Alexey Samsonov#endif // ASAN_INTERCEPT_SWAPCONTEXT 2240870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov 225f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, longjmp, void *env, int val) { 226f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 22709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(longjmp)(env, val); 2284803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2294803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 230fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP 231f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, _longjmp, void *env, int val) { 232f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 23309672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(_longjmp)(env, val); 2344803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 235fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 2364803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 237fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP 238f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, siglongjmp, void *env, int val) { 239f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 24009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(siglongjmp)(env, val); 2414803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 24207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 2434803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 244fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW 245f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 24609672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov CHECK(REAL(__cxa_throw)); 247f54b1f9b73a6855d77ee270c282bd61407fa73a0Kostya Serebryany __asan_handle_no_return(); 24809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(__cxa_throw)(a, b, c); 2494803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2504803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany#endif 2514803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 2524803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// intercept mlock and friends. 2534803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 2544803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany// All functions return 0 (success). 2554803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryanystatic void MlockIsUnsupported() { 2568d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov static bool printed = false; 2574803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany if (printed) return; 2584803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany printed = true; 259eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov if (flags()->verbosity > 0) { 260eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov Printf("INFO: AddressSanitizer ignores " 261eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov "mlock/mlockall/munlock/munlockall\n"); 262eaca82cf249021afa31dbc970278f2f28ea2a1aaTimur Iskhodzhanov } 2634803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2643389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 26500f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlock, const void *addr, uptr len) { 2664803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2674803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2684803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2693389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 27000f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlock, const void *addr, uptr len) { 2714803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2724803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2734803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2743389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 27500f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, mlockall, int flags) { 2764803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2774803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2784803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2793389b8ea81f51a28365a421b2646d594bac490f5Alexey Samsonov 28000f1c091441be5c2cacb99e21bd1965a5e418242Alexander PotapenkoINTERCEPTOR(int, munlockall, void) { 2814803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany MlockIsUnsupported(); 2824803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany return 0; 2834803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany} 2844803ab90ead451b55a5833f0fd38b10fd1fc83ebKostya Serebryany 28552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryanystatic inline int CharCmp(unsigned char c1, unsigned char c2) { 28652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 28752fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 28852fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 2893f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 29050f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_memcmp(a1, a2, size); 29152fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany ENSURE_ASAN_INITED(); 2921b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany if (flags()->replace_intrin) { 2938bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (flags()->strict_memcmp) { 2948bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko // Check the entire regions even if the first bytes of the buffers are 2958bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko // different. 2968bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko ASAN_READ_RANGE(a1, size); 2978bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko ASAN_READ_RANGE(a2, size); 2988bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko // Fallthrough to REAL(memcmp) below. 2998bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko } else { 3008bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko unsigned char c1 = 0, c2 = 0; 3018bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko const unsigned char *s1 = (const unsigned char*)a1; 3028bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko const unsigned char *s2 = (const unsigned char*)a2; 3038bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko uptr i; 3048bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko for (i = 0; i < size; i++) { 3058bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko c1 = s1[i]; 3068bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko c2 = s2[i]; 3078bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko if (c1 != c2) break; 3088bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko } 3098bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko ASAN_READ_RANGE(s1, Min(i + 1, size)); 3108bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko ASAN_READ_RANGE(s2, Min(i + 1, size)); 3118bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko return CharCmp(c1, c2); 3128bd5e74fa9d37a182088114918380e255e22e493Alexander Potapenko } 31352fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany } 3141b057b20db71ec6cc2bac460c8b2848f0889d47dKostya Serebryany return REAL(memcmp(a1, a2, size)); 31552fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany} 31652fb238ccc45781e4e1d097ae1ee748c898b5825Kostya Serebryany 3173f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 31850f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_memcpy(to, from, size); 3191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // memcpy is called during __asan_init() from the internals 3201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // of printf(...). 3211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 32209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(memcpy)(to, from, size); 3231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 324e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 325cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_intrin) { 326c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany if (to != from) { 327c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany // We do not treat memcpy with to==from as a bug. 328c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany // See http://llvm.org/bugs/show_bug.cgi?id=11763. 329c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 330c655cfa8dc0fdf5b521e565f6cbdbf7981fba1b2Kostya Serebryany } 331c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_READ_RANGE(from, size); 332c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_WRITE_RANGE(to, size); 3331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 334f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 335f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 336f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko return internal_memcpy(to, from, size); 3371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3393f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 3403e8458ab54c7cbaec45e367b2da909c6f94b291cAlexander Potapenko if (!asan_inited) return internal_memmove(to, from, size); 341a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov if (asan_init_is_running) { 342a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov return REAL(memmove)(to, from, size); 343a1a25c1afe38e59ffb342c24bb5bb10d05679df7Alexey Samsonov } 344e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 345cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_intrin) { 346c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_READ_RANGE(from, size); 347c75d8483e27528349620ccf4e997a72029a7ea17Alexander Potapenko ASAN_WRITE_RANGE(to, size); 3481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 349f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 350f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 351f1673e61768cb08d488a75584b61bfdf24ffdac1Alexander Potapenko return internal_memmove(to, from, size); 3521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 3543f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(void*, memset, void *block, int c, uptr size) { 35550f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_memset(block, c, size); 356ebb9702cff96192c6a6ea963037929ca7ed60eaeAlexander Potapenko // memset is called inside Printf. 357e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany if (asan_init_is_running) { 35809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(memset)(block, c, size); 359e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany } 360e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 361cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_intrin) { 3621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(block, size); 3631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 36409672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(memset)(block, c, size); 3651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 367f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strchr, const char *str, int c) { 36850f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strchr(str, c); 3698d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 3708d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko // used. 3718d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko if (asan_init_is_running) { 3728d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko return REAL(strchr)(str, c); 3738d6e3f7d011970e35dadf831964260bcf6a4d8a9Alexander Potapenko } 374e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 37509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov char *result = REAL(strchr)(str, c); 376cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 3773f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 3781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(str, bytes_read); 3791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 3801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return result; 3811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 3821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 383fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_INDEX 384fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 3854b0c5f240e71be4f375627e57d0f1b89600918a7Evgeniy StepanovINTERCEPTOR(char*, index, const char *string, int c) 38672bbfd4f3a442afde281476bc6bd41b3b2152a4eAlexander Potapenko ALIAS(WRAPPER_NAME(strchr)); 387fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# else 38824e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov# if SANITIZER_MAC 38950a002ecad3f0a10c136496e5b6289bd3c71590eAlexander PotapenkoDECLARE_REAL(char*, index, const char *string, int c) 39050a002ecad3f0a10c136496e5b6289bd3c71590eAlexander PotapenkoOVERRIDE_FUNCTION(index, strchr); 39150a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko# else 392fdde5a97a71b142297d7b2270c2a7f564a37dbaeAlexey SamsonovDEFINE_REAL(char*, index, const char *string, int c) 39350a002ecad3f0a10c136496e5b6289bd3c71590eAlexander Potapenko# endif 394fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov# endif 395fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif // ASAN_INTERCEPT_INDEX 396af0f01d77c2a495f023ffbf6cce85b33bbd2306dKostya Serebryany 39737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// For both strcat() and strncat() we need to check the validity of |to| 39837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko// argument irrespective of the |from| length. 399f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 4000985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ENSURE_ASAN_INITED(); 401cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4023f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr from_length = REAL(strlen)(from); 4030985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany ASAN_READ_RANGE(from, from_length + 1); 40437b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko uptr to_length = REAL(strlen)(to); 40537b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ASAN_READ_RANGE(to, to_length); 40637b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ASAN_WRITE_RANGE(to + to_length, from_length + 1); 40737b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // If the copying actually happens, the |from| string should not overlap 40837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // with the resulting string starting at |to|, which has a length of 40937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko // to_length + from_length + 1. 4100985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany if (from_length > 0) { 41137b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 41237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko from, from_length + 1); 4130985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 4140985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany } 41509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strcat)(to, from); // NOLINT 4160985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany} 4170985ca240812ac5519168a6aecbccf4c513ae243Kostya Serebryany 418c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey SamsonovINTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 419c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ENSURE_ASAN_INITED(); 42037b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko if (flags()->replace_str) { 421c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov uptr from_length = MaybeRealStrnlen(from, size); 42237b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko uptr copy_length = Min(size, from_length + 1); 42337b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko ASAN_READ_RANGE(from, copy_length); 424c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov uptr to_length = REAL(strlen)(to); 425c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_READ_RANGE(to, to_length); 426c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_WRITE_RANGE(to + to_length, from_length + 1); 427c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov if (from_length > 0) { 42837b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 42937b3fcd6fdec5740fe51fc1315c5d4d54313de98Alexander Potapenko from, copy_length); 430c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov } 431c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov } 432c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov return REAL(strncat)(to, from, size); 433c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov} 434c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov 435f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 43650f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strcmp(s1, s2); 437fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov if (asan_init_is_running) { 438fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov return REAL(strcmp)(s1, s2); 4391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4408648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany ENSURE_ASAN_INITED(); 4411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1, c2; 4423f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr i; 4431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; ; i++) { 4441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c1 = (unsigned char)s1[i]; 4451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 4461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 4471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s1, i + 1); 4491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s2, i + 1); 4501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 4511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 453f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 45424e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC 455beda44f87166f91dbeef3d174d77395653bead4dAlexander Potapenko if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 4560ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 4571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strcpy is called from malloc_default_purgeable_zone() 4581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 4591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 46009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strcpy)(to, from); // NOLINT 4611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 462e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 463cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr from_size = REAL(strlen)(from) + 1; 465c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 4661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, from_size); 4671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(to, from_size); 4681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 46909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strcpy)(to, from); // NOLINT 4701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 4711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 472fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP 473f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(char*, strdup, const char *s) { 47450f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strdup(s); 475e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 476d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov uptr length = REAL(strlen)(s); 477cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, length + 1); 4791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 480d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov GET_STACK_TRACE_MALLOC; 481d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov void *new_mem = asan_malloc(length + 1, &stack); 482d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov REAL(memcpy)(new_mem, s, length + 1); 483d530d892b4958a9ae54e57472d5d0a0bae1f6ad8Alexey Samsonov return reinterpret_cast<char*>(new_mem); 4841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 485fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 4861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 4873f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strlen, const char *s) { 48850f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strlen(s); 4891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strlen is called from malloc_default_purgeable_zone() 4901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 4911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 49209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strlen)(s); 4931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 494e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 4953f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr length = REAL(strlen)(s); 496cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 4971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(s, length + 1); 4981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 4991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return length; 5001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5023f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 50350f2e30497ba2a69ee5721e7235a296d7c13a495Alexander Potapenko if (!asan_inited) return internal_strncmp(s1, s2, size); 5041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // strncmp is called from malloc_default_purgeable_zone() 5051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // in __asan::ReplaceSystemAlloc() on Mac. 5061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (asan_init_is_running) { 50709672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strncmp)(s1, s2, size); 5081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5098648e7734ff02a25706464e9e294bd217622bcaeKostya Serebryany ENSURE_ASAN_INITED(); 5101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany unsigned char c1 = 0, c2 = 0; 5113f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr i; 5121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany for (i = 0; i < size; i++) { 5131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c1 = (unsigned char)s1[i]; 5141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany c2 = (unsigned char)s2[i]; 5151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (c1 != c2 || c1 == '\0') break; 5161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5172d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s1, Min(i + 1, size)); 5182d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s2, Min(i + 1, size)); 5191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return CharCmp(c1, c2); 5201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5223f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 523e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 524cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 525c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 526c5e72a3b7c60f1b2d9d9be3a07d397d5b5f872beKostya Serebryany CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 5271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_READ_RANGE(from, from_size); 5281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ASAN_WRITE_RANGE(to, size); 5291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 53009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov return REAL(strncpy)(to, from, size); 5311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 5321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 53381a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#if ASAN_INTERCEPT_STRNLEN 5343f4c3875c42078e22c7e5356c5746fd18756d958Kostya SerebryanyINTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 535e130191a254064bfd1c8d373afdacf6d52979713Kostya Serebryany ENSURE_ASAN_INITED(); 5363f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr length = REAL(strnlen)(s, maxlen); 537cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->replace_str) { 5382d8b3bdb112ebb8ed3f15ee41d4cebcd683b41b0Kostya Serebryany ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 5391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 5401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return length; 5411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 54281a7a4ab53c94e76c3b131d6f0ed82894640900bAlexey Samsonov#endif // ASAN_INTERCEPT_STRNLEN 543547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 5448f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline bool IsValidStrtolBase(int base) { 5458f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov return (base == 0) || (2 <= base && base <= 36); 5468f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov} 5478f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov 5488f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonovstatic inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 549a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany CHECK(endptr); 5508f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (nptr == *endptr) { 5518f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // No digits were found at strtol call, we need to find out the last 5528f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // symbol accessed by strtoll on our own. 5538f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov // We get this symbol by skipping leading blanks and optional +/- sign. 5548f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov while (IsSpace(*nptr)) nptr++; 5558f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (*nptr == '+' || *nptr == '-') nptr++; 5568f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov *endptr = (char*)nptr; 5578f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 5588f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov CHECK(*endptr >= nptr); 55984ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov} 56084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 561847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, strtol, const char *nptr, // NOLINT 56284ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov char **endptr, int base) { 56384ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ENSURE_ASAN_INITED(); 564cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 565847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(strtol)(nptr, endptr, base); 56684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 56784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov char *real_endptr; 568847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 5693f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (endptr != 0) { 57084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov *endptr = real_endptr; 57184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 5728f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (IsValidStrtolBase(base)) { 5738f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 57484ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 57584ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov } 57684ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov return result; 57784ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov} 57884ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 579847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(int, atoi, const char *nptr) { 58024e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC 5810ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko if (!asan_inited) return REAL(atoi)(nptr); 5820ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 583847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 584cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 585847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atoi)(nptr); 586847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 587847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 588847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // "man atoi" tells that behavior of atoi(nptr) is the same as 5893f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 590847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // parsed integer can't be stored in *long* type (even if it's 591847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // different from int). So, we just imitate this behavior. 592847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov int result = REAL(strtol)(nptr, &real_endptr, 10); 593847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 594847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 595847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 596847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 597847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 598847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long, atol, const char *nptr) { // NOLINT 59924e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC 6000ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko if (!asan_inited) return REAL(atol)(nptr); 6010ef531054fc25c11e372cbab1384f10954984219Alexander Potapenko#endif 602847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 603cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 604847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atol)(nptr); 605847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 606847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 607847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 608847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 609847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 610847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 611847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 612847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 613847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 614847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 6158f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov char **endptr, int base) { 6168f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ENSURE_ASAN_INITED(); 617cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 618847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(strtoll)(nptr, endptr, base); 6198f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 6208f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov char *real_endptr; 621847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 6223f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany if (endptr != 0) { 6238f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov *endptr = real_endptr; 6248f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 625847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // If base has unsupported value, strtoll can exit with EINVAL 626847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // without reading any characters. So do additional checks only 627847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov // if base is valid. 6288f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov if (IsValidStrtolBase(base)) { 6298f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 6308f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 6318f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov } 6328f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov return result; 6338f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov} 6348f6a77f3f59ebc5f40f235e51836f468f30b9110Alexey Samsonov 635847f932ab0405757946433b81d3b2952b306b0bcAlexey SamsonovINTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 636847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ENSURE_ASAN_INITED(); 637cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!flags()->replace_str) { 638847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return REAL(atoll)(nptr); 639847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov } 640847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov char *real_endptr; 641847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 642847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov FixRealStrtolEndptr(nptr, &real_endptr); 643847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 644847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov return result; 645847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov} 646847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 647847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov 64846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonovstatic void AtCxaAtexit(void *unused) { 64946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov (void)unused; 65046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov StopInitOrderChecking(); 65146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov} 65246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov 65346efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#if ASAN_INTERCEPT___CXA_ATEXIT 65446efcb09dc16b91cb805abea52f3ff6081a63751Alexey SamsonovINTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 65546efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov void *dso_handle) { 65646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov ENSURE_ASAN_INITED(); 65746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov int res = REAL(__cxa_atexit)(func, arg, dso_handle); 65846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov REAL(__cxa_atexit)(AtCxaAtexit, 0, 0); 65946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov return res; 66046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov} 66146efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif // ASAN_INTERCEPT___CXA_ATEXIT 66246efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov 663fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#if !SANITIZER_MAC 664580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov#define ASAN_INTERCEPT_FUNC(name) do { \ 665cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 666580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 667580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov } while (0) 668fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#else 669fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. 670fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#define ASAN_INTERCEPT_FUNC(name) 671fd55281122b4dedceb4e5a2fedc3946bfba9032bAlexander Potapenko#endif // SANITIZER_MAC 672580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov 67324e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_WINDOWS 674600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovINTERCEPTOR_WINAPI(DWORD, CreateThread, 6753f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany void* security, uptr stack_size, 676600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov DWORD (__stdcall *start_routine)(void*), void* arg, 677b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov DWORD thr_flags, void* tid) { 678bdd0966deb04068ea94cf416c7fb46516013bd26Alexey Samsonov // Strict init-order checking in thread-hostile. 6799465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov if (flags()->strict_init_order) 6809465cbdbe73590746b57916f46ea1aa4bf3dd13dAlexey Samsonov StopInitOrderChecking(); 681a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany GET_STACK_TRACE_THREAD; 68289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov u32 current_tid = GetCurrentTidOrInvalid(); 683dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov AsanThread *t = AsanThread::Create(start_routine, arg); 684dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov CreateThreadContextArgs args = { t, &stack }; 6858d2438a7ebb01201c652f91d1e8043a1f3d03bffTimur Iskhodzhanov bool detached = false; // FIXME: how can we determine it on Windows? 686dfe3f9691d4700981566a4b57e1e482f72783950Alexey Samsonov asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 687600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov return REAL(CreateThread)(security, stack_size, 688b9a928497168e177791f10f5042ff6f5e4e8a881Alexey Samsonov asan_thread_start, t, thr_flags, tid); 689600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov} 690600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 691600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovnamespace __asan { 692600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovvoid InitializeWindowsInterceptors() { 693580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(CreateThread); 694600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov} 695600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 696600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov} // namespace __asan 697600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif 698600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 699547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany// ---------------------- InitializeAsanInterceptors ---------------- {{{1 700547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanynamespace __asan { 701547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryanyvoid InitializeAsanInterceptors() { 702fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany static bool was_called_once; 703fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany CHECK(was_called_once == false); 704fdbdab5ff8de4c23b58bb411ea2358a78e2d9b2fKostya Serebryany was_called_once = true; 7058530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany SANITIZER_COMMON_INTERCEPTORS_INIT; 7068530e2b953f0b34ecd267a6aba5f155d5c08c5c8Kostya Serebryany 70707bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intercept mem* functions. 708580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memcmp); 709580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memmove); 710580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memset); 71138dd4ed885e714c376466f6fe0d69f5f22d37014Alexey Samsonov if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 712580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(memcpy); 713573fb4b102dda9d231a8dbd0c01e67e84e9b0874Alexander Potapenko } 71407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov 71507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intercept str* functions. 716580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcat); // NOLINT 717580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strchr); 718580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcmp); 719580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 720580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strlen); 721c1bdd5adca453f2fae238a4c53ade35ae60b85daAlexey Samsonov ASAN_INTERCEPT_FUNC(strncat); 722580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strncmp); 723580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strncpy); 724fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRDUP 725fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(strdup); 726fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 727fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_STRNLEN 728fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov ASAN_INTERCEPT_FUNC(strnlen); 729fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 73069563986ca570ce750111a82264d51ddbf4107baAlexander Potapenko#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 731580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(index); 73207bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 7335b29018cf422e7711fb760b733c32127397a43fcAlexey Samsonov 734580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atoi); 735580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atol); 736580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strtol); 737847f932ab0405757946433b81d3b2952b306b0bcAlexey Samsonov#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 738580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(atoll); 739580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(strtoll); 74084ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov#endif 74184ba324b94d22a69acc823e845f9718fd2984e44Alexey Samsonov 742f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#if ASAN_INTERCEPT_MLOCKX 74300f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko // Intercept mlock/munlock. 74400f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(mlock); 74500f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(munlock); 74600f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(mlockall); 74700f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko ASAN_INTERCEPT_FUNC(munlockall); 748f0c6de3d91ba5cdfbb17a630e823523c7d433160Alexander Potapenko#endif 74900f1c091441be5c2cacb99e21bd1965a5e418242Alexander Potapenko 75007bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intecept signal- and jump-related functions. 751580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(longjmp); 75234a3202a2c22816a6da66959e266a2d078ded37bAlexey Samsonov#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 753580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(sigaction); 754580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(signal); 755919c24787a655597bdcf367e26c9dd1504e9f463Evgeniy Stepanov#endif 7560870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#if ASAN_INTERCEPT_SWAPCONTEXT 7570870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov ASAN_INTERCEPT_FUNC(swapcontext); 7580870028410087e67a0049c76cb7c64f02c260d24Alexey Samsonov#endif 759fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT__LONGJMP 760580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(_longjmp); 761fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 762fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_SIGLONGJMP 763580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(siglongjmp); 764fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#endif 765fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov 766fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov // Intercept exception handling functions. 767fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT___CXA_THROW 768fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov INTERCEPT_FUNCTION(__cxa_throw); 7693e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov#endif 7703e81fe43798c096d1d3565596f0717b9919de4fbTimur Iskhodzhanov 77107bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov // Intercept threading-related functions 772fd2ae4fc7df0e5acd200f30d87bbc6b96830a989Alexey Samsonov#if ASAN_INTERCEPT_PTHREAD_CREATE 773580469d7e40e39319cb2d3750edac4bccca18105Dmitry Vyukov ASAN_INTERCEPT_FUNC(pthread_create); 77407bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov#endif 77507bb9f1e3600195119aec1aae1aa48a6ed2f5febTimur Iskhodzhanov 77646efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov // Intercept atexit function. 77746efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#if ASAN_INTERCEPT___CXA_ATEXIT 77846efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov ASAN_INTERCEPT_FUNC(__cxa_atexit); 77946efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov#endif 78046efcb09dc16b91cb805abea52f3ff6081a63751Alexey Samsonov 781600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov // Some Windows-specific interceptors. 78224e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_WINDOWS 783600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov InitializeWindowsInterceptors(); 784600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov#endif 785600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov 786cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity > 0) { 7872962f26071ebef1d5fec52b5569e5ae7aae45c9bAlexander Potapenko Report("AddressSanitizer: libc interceptors initialized\n"); 788547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany } 789547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany} 790547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany 791547652c45fd7f7497dd214ec8ec6b6ee0f80359dKostya Serebryany} // namespace __asan 792