168d75effSDimitry Andric //===-- asan_interceptors_memintrinsics.cpp -------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===---------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // ASan versions of memcpy, memmove, and memset. 1268d75effSDimitry Andric //===---------------------------------------------------------------------===// 1368d75effSDimitry Andric 1406c3fb27SDimitry Andric #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS 1506c3fb27SDimitry Andric 1668d75effSDimitry Andric #include "asan_interceptors_memintrinsics.h" 1706c3fb27SDimitry Andric 1806c3fb27SDimitry Andric #include "asan_interceptors.h" 1968d75effSDimitry Andric #include "asan_report.h" 2068d75effSDimitry Andric #include "asan_stack.h" 2168d75effSDimitry Andric #include "asan_suppressions.h" 2268d75effSDimitry Andric 2368d75effSDimitry Andric using namespace __asan; 2468d75effSDimitry Andric 2506c3fb27SDimitry Andric // memcpy is called during __asan_init() from the internals of printf(...). 2606c3fb27SDimitry Andric // We do not treat memcpy with to==from as a bug. 2706c3fb27SDimitry Andric // See http://llvm.org/bugs/show_bug.cgi?id=11763. 2806c3fb27SDimitry Andric #define ASAN_MEMCPY_IMPL(ctx, to, from, size) \ 2906c3fb27SDimitry Andric do { \ 3006c3fb27SDimitry Andric if (LIKELY(replace_intrin_cached)) { \ 3106c3fb27SDimitry Andric if (LIKELY(to != from)) { \ 3206c3fb27SDimitry Andric CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \ 3306c3fb27SDimitry Andric } \ 3406c3fb27SDimitry Andric ASAN_READ_RANGE(ctx, from, size); \ 3506c3fb27SDimitry Andric ASAN_WRITE_RANGE(ctx, to, size); \ 36*5f757f3fSDimitry Andric } else if (UNLIKELY(!AsanInited())) { \ 3706c3fb27SDimitry Andric return internal_memcpy(to, from, size); \ 3806c3fb27SDimitry Andric } \ 3906c3fb27SDimitry Andric return REAL(memcpy)(to, from, size); \ 4006c3fb27SDimitry Andric } while (0) 4106c3fb27SDimitry Andric 4206c3fb27SDimitry Andric // memset is called inside Printf. 4306c3fb27SDimitry Andric #define ASAN_MEMSET_IMPL(ctx, block, c, size) \ 4406c3fb27SDimitry Andric do { \ 4506c3fb27SDimitry Andric if (LIKELY(replace_intrin_cached)) { \ 4606c3fb27SDimitry Andric ASAN_WRITE_RANGE(ctx, block, size); \ 47*5f757f3fSDimitry Andric } else if (UNLIKELY(!AsanInited())) { \ 4806c3fb27SDimitry Andric return internal_memset(block, c, size); \ 4906c3fb27SDimitry Andric } \ 5006c3fb27SDimitry Andric return REAL(memset)(block, c, size); \ 5106c3fb27SDimitry Andric } while (0) 5206c3fb27SDimitry Andric 5306c3fb27SDimitry Andric #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ 5406c3fb27SDimitry Andric do { \ 5506c3fb27SDimitry Andric if (LIKELY(replace_intrin_cached)) { \ 5606c3fb27SDimitry Andric ASAN_READ_RANGE(ctx, from, size); \ 5706c3fb27SDimitry Andric ASAN_WRITE_RANGE(ctx, to, size); \ 5806c3fb27SDimitry Andric } \ 5906c3fb27SDimitry Andric return internal_memmove(to, from, size); \ 6006c3fb27SDimitry Andric } while (0) 6106c3fb27SDimitry Andric 6268d75effSDimitry Andric void *__asan_memcpy(void *to, const void *from, uptr size) { 6368d75effSDimitry Andric ASAN_MEMCPY_IMPL(nullptr, to, from, size); 6468d75effSDimitry Andric } 6568d75effSDimitry Andric 6668d75effSDimitry Andric void *__asan_memset(void *block, int c, uptr size) { 6768d75effSDimitry Andric ASAN_MEMSET_IMPL(nullptr, block, c, size); 6868d75effSDimitry Andric } 6968d75effSDimitry Andric 7068d75effSDimitry Andric void *__asan_memmove(void *to, const void *from, uptr size) { 7168d75effSDimitry Andric ASAN_MEMMOVE_IMPL(nullptr, to, from, size); 7268d75effSDimitry Andric } 7368d75effSDimitry Andric 74fe6060f1SDimitry Andric #if SANITIZER_FUCHSIA 7568d75effSDimitry Andric 76fe6060f1SDimitry Andric // Fuchsia doesn't use sanitizer_common_interceptors.inc, but 7768d75effSDimitry Andric // the only things there it wants are these three. Just define them 7868d75effSDimitry Andric // as aliases here rather than repeating the contents. 7968d75effSDimitry Andric 8068d75effSDimitry Andric extern "C" decltype(__asan_memcpy) memcpy[[gnu::alias("__asan_memcpy")]]; 8168d75effSDimitry Andric extern "C" decltype(__asan_memmove) memmove[[gnu::alias("__asan_memmove")]]; 8268d75effSDimitry Andric extern "C" decltype(__asan_memset) memset[[gnu::alias("__asan_memset")]]; 8368d75effSDimitry Andric 8406c3fb27SDimitry Andric #else // SANITIZER_FUCHSIA 8506c3fb27SDimitry Andric 8606c3fb27SDimitry Andric #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ 8706c3fb27SDimitry Andric do { \ 8806c3fb27SDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ 8906c3fb27SDimitry Andric ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ 9006c3fb27SDimitry Andric } while (false) 9106c3fb27SDimitry Andric 9206c3fb27SDimitry Andric #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ 9306c3fb27SDimitry Andric do { \ 9406c3fb27SDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ 9506c3fb27SDimitry Andric ASAN_MEMCPY_IMPL(ctx, to, from, size); \ 9606c3fb27SDimitry Andric } while (false) 9706c3fb27SDimitry Andric 9806c3fb27SDimitry Andric #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ 9906c3fb27SDimitry Andric do { \ 10006c3fb27SDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, memset); \ 10106c3fb27SDimitry Andric ASAN_MEMSET_IMPL(ctx, block, c, size); \ 10206c3fb27SDimitry Andric } while (false) 10306c3fb27SDimitry Andric 10406c3fb27SDimitry Andric #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc" 10506c3fb27SDimitry Andric 106fe6060f1SDimitry Andric #endif // SANITIZER_FUCHSIA 107