Merge "Random HWASan cleanups."
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 6eb1749..8c51347 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -277,3 +277,14 @@
 bool DispatchIsGwpAsan(const MallocDispatch* dispatch) {
   return dispatch == &gwp_asan_dispatch;
 }
+
+bool EnableGwpAsan(bool force_init) {
+  if (GwpAsanInitialized) {
+    return true;
+  }
+
+  bool ret_value;
+  __libc_globals.mutate(
+      [&](libc_globals* globals) { ret_value = MaybeInitGwpAsan(globals, force_init); });
+  return ret_value;
+}
diff --git a/libc/bionic/gwp_asan_wrappers.h b/libc/bionic/gwp_asan_wrappers.h
index a39d50b..c568681 100644
--- a/libc/bionic/gwp_asan_wrappers.h
+++ b/libc/bionic/gwp_asan_wrappers.h
@@ -32,6 +32,9 @@
 #include <private/bionic_malloc_dispatch.h>
 #include <stddef.h>
 
+// Enable GWP-ASan, used by android_mallopt.
+bool EnableGwpAsan(bool force_init);
+
 // Hooks for libc to possibly install GWP-ASan.
 bool MaybeInitGwpAsanFromLibc(libc_globals* globals);
 
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index c91efa0..38168ee 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -330,9 +330,8 @@
       errno = EINVAL;
       return false;
     }
-    __libc_globals.mutate([&](libc_globals* globals) {
-      return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
-    });
+
+    return EnableGwpAsan(*reinterpret_cast<bool*>(arg));
   }
   errno = ENOTSUP;
   return false;
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 31d1e69..1f58fda 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -530,9 +530,8 @@
       errno = EINVAL;
       return false;
     }
-    __libc_globals.mutate([&](libc_globals* globals) {
-      return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
-    });
+
+    return EnableGwpAsan(*reinterpret_cast<bool*>(arg));
   }
   // Try heapprofd's mallopt, as it handles options not covered here.
   return HeapprofdMallopt(opcode, arg, arg_size);
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 3f22007..1386e30 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -875,7 +875,7 @@
 }
 #endif
 
-TEST(malloc, align_check) {
+void AlignCheck() {
   // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445
   // for a discussion of type alignment.
   ASSERT_NO_FATAL_FAILURE(TestAllocateType<float>());
@@ -899,22 +899,35 @@
 
 #if defined(__ANDROID__)
   // On Android, there is a lot of code that expects certain alignments:
-  // - Allocations of a size that rounds up to a multiple of 16 bytes
-  //   must have at least 16 byte alignment.
-  // - Allocations of a size that rounds up to a multiple of 8 bytes and
-  //   not 16 bytes, are only required to have at least 8 byte alignment.
-  // This is regardless of whether it is in a 32 bit or 64 bit environment.
+  //  1. Allocations of a size that rounds up to a multiple of 16 bytes
+  //     must have at least 16 byte alignment.
+  //  2. Allocations of a size that rounds up to a multiple of 8 bytes and
+  //     not 16 bytes, are only required to have at least 8 byte alignment.
+  // In addition, on Android clang has been configured for 64 bit such that:
+  //  3. Allocations <= 8 bytes must be aligned to at least 8 bytes.
+  //  4. Allocations > 8 bytes must be aligned to at least 16 bytes.
+  // For 32 bit environments, only the first two requirements must be met.
 
   // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for
   // a discussion of this alignment mess. The code below is enforcing
   // strong-alignment, since who knows what code depends on this behavior now.
+  // As mentioned before, for 64 bit this will enforce the higher
+  // requirement since clang expects this behavior on Android now.
   for (size_t i = 1; i <= 128; i++) {
+#if defined(__LP64__)
+    if (i <= 8) {
+      AndroidVerifyAlignment(i, 8);
+    } else {
+      AndroidVerifyAlignment(i, 16);
+    }
+#else
     size_t rounded = (i + 7) & ~7;
     if ((rounded % 16) == 0) {
       AndroidVerifyAlignment(i, 16);
     } else {
       AndroidVerifyAlignment(i, 8);
     }
+#endif
     if (::testing::Test::HasFatalFailure()) {
       return;
     }
@@ -922,6 +935,22 @@
 #endif
 }
 
+TEST(malloc, align_check) {
+  AlignCheck();
+}
+
+// Force GWP-ASan on and verify all alignment checks still pass.
+TEST(malloc, align_check_gwp_asan) {
+#if defined(__BIONIC__)
+  bool force_init = true;
+  ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
+
+  AlignCheck();
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
 // Jemalloc doesn't pass this test right now, so leave it as disabled.
 TEST(malloc, DISABLED_alloc_after_fork) {
   // Both of these need to be a power of 2.
@@ -1271,6 +1300,22 @@
 #endif
 }
 
+TEST(android_mallopt, force_init_gwp_asan) {
+#if defined(__BIONIC__)
+  bool force_init = true;
+  ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
+
+  // Verify that trying to do the call again also passes no matter the
+  // value of force_init.
+  force_init = false;
+  ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
+  force_init = true;
+  ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
+#else
+  GTEST_SKIP() << "bionic extension";
+#endif
+}
+
 void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
   std::vector<void*> allocs;
   constexpr int kMaxBytesToCheckZero = 64;