Merge "benchmarks: add 16 and 32 bytes to common sizes"
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 1feb871..d3e6a14 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -26,7 +26,10 @@
  * SUCH DAMAGE.
  */
 
+#include <platform/bionic/android_unsafe_frame_pointer_chase.h>
 #include <platform/bionic/malloc.h>
+#include <private/bionic_arc4random.h>
+#include <private/bionic_globals.h>
 #include <private/bionic_malloc_dispatch.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -64,9 +67,15 @@
   Opts.SampleRate = 2500;
   Opts.InstallSignalHandlers = false;
   Opts.InstallForkHandlers = true;
+  Opts.Backtrace = android_unsafe_frame_pointer_chase;
 
   GuardedAlloc.init(Opts);
-  info_log("GWP-ASan has been enabled.");
+  // TODO(b/149790891): The log line below causes ART tests to fail as they're
+  // not expecting any output. Disable the output for now.
+  // info_log("GWP-ASan has been enabled.");
+
+  __libc_shared_globals()->gwp_asan_state = GuardedAlloc.getAllocatorState();
+  __libc_shared_globals()->gwp_asan_metadata = GuardedAlloc.getMetadataRegion();
   return true;
 }
 
@@ -190,9 +199,15 @@
   Malloc(malloc_info),
 };
 
-// TODO(mitchp): Turn on GWP-ASan here probabilistically.
+// The probability (1 / kProcessSampleRate) that a process will be ranodmly
+// selected for sampling. kProcessSampleRate should always be a power of two to
+// avoid modulo bias.
+static constexpr uint8_t kProcessSampleRate = 128;
+
 bool ShouldGwpAsanSampleProcess() {
-  return false;
+  uint8_t random_number;
+  __libc_safe_arc4random_buf(&random_number, sizeof(random_number));
+  return random_number % kProcessSampleRate == 0;
 }
 
 bool MaybeInitGwpAsanFromLibc(libc_globals* globals) {
@@ -259,3 +274,7 @@
 
   return true;
 }
+
+bool DispatchIsGwpAsan(const MallocDispatch* dispatch) {
+  return dispatch == &gwp_asan_dispatch;
+}
diff --git a/libc/bionic/gwp_asan_wrappers.h b/libc/bionic/gwp_asan_wrappers.h
index fd9c547..a39d50b 100644
--- a/libc/bionic/gwp_asan_wrappers.h
+++ b/libc/bionic/gwp_asan_wrappers.h
@@ -37,3 +37,8 @@
 
 // Maybe initialize GWP-ASan. Set force_init to true to bypass process sampling.
 bool MaybeInitGwpAsan(libc_globals* globals, bool force_init = false);
+
+// Returns whether GWP-ASan is the provided dispatch table pointer. Used in
+// heapprofd's signal-initialization sequence to determine the intermediate
+// dispatch pointer to use when initing.
+bool DispatchIsGwpAsan(const MallocDispatch* dispatch);
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
index bf4c63a..198d2f0 100644
--- a/libc/bionic/malloc_heapprofd.cpp
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -42,6 +42,7 @@
 #include <private/bionic_malloc_dispatch.h>
 #include <sys/system_properties.h>
 
+#include "gwp_asan_wrappers.h"
 #include "malloc_common.h"
 #include "malloc_common_dynamic.h"
 #include "malloc_heapprofd.h"
@@ -86,30 +87,6 @@
 
 extern "C" void* MallocInitHeapprofdHook(size_t);
 
-static constexpr MallocDispatch __heapprofd_init_dispatch
-  __attribute__((unused)) = {
-    Malloc(calloc),
-    Malloc(free),
-    Malloc(mallinfo),
-    MallocInitHeapprofdHook, // malloc replacement
-    Malloc(malloc_usable_size),
-    Malloc(memalign),
-    Malloc(posix_memalign),
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-    Malloc(pvalloc),
-#endif
-    Malloc(realloc),
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-    Malloc(valloc),
-#endif
-    Malloc(malloc_iterate),
-    Malloc(malloc_disable),
-    Malloc(malloc_enable),
-    Malloc(mallopt),
-    Malloc(aligned_alloc),
-    Malloc(malloc_info),
-  };
-
 constexpr char kHeapprofdProgramPropertyPrefix[] = "heapprofd.enable.";
 constexpr size_t kHeapprofdProgramPropertyPrefixSize = sizeof(kHeapprofdProgramPropertyPrefix) - 1;
 constexpr size_t kMaxCmdlineSize = 512;
