From c8ef98e5de0ec5ebd4efc80ad8938ed53b268ce3 Mon Sep 17 00:00:00 2001 From: Matt Morehouse Date: Wed, 24 Mar 2021 16:17:38 -0700 Subject: [PATCH] Revert "[HWASan] Use page aliasing on x86_64." This reverts commit 63f73c3eb9716256ab8dbb868e16d08a88636cba due to breakage on aarch64 without TBI. --- compiler-rt/lib/hwasan/hwasan.h | 22 ++------------ compiler-rt/lib/hwasan/hwasan_allocator.cpp | 5 ++-- compiler-rt/lib/hwasan/hwasan_allocator.h | 14 +-------- .../lib/hwasan/hwasan_dynamic_shadow.cpp | 16 +++------- compiler-rt/lib/hwasan/hwasan_flags.h | 2 -- .../lib/hwasan/hwasan_interceptors.cpp | 3 +- compiler-rt/lib/hwasan/hwasan_linux.cpp | 16 +--------- compiler-rt/lib/hwasan/hwasan_mapping.h | 2 -- .../lib/hwasan/hwasan_memintrinsics.cpp | 4 +-- .../lib/sanitizer_common/sanitizer_common.h | 10 ++----- .../Linux/aligned_alloc-alignment.cpp | 4 ++- .../TestCases/Linux/decorate-proc-maps.c | 13 +++++--- .../TestCases/Linux/pvalloc-overflow.cpp | 8 +++-- .../hwasan/TestCases/Linux/release-shadow.c | 16 +++++----- .../hwasan/TestCases/Linux/reuse-threads.cpp | 12 ++++---- .../test/hwasan/TestCases/Linux/vfork.c | 3 -- .../Posix/posix_memalign-alignment.cpp | 4 ++- .../TestCases/allocator_returns_null.cpp | 20 +++++++------ .../hwasan/TestCases/heap-buffer-overflow.c | 16 ++-------- .../hwasan/TestCases/hwasan-print-shadow.cpp | 5 ++-- .../test/hwasan/TestCases/malloc_fill.cpp | 8 +++-- .../test/hwasan/TestCases/many-threads-uaf.c | 4 ++- .../test/hwasan/TestCases/mem-intrinsics.c | 4 ++- .../TestCases/set-error-report-callback.cpp | 4 ++- compiler-rt/test/hwasan/TestCases/sizes.cpp | 16 +++++----- .../test/hwasan/TestCases/tail-magic.c | 8 +++-- .../test/hwasan/TestCases/use-after-free.c | 4 ++- compiler-rt/test/hwasan/TestCases/utils.h | 30 +++++++++++++++++++ .../Instrumentation/HWAddressSanitizer.cpp | 3 +- .../HWAddressSanitizer/X86/atomic.ll | 10 +++++-- .../HWAddressSanitizer/X86/basic.ll | 25 ++++++++++++---- .../HWAddressSanitizer/X86/kernel.ll | 5 +++- .../HWAddressSanitizer/X86/with-calls.ll | 20 ++++++++++--- 33 files changed, 179 insertions(+), 157 deletions(-) create mode 100644 compiler-rt/test/hwasan/TestCases/utils.h diff --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h index 24d96cedc044..119286cc7408 100644 --- a/compiler-rt/lib/hwasan/hwasan.h +++ b/compiler-rt/lib/hwasan/hwasan.h @@ -14,12 +14,11 @@ #ifndef HWASAN_H #define HWASAN_H -#include "hwasan_flags.h" -#include "hwasan_interface_internal.h" -#include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_stacktrace.h" +#include "hwasan_interface_internal.h" +#include "hwasan_flags.h" #include "ubsan/ubsan_platform.h" #ifndef HWASAN_CONTAINS_UBSAN @@ -36,30 +35,15 @@ typedef u8 tag_t; -#if defined(__x86_64__) -// Tags are done in middle bits using userspace aliasing. -constexpr unsigned kAddressTagShift = 39; -constexpr unsigned kTagBits = 3; - -// The alias region is placed next to the shadow so the upper bits of all -// taggable addresses matches the upper bits of the shadow base. This shift -// value determines which upper bits must match. It has a floor of 44 since the -// shadow is always 8TB. -// TODO(morehouse): In alias mode we can shrink the shadow and use a -// simpler/faster shadow calculation. -constexpr unsigned kTaggableRegionCheckShift = - __sanitizer::Max(kAddressTagShift + kTagBits + 1U, 44U); -#else // TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address // translation and can be used to store a tag. constexpr unsigned kAddressTagShift = 56; constexpr unsigned kTagBits = 8; -#endif // defined(__x86_64__) // Mask for extracting tag bits from the lower 8 bits. constexpr uptr kTagMask = (1UL << kTagBits) - 1; -// Mask for extracting tag bits from full pointers. +// Masks for extracting and removing tags from full pointers. constexpr uptr kAddressTagMask = kTagMask << kAddressTagShift; // Minimal alignment of the shadow base address. Determines the space available diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp index a6fc794082a5..72dafffe48e3 100644 --- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -84,8 +84,7 @@ void HwasanAllocatorInit() { atomic_store_relaxed(&hwasan_allocator_tagging_enabled, !flags()->disable_allocator_tagging); SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); - allocator.Init(common_flags()->allocator_release_to_os_interval_ms, - kAliasRegionStart); + allocator.Init(common_flags()->allocator_release_to_os_interval_ms); for (uptr i = 0; i < sizeof(tail_magic); i++) tail_magic[i] = GetCurrentThread()->GenerateRandomTag(); } @@ -375,7 +374,7 @@ int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size, // OOM error is already taken care of by HwasanAllocate. return errno_ENOMEM; CHECK(IsAligned((uptr)ptr, alignment)); - *memptr = ptr; + *(void **)UntagPtr(memptr) = ptr; return 0; } diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.h b/compiler-rt/lib/hwasan/hwasan_allocator.h index 03bbcff3f0f2..93d20ce8759e 100644 --- a/compiler-rt/lib/hwasan/hwasan_allocator.h +++ b/compiler-rt/lib/hwasan/hwasan_allocator.h @@ -13,8 +13,6 @@ #ifndef HWASAN_ALLOCATOR_H #define HWASAN_ALLOCATOR_H -#include "hwasan.h" -#include "hwasan_interface_internal.h" #include "hwasan_poisoning.h" #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_allocator_checks.h" @@ -57,12 +55,7 @@ static const uptr kMaxAllowedMallocSize = 1UL << 40; // 1T struct AP64 { static const uptr kSpaceBeg = ~0ULL; - -#if defined(__x86_64__) - static const uptr kSpaceSize = 1ULL << kAddressTagShift; -#else static const uptr kSpaceSize = 0x2000000000ULL; -#endif static const uptr kMetadataSize = sizeof(Metadata); typedef __sanitizer::VeryDenseSizeClassMap SizeClassMap; using AddressSpaceView = LocalAddressSpaceView; @@ -110,12 +103,7 @@ typedef RingBuffer HeapAllocationsRingBuffer; void GetAllocatorStats(AllocatorStatCounters s); inline bool InTaggableRegion(uptr addr) { -#if defined(__x86_64__) - // Aliases are mapped next to shadow so that the upper bits match the shadow - // base. - return (addr >> kTaggableRegionCheckShift) == - (__hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); -#endif + // TODO: specialize for x86 once we use aliasing mode in the allocator. return true; } diff --git a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp index f53276e330d3..12730b29bae3 100644 --- a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp +++ b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp @@ -12,17 +12,15 @@ /// //===----------------------------------------------------------------------===// +#include "hwasan.h" #include "hwasan_dynamic_shadow.h" +#include "hwasan_mapping.h" +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_posix.h" #include #include -#include "hwasan.h" -#include "hwasan_mapping.h" -#include "hwasan_thread_list.h" -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_posix.h" - // The code in this file needs to run in an unrelocated binary. It should not // access any external symbol, including its own non-hidden globals. @@ -119,12 +117,6 @@ namespace __hwasan { void InitShadowGOT() {} uptr FindDynamicShadowStart(uptr shadow_size_bytes) { -#if defined(__x86_64__) - constexpr uptr kAliasSize = 1ULL << kAddressTagShift; - constexpr uptr kNumAliases = 1ULL << kTagBits; - return MapDynamicShadowAndAliases(shadow_size_bytes, kAliasSize, kNumAliases, - RingBufferSize()); -#endif return MapDynamicShadow(shadow_size_bytes, kShadowScale, kShadowBaseAlignment, kHighMemEnd); } diff --git a/compiler-rt/lib/hwasan/hwasan_flags.h b/compiler-rt/lib/hwasan/hwasan_flags.h index b17750158d02..0a6998f675d6 100644 --- a/compiler-rt/lib/hwasan/hwasan_flags.h +++ b/compiler-rt/lib/hwasan/hwasan_flags.h @@ -12,8 +12,6 @@ #ifndef HWASAN_FLAGS_H #define HWASAN_FLAGS_H -#include "sanitizer_common/sanitizer_internal_defs.h" - namespace __hwasan { struct Flags { diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index ad67e2787d31..44e569ee6d72 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -221,7 +221,8 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), ThreadStartArg *A = reinterpret_cast (MmapOrDie( GetPageSizeCached(), "pthread_create")); *A = {callback, param}; - int res = REAL(pthread_create)(th, attr, &HwasanThreadStartFunc, A); + int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr), + &HwasanThreadStartFunc, A); return res; } diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp index 8ce0ff7da956..2b9b947c9334 100644 --- a/compiler-rt/lib/hwasan/hwasan_linux.cpp +++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp @@ -76,8 +76,6 @@ uptr kHighShadowEnd; uptr kHighMemStart; uptr kHighMemEnd; -uptr kAliasRegionStart; // Always 0 on non-x86. - static void PrintRange(uptr start, uptr end, const char *name) { Printf("|| [%p, %p] || %.*s ||\n", (void *)start, (void *)end, 10, name); } @@ -125,7 +123,7 @@ void InitPrctl() { if (internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0), &local_errno) && local_errno == EINVAL) { -#if SANITIZER_ANDROID || defined(__x86_64__) +#if SANITIZER_ANDROID // Some older Android kernels have the tagged pointer ABI on // unconditionally, and hence don't have the tagged-addr prctl while still // allow the ABI. @@ -181,18 +179,6 @@ bool InitShadow() { // High memory starts where allocated shadow allows. kHighMemStart = ShadowToMem(kHighShadowStart); -#if defined(__x86_64__) - constexpr uptr kAliasRegionOffset = 1ULL << (kTaggableRegionCheckShift - 1); - kAliasRegionStart = - __hwasan_shadow_memory_dynamic_address + kAliasRegionOffset; - - CHECK_EQ(kAliasRegionStart >> kTaggableRegionCheckShift, - __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); - CHECK_EQ( - (kAliasRegionStart + kAliasRegionOffset - 1) >> kTaggableRegionCheckShift, - __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); -#endif - // Check the sanity of the defined memory ranges (there might be gaps). CHECK_EQ(kHighMemStart % GetMmapGranularity(), 0); CHECK_GT(kHighMemStart, kHighShadowEnd); diff --git a/compiler-rt/lib/hwasan/hwasan_mapping.h b/compiler-rt/lib/hwasan/hwasan_mapping.h index 8243d1ec7ed5..c149687bdfa6 100644 --- a/compiler-rt/lib/hwasan/hwasan_mapping.h +++ b/compiler-rt/lib/hwasan/hwasan_mapping.h @@ -48,8 +48,6 @@ extern uptr kHighShadowEnd; extern uptr kHighMemStart; extern uptr kHighMemEnd; -extern uptr kAliasRegionStart; - inline uptr MemToShadow(uptr untagged_addr) { return (untagged_addr >> kShadowScale) + __hwasan_shadow_memory_dynamic_address; diff --git a/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp b/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp index fab017aae60b..e82d77a1bc16 100644 --- a/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp +++ b/compiler-rt/lib/hwasan/hwasan_memintrinsics.cpp @@ -24,7 +24,7 @@ using namespace __hwasan; void *__hwasan_memset(void *block, int c, uptr size) { CheckAddressSized( reinterpret_cast(block), size); - return memset(block, c, size); + return memset(UntagPtr(block), c, size); } void *__hwasan_memcpy(void *to, const void *from, uptr size) { @@ -32,7 +32,7 @@ void *__hwasan_memcpy(void *to, const void *from, uptr size) { reinterpret_cast(to), size); CheckAddressSized( reinterpret_cast(from), size); - return memcpy(to, from, size); + return memcpy(UntagPtr(to), UntagPtr(from), size); } void *__hwasan_memmove(void *to, const void *from, uptr size) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index dcd625d30f77..e1d3d3d6e191 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -449,14 +449,8 @@ inline uptr Log2(uptr x) { // Don't use std::min, std::max or std::swap, to minimize dependency // on libstdc++. -template -constexpr T Min(T a, T b) { - return a < b ? a : b; -} -template -constexpr T Max(T a, T b) { - return a > b ? a : b; -} +template T Min(T a, T b) { return a < b ? a : b; } +template T Max(T a, T b) { return a > b ? a : b; } template void Swap(T& a, T& b) { T tmp = a; a = b; diff --git a/compiler-rt/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cpp b/compiler-rt/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cpp index 3d7a4e2ba7a1..1a1acb2b8833 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cpp +++ b/compiler-rt/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cpp @@ -9,6 +9,8 @@ #include #include +#include "../utils.h" + extern void *aligned_alloc(size_t alignment, size_t size); int main() { @@ -18,7 +20,7 @@ int main() { // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cpp:}}[[@LINE-3]] // CHECK: SUMMARY: HWAddressSanitizer: invalid-aligned-alloc-alignment - printf("pointer after failed aligned_alloc: %zd\n", (size_t)p); + untag_printf("pointer after failed aligned_alloc: %zd\n", (size_t)p); // CHECK-NULL: pointer after failed aligned_alloc: 0 return 0; diff --git a/compiler-rt/test/hwasan/TestCases/Linux/decorate-proc-maps.c b/compiler-rt/test/hwasan/TestCases/Linux/decorate-proc-maps.c index 65c970ec0101..ce33d45179fe 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/decorate-proc-maps.c +++ b/compiler-rt/test/hwasan/TestCases/Linux/decorate-proc-maps.c @@ -8,6 +8,9 @@ // A-NEXT: ---p {{.*}}shadow gap] // A-NEXT: rw-p {{.*}}high shadow] +// B-DAG: rw-p {{.*}}SizeClassAllocator: region data] +// B-DAG: rw-p {{.*}}SizeClassAllocator: region metadata] +// B-DAG: rw-p {{.*}}SizeClassAllocator: freearray] // B-DAG: rw-p {{.*}}SizeClassAllocator: region info] // B-DAG: rw-p {{.*}}LargeMmapAllocator] // B-DAG: rw-p {{.*}}stack depot] @@ -22,17 +25,19 @@ #include #include +#include "../utils.h" + void CopyFdToFd(int in_fd, int out_fd) { const size_t kBufSize = 0x10000; static char buf[kBufSize]; while (1) { - ssize_t got = read(in_fd, buf, kBufSize); + ssize_t got = read(in_fd, UNTAG(buf), kBufSize); if (got > 0) { - write(out_fd, buf, got); + write(out_fd, UNTAG(buf), got); } else if (got == 0) { break; } else if (errno != EAGAIN || errno != EWOULDBLOCK || errno != EINTR) { - fprintf(stderr, "error reading file, errno %d\n", errno); + untag_fprintf(stderr, "error reading file, errno %d\n", errno); abort(); } } @@ -40,7 +45,7 @@ void CopyFdToFd(int in_fd, int out_fd) { void *ThreadFn(void *arg) { (void)arg; - int fd = open("/proc/self/maps", O_RDONLY); + int fd = open(UNTAG("/proc/self/maps"), O_RDONLY); CopyFdToFd(fd, 2); close(fd); return NULL; diff --git a/compiler-rt/test/hwasan/TestCases/Linux/pvalloc-overflow.cpp b/compiler-rt/test/hwasan/TestCases/Linux/pvalloc-overflow.cpp index 8e54ead4133e..2a203028aef8 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/pvalloc-overflow.cpp +++ b/compiler-rt/test/hwasan/TestCases/Linux/pvalloc-overflow.cpp @@ -18,6 +18,8 @@ #include #include +#include "../utils.h" + int main(int argc, char *argv[]) { assert(argc == 2); const char *action = argv[1]; @@ -25,15 +27,15 @@ int main(int argc, char *argv[]) { const size_t page_size = sysconf(_SC_PAGESIZE); void *p = nullptr; - if (!strcmp(action, "m1")) { + if (!untag_strcmp(action, "m1")) { p = pvalloc((uintptr_t)-1); - } else if (!strcmp(action, "psm1")) { + } else if (!untag_strcmp(action, "psm1")) { p = pvalloc((uintptr_t)-(page_size - 1)); } else { assert(0); } - fprintf(stderr, "errno: %d\n", errno); + untag_fprintf(stderr, "errno: %d\n", errno); return p != nullptr; } diff --git a/compiler-rt/test/hwasan/TestCases/Linux/release-shadow.c b/compiler-rt/test/hwasan/TestCases/Linux/release-shadow.c index 9aae35063366..68237fe1d3f3 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/release-shadow.c +++ b/compiler-rt/test/hwasan/TestCases/Linux/release-shadow.c @@ -12,6 +12,8 @@ #include +#include "../utils.h" + const unsigned char kTag = 42; const size_t kNumShadowPages = 256; const size_t kNumPages = 16 * kNumShadowPages; @@ -30,13 +32,13 @@ void sync_rss() { size_t current_rss() { sync_rss(); - int statm_fd = open("/proc/self/statm", O_RDONLY); + int statm_fd = open(UNTAG("/proc/self/statm"), O_RDONLY); assert(statm_fd >= 0); char buf[100]; assert(read(statm_fd, &buf, sizeof(buf)) > 0); size_t size, rss; - assert(sscanf(buf, "%zu %zu", &size, &rss) == 2); + assert(sscanf(buf, UNTAG("%zu %zu"), &size, &rss) == 2); close(statm_fd); return rss; @@ -47,20 +49,20 @@ void test_rss_difference(void *p) { size_t rss_before = current_rss(); __hwasan_tag_memory(p, 0, kMapSize); size_t rss_after = current_rss(); - fprintf(stderr, "%zu -> %zu\n", rss_before, rss_after); + untag_fprintf(stderr, "%zu -> %zu\n", rss_before, rss_after); assert(rss_before > rss_after); size_t diff = rss_before - rss_after; - fprintf(stderr, "diff %zu\n", diff); + untag_fprintf(stderr, "diff %zu\n", diff); // Check that the difference is at least close to kNumShadowPages. assert(diff > kNumShadowPages / 4 * 3); } int main() { - fprintf(stderr, "starting rss %zu\n", current_rss()); - fprintf(stderr, "shadow pages: %zu\n", kNumShadowPages); + untag_fprintf(stderr, "starting rss %zu\n", current_rss()); + untag_fprintf(stderr, "shadow pages: %zu\n", kNumShadowPages); void *p = mmap(0, kMapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - fprintf(stderr, "p = %p\n", p); + untag_fprintf(stderr, "p = %p\n", p); test_rss_difference(p); test_rss_difference(p); diff --git a/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp b/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp index 6c8321ee42cb..590bee36945e 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp +++ b/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp @@ -10,10 +10,12 @@ #include +#include "../utils.h" + pthread_barrier_t bar; void *threadfn(void *) { - pthread_barrier_wait(&bar); + pthread_barrier_wait(UNTAG(&bar)); return nullptr; } @@ -21,21 +23,21 @@ void start_stop_threads() { constexpr int N = 2; pthread_t threads[N]; - pthread_barrier_init(&bar, nullptr, N + 1); + pthread_barrier_init(UNTAG(&bar), nullptr, N + 1); for (auto &t : threads) pthread_create(&t, nullptr, threadfn, nullptr); - pthread_barrier_wait(&bar); + pthread_barrier_wait(UNTAG(&bar)); for (auto &t : threads) pthread_join(t, nullptr); - pthread_barrier_destroy(&bar); + pthread_barrier_destroy(UNTAG(&bar)); } int main() { // Cut off initial threads. // CHECK: === test start === - fprintf(stderr, "=== test start ===\n"); + untag_fprintf(stderr, "=== test start ===\n"); // CHECK: Creating : T{{[0-9]+}} [[A:0x[0-9a-f]+]] stack: // CHECK: Creating : T{{[0-9]+}} [[B:0x[0-9a-f]+]] stack: diff --git a/compiler-rt/test/hwasan/TestCases/Linux/vfork.c b/compiler-rt/test/hwasan/TestCases/Linux/vfork.c index 2b40c2bd1893..84e960279673 100644 --- a/compiler-rt/test/hwasan/TestCases/Linux/vfork.c +++ b/compiler-rt/test/hwasan/TestCases/Linux/vfork.c @@ -3,9 +3,6 @@ // REQUIRES: aarch64-target-arch || x86_64-target-arch -// Aliasing mode does not support stack tagging. -// XFAIL: x86_64 - #include #include #include diff --git a/compiler-rt/test/hwasan/TestCases/Posix/posix_memalign-alignment.cpp b/compiler-rt/test/hwasan/TestCases/Posix/posix_memalign-alignment.cpp index 0ccc2ad33886..5224dcb0ab1f 100644 --- a/compiler-rt/test/hwasan/TestCases/Posix/posix_memalign-alignment.cpp +++ b/compiler-rt/test/hwasan/TestCases/Posix/posix_memalign-alignment.cpp @@ -7,6 +7,8 @@ #include #include +#include "../utils.h" + int main() { void *p = reinterpret_cast(42); int res = posix_memalign(&p, 17, 100); @@ -15,7 +17,7 @@ int main() { // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cpp:}}[[@LINE-3]] // CHECK: SUMMARY: HWAddressSanitizer: invalid-posix-memalign-alignment - printf("pointer after failed posix_memalign: %zd\n", (size_t)p); + untag_printf("pointer after failed posix_memalign: %zd\n", (size_t)p); // CHECK-NULL: pointer after failed posix_memalign: 42 return 0; diff --git a/compiler-rt/test/hwasan/TestCases/allocator_returns_null.cpp b/compiler-rt/test/hwasan/TestCases/allocator_returns_null.cpp index e1326c319b57..11a9615f6f50 100644 --- a/compiler-rt/test/hwasan/TestCases/allocator_returns_null.cpp +++ b/compiler-rt/test/hwasan/TestCases/allocator_returns_null.cpp @@ -48,40 +48,42 @@ #include #include +#include "utils.h" + int main(int argc, char **argv) { assert(argc == 2); const char *action = argv[1]; - fprintf(stderr, "%s:\n", action); + untag_fprintf(stderr, "%s:\n", action); static const size_t kMaxAllowedMallocSizePlusOne = (1UL << 40) + 1; void *x = nullptr; - if (!strcmp(action, "malloc")) { + if (!untag_strcmp(action, "malloc")) { x = malloc(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "calloc")) { + } else if (!untag_strcmp(action, "calloc")) { x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4); - } else if (!strcmp(action, "calloc-overflow")) { + } else if (!untag_strcmp(action, "calloc-overflow")) { volatile size_t kMaxSizeT = std::numeric_limits::max(); size_t kArraySize = 4096; volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; x = calloc(kArraySize, kArraySize2); - } else if (!strcmp(action, "realloc")) { + } else if (!untag_strcmp(action, "realloc")) { x = realloc(0, kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "realloc-after-malloc")) { + } else if (!untag_strcmp(action, "realloc-after-malloc")) { char *t = (char*)malloc(100); *t = 42; x = realloc(t, kMaxAllowedMallocSizePlusOne); assert(*t == 42); free(t); - } else if (!strcmp(action, "new")) { + } else if (!untag_strcmp(action, "new")) { x = operator new(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "new-nothrow")) { + } else if (!untag_strcmp(action, "new-nothrow")) { x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); } else { assert(0); } - fprintf(stderr, "errno: %d\n", errno); + untag_fprintf(stderr, "errno: %d\n", errno); free(x); diff --git a/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c b/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c index 67398141209a..26a07c3b8969 100644 --- a/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c +++ b/compiler-rt/test/hwasan/TestCases/heap-buffer-overflow.c @@ -15,6 +15,8 @@ #include #include +#include "utils.h" + static volatile char sink; int main(int argc, char **argv) { @@ -22,21 +24,9 @@ int main(int argc, char **argv) { int offset = argc < 2 ? 40 : atoi(argv[1]); int size = argc < 3 ? 30 : atoi(argv[2]); char * volatile x = (char*)malloc(size); - fprintf(stderr, "base: %p access: %p\n", x, &x[offset]); + untag_fprintf(stderr, "base: %p access: %p\n", x, &x[offset]); sink = x[offset]; -#if defined(__x86_64__) - // Aliasing mode doesn't support the secondary allocator, so we fake a HWASan - // report instead of disabling the entire test. - if (size == 1000000) { - fprintf(stderr, "is a large allocated heap chunk; size: 1003520 offset: %d\n", - offset); - fprintf(stderr, "is located %s of 1000000-byte region\n", - offset == -30 ? "30 bytes to the left" : "0 bytes to the right"); - return -1; - } -#endif - // CHECK40: allocated heap chunk; size: 32 offset: 8 // CHECK40: is located 10 bytes to the right of 30-byte region // diff --git a/compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cpp b/compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cpp index 1abe209c10b5..fa6330bbcccd 100644 --- a/compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cpp +++ b/compiler-rt/test/hwasan/TestCases/hwasan-print-shadow.cpp @@ -8,7 +8,8 @@ #include int main() { - char *p = (char *)malloc(4096); + char *p = (char *)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); assert(p); __hwasan_tag_memory(p, 1, 32); @@ -25,6 +26,4 @@ int main() { // CHECK-NEXT: {{.*}}0: 0 // CHECK-NEXT: {{.*}}0: 0 // CHECK-NEXT: {{.*}}0: 4 - - free(p); } diff --git a/compiler-rt/test/hwasan/TestCases/malloc_fill.cpp b/compiler-rt/test/hwasan/TestCases/malloc_fill.cpp index c2debfb88d63..27e28c700071 100644 --- a/compiler-rt/test/hwasan/TestCases/malloc_fill.cpp +++ b/compiler-rt/test/hwasan/TestCases/malloc_fill.cpp @@ -8,15 +8,17 @@ #include +#include "utils.h" + int main(int argc, char **argv) { // With asan allocator this makes sure we get memory from mmap. static const int kSize = 1 << 25; unsigned char *x = new unsigned char[kSize]; - printf("-"); + untag_printf("-"); for (int i = 0; i <= 32; i++) { - printf("%02x", x[i]); + untag_printf("%02x", x[i]); } - printf("-\n"); + untag_printf("-\n"); delete [] x; } diff --git a/compiler-rt/test/hwasan/TestCases/many-threads-uaf.c b/compiler-rt/test/hwasan/TestCases/many-threads-uaf.c index 3a79cb37b608..e90432c57a01 100644 --- a/compiler-rt/test/hwasan/TestCases/many-threads-uaf.c +++ b/compiler-rt/test/hwasan/TestCases/many-threads-uaf.c @@ -7,6 +7,8 @@ #include +#include "utils.h" + void *BoringThread(void *arg) { char * volatile x = (char*)malloc(10); x[5] = 0; @@ -23,7 +25,7 @@ void *BoringThread(void *arg) { void *UAFThread(void *arg) { char * volatile x = (char*)malloc(10); - fprintf(stderr, "ZZZ %p\n", x); + untag_fprintf(stderr, "ZZZ %p\n", x); free(x); x[5] = 42; // CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address diff --git a/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c b/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c index 1c8df8676f98..4466ca2e4f02 100644 --- a/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c +++ b/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c @@ -12,6 +12,8 @@ #include #include +#include "utils.h" + int main() { char Q[16] __attribute__((aligned(256))); char P[16] __attribute__((aligned(256))); @@ -22,7 +24,7 @@ int main() { #elif TEST_NO == 3 memcpy(Q, P, 32); #endif - write(STDOUT_FILENO, "recovered\n", 10); + write(STDOUT_FILENO, UNTAG("recovered\n"), 10); // WRITE: ERROR: HWAddressSanitizer: tag-mismatch on address // WRITE: WRITE of size 32 at {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem) // WRITE: Invalid access starting at offset [16, 32) diff --git a/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp b/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp index c2a20be75def..736f8a8b923d 100644 --- a/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp +++ b/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp @@ -5,8 +5,10 @@ #include +#include "utils.h" + __attribute__((no_sanitize("hwaddress"))) extern "C" void callback(const char *msg) { - fprintf(stderr, "== error start\n%s\n== error end\n", msg); + untag_fprintf(stderr, "== error start\n%s\n== error end\n", msg); } int main() { diff --git a/compiler-rt/test/hwasan/TestCases/sizes.cpp b/compiler-rt/test/hwasan/TestCases/sizes.cpp index 4a1156b91b5c..1bfc760e1f9e 100644 --- a/compiler-rt/test/hwasan/TestCases/sizes.cpp +++ b/compiler-rt/test/hwasan/TestCases/sizes.cpp @@ -34,9 +34,11 @@ #include #include +#include "utils.h" + int main(int argc, char **argv) { assert(argc <= 3); - bool test_size_max = argc == 3 && !strcmp(argv[2], "max"); + bool test_size_max = argc == 3 && !untag_strcmp(argv[2], "max"); static const size_t kMaxAllowedMallocSize = 1ULL << 40; static const size_t kChunkHeaderSize = 16; @@ -44,26 +46,26 @@ int main(int argc, char **argv) { size_t MallocSize = test_size_max ? std::numeric_limits::max() : (kMaxAllowedMallocSize + 1); - if (!strcmp(argv[1], "malloc")) { + if (!untag_strcmp(argv[1], "malloc")) { void *p = malloc(MallocSize); assert(!p); - } else if (!strcmp(argv[1], "calloc")) { + } else if (!untag_strcmp(argv[1], "calloc")) { // Trigger an overflow in calloc. size_t size = std::numeric_limits::max(); void *p = calloc((size / 0x1000) + 1, 0x1000); assert(!p); - } else if (!strcmp(argv[1], "reallocarray")) { + } else if (!untag_strcmp(argv[1], "reallocarray")) { // Trigger an overflow in reallocarray. size_t size = std::numeric_limits::max(); void *p = __sanitizer_reallocarray(nullptr, (size / 0x1000) + 1, 0x1000); assert(!p); - } else if (!strcmp(argv[1], "new")) { + } else if (!untag_strcmp(argv[1], "new")) { void *p = operator new(MallocSize); assert(!p); - } else if (!strcmp(argv[1], "new-nothrow")) { + } else if (!untag_strcmp(argv[1], "new-nothrow")) { void *p = operator new(MallocSize, std::nothrow); assert(!p); - } else if (!strcmp(argv[1], "usable")) { + } else if (!untag_strcmp(argv[1], "usable")) { // Playing with the actual usable size of a chunk. void *p = malloc(1007); assert(p); diff --git a/compiler-rt/test/hwasan/TestCases/tail-magic.c b/compiler-rt/test/hwasan/TestCases/tail-magic.c index acce591a7ac9..73f31dbe5c90 100644 --- a/compiler-rt/test/hwasan/TestCases/tail-magic.c +++ b/compiler-rt/test/hwasan/TestCases/tail-magic.c @@ -10,20 +10,22 @@ #include #include +#include "utils.h" + static volatile char *sink; // Overwrite the tail in a non-hwasan function so that we don't detect the // stores as OOB. __attribute__((no_sanitize("hwaddress"))) void overwrite_tail() { - sink[20] = 0x42; - sink[24] = 0x66; + (*UNTAG(&sink))[20] = 0x42; + (*UNTAG(&sink))[24] = 0x66; } int main(int argc, char **argv) { __hwasan_enable_allocator_tagging(); char *p = (char*)malloc(20); - sink = p; + sink = UNTAG(p); overwrite_tail(); free(p); // CHECK: ERROR: HWAddressSanitizer: allocation-tail-overwritten; heap object [{{.*}}) of size 20 diff --git a/compiler-rt/test/hwasan/TestCases/use-after-free.c b/compiler-rt/test/hwasan/TestCases/use-after-free.c index 05ea7f4d7137..8d47acf4d5c3 100644 --- a/compiler-rt/test/hwasan/TestCases/use-after-free.c +++ b/compiler-rt/test/hwasan/TestCases/use-after-free.c @@ -11,12 +11,14 @@ #include #include +#include "utils.h" + int main() { __hwasan_enable_allocator_tagging(); char * volatile x = (char*)malloc(10); free(x); __hwasan_disable_allocator_tagging(); - fprintf(stderr, ISREAD ? "Going to do a READ\n" : "Going to do a WRITE\n"); + untag_fprintf(stderr, ISREAD ? "Going to do a READ\n" : "Going to do a WRITE\n"); // CHECK: Going to do a [[TYPE:[A-Z]*]] int r = 0; if (ISREAD) r = x[5]; else x[5] = 42; // should be on the same line. diff --git a/compiler-rt/test/hwasan/TestCases/utils.h b/compiler-rt/test/hwasan/TestCases/utils.h new file mode 100644 index 000000000000..7c9f8852d23c --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/utils.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +#define UNTAG(x) (typeof((x) + 0))(((uintptr_t)(x)) & 0xffffffffffffff) + +__attribute__((no_sanitize("hwaddress"))) +int untag_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int ret = vprintf(UNTAG(fmt), ap); + va_end(ap); + return ret; +} + +__attribute__((no_sanitize("hwaddress"))) +int untag_fprintf(FILE *stream, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int ret = vfprintf(stream, UNTAG(fmt), ap); + va_end(ap); + return ret; +} + +int untag_strcmp(const char *s1, const char *s2) { + return strcmp(UNTAG(s1), UNTAG(s2)); +} diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 07892bdc854b..1c368e7cd139 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -708,7 +708,7 @@ static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { } void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) { - if (TargetTriple.isAArch64() || TargetTriple.getArch() == Triple::x86_64) + if (TargetTriple.isAArch64()) return; IRBuilder<> IRB(I); @@ -1004,7 +1004,6 @@ Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty, // Remove tag from an address. Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) { - assert(!UsePageAliases); Value *UntaggedPtrLong; if (CompileKernel) { // Kernel addresses have 0xFF in the most significant byte. diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll index e85fc70fecfa..ce2c187cf039 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/atomic.ll @@ -11,7 +11,10 @@ define void @atomicrmw(i64* %ptr) sanitize_hwaddress { ; CHECK: call void @__hwasan_store8(i64 %[[A]]) -; CHECK: atomicrmw add i64* %ptr, i64 1 seq_cst +; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64* +; CHECK: atomicrmw add i64* %[[UNTAGGED_PTR]], i64 1 seq_cst ; CHECK: ret void entry: @@ -25,7 +28,10 @@ define void @cmpxchg(i64* %ptr, i64 %compare_to, i64 %new_value) sanitize_hwaddr ; CHECK: call void @__hwasan_store8(i64 %[[A]]) -; CHECK: cmpxchg i64* %ptr, i64 %compare_to, i64 %new_value seq_cst seq_cst +; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %ptr to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64* +; CHECK: cmpxchg i64* %[[UNTAGGED_PTR]], i64 %compare_to, i64 %new_value seq_cst seq_cst ; CHECK: ret void entry: diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/basic.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/basic.ll index 59e73c5f2081..e93ebb766252 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/X86/basic.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/basic.ll @@ -15,7 +15,10 @@ define i8 @test_load8(i8* %a) sanitize_hwaddress { ; ABORT: call void @__hwasan_load1(i64 %[[A]]) ; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]]) -; CHECK: %[[G:[^ ]*]] = load i8, i8* %a, align 4 +; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* +; CHECK: %[[G:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]], align 4 ; CHECK: ret i8 %[[G]] entry: @@ -30,7 +33,10 @@ define i40 @test_load40(i40* %a) sanitize_hwaddress { ; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5) ; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5) -; CHECK: %[[B:[^ ]*]] = load i40, i40* %a +; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* +; CHECK: %[[B:[^ ]*]] = load i40, i40* %[[UNTAGGED_PTR]] ; CHECK: ret i40 %[[B]] entry: @@ -45,7 +51,10 @@ define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress { ; ABORT: call void @__hwasan_store1(i64 %[[A]]) ; RECOVER: call void @__hwasan_store1_noabort(i64 %[[A]]) -; CHECK: store i8 %b, i8* %a, align 4 +; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* +; CHECK: store i8 %b, i8* %[[UNTAGGED_PTR]], align 4 ; CHECK: ret void entry: @@ -60,7 +69,10 @@ define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress { ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5) ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5) -; CHECK: store i40 %b, i40* %a +; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* +; CHECK: store i40 %b, i40* %[[UNTAGGED_PTR]] ; CHECK: ret void entry: @@ -75,7 +87,10 @@ define void @test_store_unaligned(i64* %a, i64 %b) sanitize_hwaddress { ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 8) ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 8) -; CHECK: store i64 %b, i64* %a, align 4 +; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i64* +; CHECK: store i64 %b, i64* %[[UNTAGGED_PTR]], align 4 ; CHECK: ret void entry: diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll index 7cea081f6dee..66e13daf68ff 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/kernel.ll @@ -18,7 +18,10 @@ define i8 @test_load(i8* %a) sanitize_hwaddress { ; ABORT: call void @__hwasan_load1(i64 %[[A]]) ; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]]) -; CHECK: %[[G:[^ ]*]] = load i8, i8* %a, align 4 +; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = or i64 %[[A]], -72057594037927936 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* +; CHECK: %[[G:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]], align 4 ; CHECK: ret i8 %[[G]] entry: diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll index 60d2f047b7f1..c6fce2fe2cac 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/with-calls.ll @@ -13,7 +13,10 @@ define i8 @test_load8(i8* %a) sanitize_hwaddress { ; ABORT: call void @__hwasan_load1(i64 %[[A]]) ; RECOVER: call void @__hwasan_load1_noabort(i64 %[[A]]) -; CHECK: %[[B:[^ ]*]] = load i8, i8* %a +; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* +; CHECK: %[[B:[^ ]*]] = load i8, i8* %[[UNTAGGED_PTR]] ; CHECK: ret i8 %[[B]] entry: @@ -28,7 +31,10 @@ define i40 @test_load40(i40* %a) sanitize_hwaddress { ; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5) ; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5) -; CHECK: %[[B:[^ ]*]] = load i40, i40* %a +; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* +; CHECK: %[[B:[^ ]*]] = load i40, i40* %[[UNTAGGED_PTR]] ; CHECK: ret i40 %[[B]] entry: @@ -43,7 +49,10 @@ define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress { ; ABORT: call void @__hwasan_store1(i64 %[[A]]) ; RECOVER: call void @__hwasan_store1_noabort(i64 %[[A]]) -; CHECK: store i8 %b, i8* %a +; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i8* +; CHECK: store i8 %b, i8* %[[UNTAGGED_PTR]] ; CHECK: ret void entry: @@ -58,7 +67,10 @@ define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress { ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5) ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5) -; CHECK: store i40 %b, i40* %a +; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 +; CHECK: %[[UNTAGGED:[^ ]*]] = and i64 %[[A]], 72057594037927935 +; CHECK: %[[UNTAGGED_PTR:[^ ]*]] = inttoptr i64 %[[UNTAGGED]] to i40* +; CHECK: store i40 %b, i40* %[[UNTAGGED_PTR]] ; CHECK: ret void entry: