1 //===-- asan_interceptors_memintrinsics.cpp -------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===---------------------------------------------------------------------===// 8 // 9 // This file is a part of AddressSanitizer, an address sanity checker. 10 // 11 // ASan versions of memcpy, memmove, and memset. 12 //===---------------------------------------------------------------------===// 13 14 #define SANITIZER_COMMON_NO_REDEFINE_BUILTINS 15 16 #include "asan_interceptors_memintrinsics.h" 17 18 #include "asan_interceptors.h" 19 #include "asan_report.h" 20 #include "asan_stack.h" 21 #include "asan_suppressions.h" 22 23 using namespace __asan; 24 25 // memcpy is called during __asan_init() from the internals of printf(...). 26 // We do not treat memcpy with to==from as a bug. 27 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 28 #define ASAN_MEMCPY_IMPL(ctx, to, from, size) \ 29 do { \ 30 if (LIKELY(replace_intrin_cached)) { \ 31 if (LIKELY(to != from)) { \ 32 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \ 33 } \ 34 ASAN_READ_RANGE(ctx, from, size); \ 35 ASAN_WRITE_RANGE(ctx, to, size); \ 36 } else if (UNLIKELY(!AsanInited())) { \ 37 return internal_memcpy(to, from, size); \ 38 } \ 39 return REAL(memcpy)(to, from, size); \ 40 } while (0) 41 42 // memset is called inside Printf. 43 #define ASAN_MEMSET_IMPL(ctx, block, c, size) \ 44 do { \ 45 if (LIKELY(replace_intrin_cached)) { \ 46 ASAN_WRITE_RANGE(ctx, block, size); \ 47 } else if (UNLIKELY(!AsanInited())) { \ 48 return internal_memset(block, c, size); \ 49 } \ 50 return REAL(memset)(block, c, size); \ 51 } while (0) 52 53 #define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \ 54 do { \ 55 if (LIKELY(replace_intrin_cached)) { \ 56 ASAN_READ_RANGE(ctx, from, size); \ 57 ASAN_WRITE_RANGE(ctx, to, size); \ 58 } \ 59 return internal_memmove(to, from, size); \ 60 } while (0) 61 62 void *__asan_memcpy(void *to, const void *from, uptr size) { 63 ASAN_MEMCPY_IMPL(nullptr, to, from, size); 64 } 65 66 void *__asan_memset(void *block, int c, uptr size) { 67 ASAN_MEMSET_IMPL(nullptr, block, c, size); 68 } 69 70 void *__asan_memmove(void *to, const void *from, uptr size) { 71 ASAN_MEMMOVE_IMPL(nullptr, to, from, size); 72 } 73 74 #if SANITIZER_FUCHSIA 75 76 // Fuchsia doesn't use sanitizer_common_interceptors.inc, but 77 // the only things there it wants are these three. Just define them 78 // as aliases here rather than repeating the contents. 79 80 extern "C" decltype(__asan_memcpy) memcpy[[gnu::alias("__asan_memcpy")]]; 81 extern "C" decltype(__asan_memmove) memmove[[gnu::alias("__asan_memmove")]]; 82 extern "C" decltype(__asan_memset) memset[[gnu::alias("__asan_memset")]]; 83 84 #else // SANITIZER_FUCHSIA 85 86 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ 87 do { \ 88 ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ 89 ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ 90 } while (false) 91 92 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ 93 do { \ 94 ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ 95 ASAN_MEMCPY_IMPL(ctx, to, from, size); \ 96 } while (false) 97 98 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ 99 do { \ 100 ASAN_INTERCEPTOR_ENTER(ctx, memset); \ 101 ASAN_MEMSET_IMPL(ctx, block, c, size); \ 102 } while (false) 103 104 #include "sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc" 105 106 #endif // SANITIZER_FUCHSIA 107