@@ -176,6 +153,15 @@
 //   is loaded synchronously).
 // In both cases, the caller is responsible for verifying that the process is
 // considered profileable.
+
+// Previously installed default dispatch table, if it exists. This is used to
+// load heapprofd properly when GWP-ASan was already installed. If GWP-ASan was
+// already installed, heapprofd will take over the dispatch table, but will use
+// GWP-ASan as the backing dispatch. This variable is atomically protected by
+// gHeapprofdInitInProgress.
+static const MallocDispatch* gPreviousDefaultDispatchTable = nullptr;
+static MallocDispatch gEphemeralDispatch;
+
 void HandleHeapprofdSignal() {
   if (atomic_load_explicit(&gHeapprofdIncompatibleHooks, memory_order_acquire)) {
     error_log("%s: not enabling heapprofd, malloc_debug/malloc_hooks are enabled.", getprogname());
@@ -187,11 +173,29 @@
   // not ever have a conflict modifying the globals.
   if (!atomic_exchange(&gGlobalsMutating, true)) {
     if (!atomic_exchange(&gHeapprofdInitInProgress, true)) {
+      // If the backing dispatch is GWP-ASan, we should use GWP-ASan as the
+      // intermediate dispatch table during initialisation. It may be possible
+      // at this point in time that heapprofd is *already* the default dispatch,
+      // and as such we don't want to use heapprofd as the backing store
+      // (otherwise infinite recursion occurs).
+      gPreviousDefaultDispatchTable = nullptr;
+      const MallocDispatch* default_dispatch = GetDefaultDispatchTable();
+      if (DispatchIsGwpAsan(default_dispatch)) {
+        gPreviousDefaultDispatchTable = default_dispatch;
+      }
+
       __libc_globals.mutate([](libc_globals* globals) {
-        atomic_store(&globals->default_dispatch_table, &__heapprofd_init_dispatch);
-        auto dispatch_table = GetDispatchTable();
-        if (!MallocLimitInstalled() || dispatch_table == &globals->malloc_dispatch_table) {
-          atomic_store(&globals->current_dispatch_table, &__heapprofd_init_dispatch);
+        // Wholesale copy the malloc dispatch table here. If the current/default
+        // dispatch table is pointing to the malloc_dispatch_table, we can't
+        // modify it as it may be racy. This dispatch table copy is ephemeral,
+        // and the dispatch tables will be resolved back to the global
+        // malloc_dispatch_table after initialization finishes.
+        gEphemeralDispatch = globals->malloc_dispatch_table;
+        gEphemeralDispatch.malloc = MallocInitHeapprofdHook;
+
+        atomic_store(&globals->default_dispatch_table, &gEphemeralDispatch);
+        if (!MallocLimitInstalled()) {
+          atomic_store(&globals->current_dispatch_table, &gEphemeralDispatch);
         }
       });
     }
@@ -241,6 +245,12 @@
     return;
   }
 
+  // Before we set the new default_dispatch_table in FinishInstallHooks, save
+  // the previous dispatch table. If DispatchReset() gets called later, we want
+  // to be able to restore the dispatch. We're still under
+  // gHeapprofdInitInProgress locks at this point.
+  gPreviousDefaultDispatchTable = GetDefaultDispatchTable();
+
   if (FinishInstallHooks(globals, nullptr, kHeapprofdPrefix)) {
     atomic_store(&gHeapprofdHandle, impl_handle);
   } else if (!reusing_handle) {
@@ -274,10 +284,9 @@
   if (!atomic_exchange(&gHeapprofdInitHookInstalled, true)) {
     pthread_mutex_lock(&gGlobalsMutateLock);
     __libc_globals.mutate([](libc_globals* globals) {
-      auto old_dispatch = GetDefaultDispatchTable();
-      atomic_store(&globals->default_dispatch_table, nullptr);
-      if (GetDispatchTable() == old_dispatch) {
-        atomic_store(&globals->current_dispatch_table, nullptr);
+      atomic_store(&globals->default_dispatch_table, gPreviousDefaultDispatchTable);
+      if (!MallocLimitInstalled()) {
+        atomic_store(&globals->current_dispatch_table, gPreviousDefaultDispatchTable);
       }
     });
     pthread_mutex_unlock(&gGlobalsMutateLock);
@@ -292,7 +301,10 @@
       error_log("%s: heapprod: failed to pthread_setname_np", getprogname());
     }
   }
-  return Malloc(malloc)(bytes);
+  // Get an allocation from libc malloc. If we had a previous dispatch table,
+  // this will come from it - otherwise, we'll get it from the system
+  // allocator.
+  return malloc(bytes);
 }
 
 bool HeapprofdInitZygoteChildProfiling() {
@@ -309,10 +321,9 @@
   if (!atomic_exchange(&gHeapprofdInitInProgress, true)) {
     pthread_mutex_lock(&gGlobalsMutateLock);
     __libc_globals.mutate([](libc_globals* globals) {
-      auto old_dispatch = GetDefaultDispatchTable();
-      atomic_store(&globals->default_dispatch_table, nullptr);
-      if (GetDispatchTable() == old_dispatch) {
-        atomic_store(&globals->current_dispatch_table, nullptr);
+      atomic_store(&globals->default_dispatch_table, gPreviousDefaultDispatchTable);
+      if (!MallocLimitInstalled()) {
+        atomic_store(&globals->current_dispatch_table, gPreviousDefaultDispatchTable);
       }
     });
     pthread_mutex_unlock(&gGlobalsMutateLock);
diff --git a/libc/include/bits/elf_mips.h b/libc/include/bits/elf_mips.h
deleted file mode 100644
index e29c481..0000000
--- a/libc/include/bits/elf_mips.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*	$NetBSD: elf_machdep.h,v 1.15 2011/03/15 07:39:22 matt Exp $	*/
-
-#ifndef _MIPS_ELF_MACHDEP_H_
-#define  _MIPS_ELF_MACHDEP_H_
-
-/* mips relocs.  */
-
-#define R_MIPS_NONE		0
-#define R_MIPS_16		1
-#define R_MIPS_32		2
-#define R_MIPS_REL32		3
-#define R_MIPS_REL		R_MIPS_REL32
-#define R_MIPS_26		4
-#define R_MIPS_HI16		5	/* high 16 bits of symbol value */
-#define R_MIPS_LO16		6	/* low 16 bits of symbol value */
-#define R_MIPS_GPREL16		7  	/* GP-relative reference  */
-#define R_MIPS_LITERAL		8 	/* Reference to literal section  */
-#define R_MIPS_GOT16		9	/* Reference to global offset table */
-#define R_MIPS_GOT		R_MIPS_GOT16
-#define R_MIPS_PC16		10  	/* 16 bit PC relative reference */
-#define R_MIPS_CALL16 		11  	/* 16 bit call thru glbl offset tbl */
-#define R_MIPS_CALL		R_MIPS_CALL16
-#define R_MIPS_GPREL32		12
-
-/* 13, 14, 15 are not defined at this point. */
-#define R_MIPS_UNUSED1		13
-#define R_MIPS_UNUSED2		14
-#define R_MIPS_UNUSED3		15
-
-/*
- * The remaining relocs are apparently part of the 64-bit Irix ELF ABI.
- */
-#define R_MIPS_SHIFT5		16
-#define R_MIPS_SHIFT6		17
-
-#define R_MIPS_64		18
-#define R_MIPS_GOT_DISP		19
-#define R_MIPS_GOT_PAGE		20
-#define R_MIPS_GOT_OFST		21
-#define R_MIPS_GOT_HI16		22
-#define R_MIPS_GOT_LO16		23
-#define R_MIPS_SUB 		24
-#define R_MIPS_INSERT_A		25
-#define R_MIPS_INSERT_B		26
-#define R_MIPS_DELETE		27
-#define R_MIPS_HIGHER		28
-#define R_MIPS_HIGHEST		29
-#define R_MIPS_CALL_HI16	30
-#define R_MIPS_CALL_LO16	31
-#define R_MIPS_SCN_DISP		32
-#define R_MIPS_REL16		33
-#define R_MIPS_ADD_IMMEDIATE	34
-#define R_MIPS_PJUMP		35
-#define R_MIPS_RELGOT		36
-#define	R_MIPS_JALR		37
-/* TLS relocations */
-
-#define R_MIPS_TLS_DTPMOD32	38	/* Module number 32 bit */
-#define R_MIPS_TLS_DTPREL32	39	/* Module-relative offset 32 bit */
-#define R_MIPS_TLS_DTPMOD64	40	/* Module number 64 bit */
-#define R_MIPS_TLS_DTPREL64	41	/* Module-relative offset 64 bit */
-#define R_MIPS_TLS_GD		42	/* 16 bit GOT offset for GD */
-#define R_MIPS_TLS_LDM		43	/* 16 bit GOT offset for LDM */
-#define R_MIPS_TLS_DTPREL_HI16	44	/* Module-relative offset, high 16 bits */
-#define R_MIPS_TLS_DTPREL_LO16	45	/* Module-relative offset, low 16 bits */
-#define R_MIPS_TLS_GOTTPREL	46	/* 16 bit GOT offset for IE */
-#define R_MIPS_TLS_TPREL32	47	/* TP-relative offset, 32 bit */
-#define R_MIPS_TLS_TPREL64	48	/* TP-relative offset, 64 bit */
-#define R_MIPS_TLS_TPREL_HI16	49	/* TP-relative offset, high 16 bits */
-#define R_MIPS_TLS_TPREL_LO16	50	/* TP-relative offset, low 16 bits */
-
-#define R_MIPS_max		51
-
-#define	R_MIPS16_min		100
-#define	R_MIPS16_26		100
-#define	R_MIPS16_GPREL		101
-#define	R_MIPS16_GOT16		102
-#define	R_MIPS16_CALL16		103
-#define	R_MIPS16_HI16		104
-#define	R_MIPS16_LO16		105
-#define	R_MIPS16_max		106
-
-
-/* mips dynamic tags */
-
-#define DT_MIPS_RLD_VERSION	0x70000001
-#define DT_MIPS_TIME_STAMP	0x70000002
-#define DT_MIPS_ICHECKSUM	0x70000003
-#define DT_MIPS_IVERSION	0x70000004
-#define DT_MIPS_FLAGS		0x70000005
-#define DT_MIPS_BASE_ADDRESS	0x70000006
-#define DT_MIPS_CONFLICT	0x70000008
-#define DT_MIPS_LIBLIST		0x70000009
-#define DT_MIPS_CONFLICTNO	0x7000000b
-#define	DT_MIPS_LOCAL_GOTNO	0x7000000a	/* number of local got ents */
-#define DT_MIPS_LIBLISTNO	0x70000010
-#define	DT_MIPS_SYMTABNO	0x70000011	/* number of .dynsym entries */
-#define DT_MIPS_UNREFEXTNO	0x70000012
-#define	DT_MIPS_GOTSYM		0x70000013	/* first dynamic sym in got */
-#define DT_MIPS_HIPAGENO	0x70000014
-#define	DT_MIPS_RLD_MAP		0x70000016	/* address of loader map */
-#define DT_MIPS_RLD_MAP_REL	0x70000035	/* offset of loader map, used for PIE */
-
-/*
- * ELF Flags
- */
-#define	EF_MIPS_PIC		0x00000002	/* Contains PIC code */
-#define	EF_MIPS_CPIC		0x00000004	/* STD PIC calling sequence */
-#define	EF_MIPS_ABI2		0x00000020	/* N32 */
-
-#define	EF_MIPS_ARCH_ASE	0x0f000000	/* Architectural extensions */
-#define	EF_MIPS_ARCH_MDMX	0x08000000	/* MDMX multimedia extension */
-#define	EF_MIPS_ARCH_M16	0x04000000	/* MIPS-16 ISA extensions */
-
-#define	EF_MIPS_ARCH		0xf0000000	/* Architecture field */
-#define	EF_MIPS_ARCH_1		0x00000000	/* -mips1 code */
-#define	EF_MIPS_ARCH_2		0x10000000	/* -mips2 code */
-#define	EF_MIPS_ARCH_3		0x20000000	/* -mips3 code */
-#define	EF_MIPS_ARCH_4		0x30000000	/* -mips4 code */
-#define	EF_MIPS_ARCH_5		0x40000000	/* -mips5 code */
-#define	EF_MIPS_ARCH_32		0x50000000	/* -mips32 code */
-#define	EF_MIPS_ARCH_64		0x60000000	/* -mips64 code */
-#define	EF_MIPS_ARCH_32R2	0x70000000	/* -mips32r2 code */
-#define	EF_MIPS_ARCH_64R2	0x80000000	/* -mips64r2 code */
-
-#define	EF_MIPS_ABI		0x0000f000
-#define	EF_MIPS_ABI_O32		0x00001000
-#define	EF_MIPS_ABI_O64		0x00002000
-#define	EF_MIPS_ABI_EABI32	0x00003000
-#define	EF_MIPS_ABI_EABI64	0x00004000
-
-#endif /* _MIPS_ELF_MACHDEP_H_ */
diff --git a/libc/include/bits/fortify/string.h b/libc/include/bits/fortify/string.h
index 4a7ed12..beb5ff5 100644
--- a/libc/include/bits/fortify/string.h
+++ b/libc/include/bits/fortify/string.h
@@ -204,21 +204,17 @@
                          "'strlcat' called with size bigger than buffer") {
 #if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
     return __strlcat_chk(dst, src, size, __bos(dst));
-#endif
+#else
     return __call_bypassing_fortify(strlcat)(dst, src, size);
+#endif
 }
 
+#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
 __BIONIC_FORTIFY_INLINE
 size_t strlen(const char* const s __pass_object_size0) __overloadable {
-#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
-    size_t bos = __bos0(s);
-
-    if (!__bos_trivially_gt(bos, __builtin_strlen(s))) {
-        return __strlen_chk(s, bos);
-    }
-#endif
-    return __builtin_strlen(s);
+    return __strlen_chk(s, __bos0(s));
 }
+#endif
 
 __BIONIC_FORTIFY_INLINE
 char* strchr(const char* const s __pass_object_size, int c) __overloadable {
diff --git a/libc/include/elf.h b/libc/include/elf.h
index a319abb..4739bbd 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -33,7 +33,6 @@
 #include <bits/auxvec.h>
 #include <bits/elf_arm.h>
 #include <bits/elf_arm64.h>
-#include <bits/elf_mips.h>
 #include <bits/elf_x86.h>
 #include <bits/elf_x86_64.h>
 #include <linux/elf.h>
diff --git a/libc/platform/bionic/mte.h b/libc/platform/bionic/mte.h
index 661664a..fbf3895 100644
--- a/libc/platform/bionic/mte.h
+++ b/libc/platform/bionic/mte.h
@@ -42,20 +42,26 @@
 }
 #endif
 
-struct ScopedDisableMTE {
-  ScopedDisableMTE() {
 #ifdef __aarch64__
+class ScopedDisableMTE {
+  size_t prev_tco_;
+
+ public:
+  ScopedDisableMTE() {
     if (mte_supported()) {
-      __asm__ __volatile__(".arch_extension mte; msr tco, #1");
+      __asm__ __volatile__(".arch_extension mte; mrs %0, tco; msr tco, #1" : "=r"(prev_tco_));
     }
-#endif
   }
 
   ~ScopedDisableMTE() {
-#ifdef __aarch64__
     if (mte_supported()) {
-      __asm__ __volatile__(".arch_extension mte; msr tco, #0");
+      __asm__ __volatile__(".arch_extension mte; msr tco, %0" : : "r"(prev_tco_));
     }
-#endif
   }
 };
+#else
+struct ScopedDisableMTE {
+  // Silence unused variable warnings in non-aarch64 builds.
+  ScopedDisableMTE() {}
+};
+#endif
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 4cc9bbe..6e7eb76 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -65,6 +65,10 @@
 __LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals;
 
 struct abort_msg_t;
+namespace gwp_asan {
+struct AllocatorState;
+struct AllocationMetadata;
+};  // namespace gwp_asan
 
 // Globals shared between the dynamic linker and libc.so.
 struct libc_shared_globals {
@@ -96,6 +100,9 @@
   // Values passed from the linker to libc.so.
   const char* init_progname = nullptr;
   char** init_environ = nullptr;
+
+  const gwp_asan::AllocatorState *gwp_asan_state = nullptr;
+  const gwp_asan::AllocationMetadata *gwp_asan_metadata = nullptr;
 };
 
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 03b08b6..15b6a40 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -3448,16 +3448,12 @@
     return path;
   }
 
-  // Use generated linker config if flag is set
-  // TODO(b/138920271) Do not check property once it is confirmed as stable
-  if (android::base::GetBoolProperty("sys.linker.use_generated_config", true)) {
-    if (file_exists(kLdGeneratedConfigFilePath)) {
-      return kLdGeneratedConfigFilePath;
-    } else {
-      // TODO(b/146386369) : Adjust log level and add more condition to log only when necessary
-      INFO("Warning: failed to find generated linker configuration from \"%s\"",
-           kLdGeneratedConfigFilePath);
-    }
+  if (file_exists(kLdGeneratedConfigFilePath)) {
+    return kLdGeneratedConfigFilePath;
+  } else {
+    // TODO(b/146386369) : Adjust log level and add more condition to log only when necessary
+    INFO("Warning: failed to find generated linker configuration from \"%s\"",
+         kLdGeneratedConfigFilePath);
   }
 
   path = get_ld_config_file_vndk_path();
diff --git a/linker/linker_debuggerd_android.cpp b/linker/linker_debuggerd_android.cpp
index b8c82f9..42ea2b7 100644
--- a/linker/linker_debuggerd_android.cpp
+++ b/linker/linker_debuggerd_android.cpp
@@ -39,6 +39,12 @@
       return __libc_shared_globals()->abort_msg;
     },
     .post_dump = &notify_gdb_of_libraries,
+    .get_gwp_asan_state = []() {
+      return __libc_shared_globals()->gwp_asan_state;
+    },
+    .get_gwp_asan_metadata = []() {
+      return __libc_shared_globals()->gwp_asan_metadata;
+    },
   };
   debuggerd_init(&callbacks);
 }
diff --git a/tests/mte_test.cpp b/tests/mte_test.cpp
index 2f922a2..8928805 100644
--- a/tests/mte_test.cpp
+++ b/tests/mte_test.cpp
@@ -16,17 +16,30 @@
 
 #include <gtest/gtest.h>
 
+#include <android-base/macros.h>
 #include <bionic/mte.h>
 
 __attribute__((no_sanitize("hwaddress")))
 static void test_tag_mismatch() {
-  ScopedDisableMTE x;
-#if defined(__aarch64__)
   std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
   p[0] = 1;
-  int* mistagged_p = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(p.get()) + (1ULL << 56));
-  volatile int load = *mistagged_p;
-  (void)load;
+  int* mistagged_p ATTRIBUTE_UNUSED =
+      reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(p.get()) + (1ULL << 56));
+  {
+    ScopedDisableMTE x;
+    { ScopedDisableMTE y; }
+#if defined(__aarch64__)
+    volatile int load ATTRIBUTE_UNUSED = *mistagged_p;
+#endif
+  }
+#if defined(__aarch64__)
+  if (mte_supported()) {
+    EXPECT_DEATH(
+        {
+          volatile int load ATTRIBUTE_UNUSED = *mistagged_p;
+        },
+        "");
+  }
 #endif
 }