Add new malloc align tests.

Bug: 146576216

Test: Ran the test on jemalloc and glibc.
Test: Ran the test on scudo and verified that failed without the align
Test: change.
Change-Id: I31a96f8672c6bce2423210300288a13df1eda42a
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index ebbd247..fcdae85 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -29,6 +29,8 @@
 #include <unistd.h>
 
 #include <atomic>
+#include <thread>
+
 #include <tinyxml2.h>
 
 #include <android-base/file.h>
@@ -707,6 +709,119 @@
 #endif
 }
 
+template <typename Type>
+void __attribute__((optnone)) VerifyAlignment(Type* floating) {
+  size_t expected_alignment = alignof(Type);
+  if (expected_alignment != 0) {
+    ASSERT_EQ(0U, (expected_alignment - 1) & reinterpret_cast<uintptr_t>(floating))
+        << "Expected alignment " << expected_alignment << " ptr value " << floating;
+  }
+}
+
+template <typename Type>
+void __attribute__((optnone)) TestAllocateType() {
+  // The number of allocations to do in a row. This is to attempt to
+  // expose the worst case alignment for native allocators that use
+  // bins.
+  static constexpr size_t kMaxConsecutiveAllocs = 100;
+
+  // Verify using new directly.
+  Type* types[kMaxConsecutiveAllocs];
+  for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
+    types[i] = new Type;
+    VerifyAlignment(types[i]);
+    if (::testing::Test::HasFatalFailure()) {
+      return;
+    }
+  }
+  for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
+    delete types[i];
+  }
+
+  // Verify using malloc.
+  for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
+    types[i] = reinterpret_cast<Type*>(malloc(sizeof(Type)));
+    ASSERT_TRUE(types[i] != nullptr);
+    VerifyAlignment(types[i]);
+    if (::testing::Test::HasFatalFailure()) {
+      return;
+    }
+  }
+  for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
+    free(types[i]);
+  }
+
+  // Verify using a vector.
+  std::vector<Type> type_vector(kMaxConsecutiveAllocs);
+  for (size_t i = 0; i < type_vector.size(); i++) {
+    VerifyAlignment(&type_vector[i]);
+    if (::testing::Test::HasFatalFailure()) {
+      return;
+    }
+  }
+}
+
+#if defined(__ANDROID__)
+static void __attribute__((optnone)) AndroidVerifyAlignment(size_t alloc_size, size_t aligned_bytes) {
+  void* ptrs[100];
+  uintptr_t mask = aligned_bytes - 1;
+  for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
+    ptrs[i] = malloc(alloc_size);
+    ASSERT_TRUE(ptrs[i] != nullptr);
+    ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptrs[i]) & mask)
+        << "Expected at least " << aligned_bytes << " byte alignment: size "
+        << alloc_size << " actual ptr " << ptrs[i];
+  }
+}
+#endif
+
+TEST(malloc, align_check) {
+  // 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>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<double>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<long double>());
+
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<char>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<char16_t>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<char32_t>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<wchar_t>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<signed char>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<short int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<long int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<long long int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned char>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned short int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long int>());
+  ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long long int>());
+
+#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.
+
+  // 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.
+  for (size_t i = 1; i <= 128; i++) {
+    size_t rounded = (i + 7) & ~7;
+    if ((rounded % 16) == 0) {
+      AndroidVerifyAlignment(i, 16);
+    } else {
+      AndroidVerifyAlignment(i, 8);
+    }
+    if (::testing::Test::HasFatalFailure()) {
+      return;
+    }
+  }
+#endif
+}
+
 TEST(android_mallopt, error_on_unexpected_option) {
 #if defined(__BIONIC__)
   const int unrecognized_option = -1;