Index: lib/hwasan/CMakeLists.txt =================================================================== --- lib/hwasan/CMakeLists.txt +++ lib/hwasan/CMakeLists.txt @@ -6,6 +6,7 @@ hwasan_allocator.cc hwasan_dynamic_shadow.cc hwasan_interceptors.cc + hwasan_interceptors_memintrinsics.cc hwasan_linux.cc hwasan_poisoning.cc hwasan_report.cc Index: lib/hwasan/hwasan_interceptors_memintrinsics.cc =================================================================== --- lib/hwasan/hwasan_interceptors_memintrinsics.cc +++ lib/hwasan/hwasan_interceptors_memintrinsics.cc @@ -0,0 +1,59 @@ +//===-- hwasan_interceptors_memintrinsics.cc -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// +// This file is a part of HWAddressSanitizer, an address sanity checker. +// +// HWASan versions of memcpy, memmove, and memset. +//===---------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" + +#include "hwasan.h" +#include "hwasan_interface_internal.h" +#include "hwasan_report.h" + +using namespace __hwasan; + +#define TEST_RANGE(block, size, is_write) \ + do { \ + sptr offset = __hwasan_test_shadow(block, size); \ + if (offset >= 0) { \ + GET_CALLER_PC_BP_SP; \ + GET_FATAL_STACK_TRACE_PC_BP(pc, bp); \ + ReportTagMismatch(&stack, reinterpret_cast(block) + offset, \ + size - offset, is_write, true); \ + if (__hwasan::flags()->halt_on_error) { \ + Printf("Exiting\n"); \ + Die(); \ + } \ + } \ + } while (0) + +void *__hwasan_memcpy(void *to, const void *from, uptr size) { + if (LIKELY(hwasan_inited)) { + TEST_RANGE(to, size, true); + TEST_RANGE(from, size, false); + } + return internal_memcpy(to, from, size); +} + +void *__hwasan_memset(void *block, int c, uptr size) { + if (LIKELY(hwasan_inited)) + TEST_RANGE(block, size, true); + return internal_memset(block, c, size); +} + +void *__hwasan_memmove(void *to, const void *from, uptr size) { + if (LIKELY(hwasan_inited)) { + TEST_RANGE(to, size, true); + TEST_RANGE(from, size, false); + } + return internal_memcpy(to, from, size); +} Index: lib/hwasan/hwasan_interface_internal.h =================================================================== --- lib/hwasan/hwasan_interface_internal.h +++ lib/hwasan/hwasan_interface_internal.h @@ -194,6 +194,13 @@ SANITIZER_INTERFACE_ATTRIBUTE void * __sanitizer_malloc(uptr size); + +SANITIZER_INTERFACE_ATTRIBUTE +void *__hwasan_memcpy(void *dst, const void *src, uptr size); +SANITIZER_INTERFACE_ATTRIBUTE +void *__hwasan_memset(void *s, int c, uptr n); +SANITIZER_INTERFACE_ATTRIBUTE +void *__hwasan_memmove(void *dest, const void *src, uptr n); } // extern "C" #endif // HWASAN_INTERFACE_INTERNAL_H Index: test/hwasan/TestCases/mem-intrinsics.c =================================================================== --- test/hwasan/TestCases/mem-intrinsics.c +++ test/hwasan/TestCases/mem-intrinsics.c @@ -0,0 +1,31 @@ +// RUN: %clang_hwasan %s -DTEST_NO=1 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE +// RUN: %clang_hwasan %s -DTEST_NO=2 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=READ +// RUN: %clang_hwasan %s -DTEST_NO=3 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE + +// REQUIRES: stable-runtime + +#include +#include +#include + +int main() { + char Q[16]; + char P[16]; +#if TEST_NO == 1 + memset(Q, 0, 32); +#elif TEST_NO == 2 + memmove(Q, Q + 16, 16); +#elif TEST_NO == 3 + memcpy(Q, P, 32); +#endif + // WRITE: ERROR: HWAddressSanitizer: tag-mismatch on address + // WRITE: WRITE of size 16 at {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem) + // WRITE: Memory tags around the buggy address (one tag corresponds to 16 bytes): + // WRITE: =>{{.*}}[[MEM_TAG]] + + // READ: ERROR: HWAddressSanitizer: tag-mismatch on address + // READ: READ of size 16 at {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem) + // READ: Memory tags around the buggy address (one tag corresponds to 16 bytes): + // READ: =>{{.*}}[[MEM_TAG]] + return 0; +}