Fix the default alignment of the allocations.
In order to enforce this constraint:
The pointer returned if the allocation succeeds shall be suitably
aligned so that it may be assigned to a pointer to any type of object
and then used to access such an object in the space allocated.
Force all allocations on 32 bit systems to have 8 byte alignment,
and all allocations on 64 bit systems to have 16 byte alignment.
Add a test to verify that the allocator returns the correct alignments.
Bug: 26739265
Change-Id: I9af53279617408676b94e4ec6481b3ed7ffafc6a
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index d3a9d01..8fba1c4 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -430,3 +430,73 @@
void* p2 = realloc(p, 0);
ASSERT_TRUE(p2 == nullptr);
}
+
+constexpr size_t MAX_LOOPS = 200;
+
+// Make sure that memory returned by malloc is aligned to allow these data types.
+TEST(malloc, verify_alignment) {
+ uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
+ uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
+ long double** values_ldouble = new long double*[MAX_LOOPS];
+ // Use filler to attempt to force the allocator to get potentially bad alignments.
+ void** filler = new void*[MAX_LOOPS];
+
+ for (size_t i = 0; i < MAX_LOOPS; i++) {
+ // Check uint32_t pointers.
+ filler[i] = malloc(1);
+ ASSERT_TRUE(filler[i] != nullptr);
+
+ values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
+ ASSERT_TRUE(values_32[i] != nullptr);
+ *values_32[i] = i;
+ ASSERT_EQ(*values_32[i], i);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
+
+ free(filler[i]);
+ }
+
+ for (size_t i = 0; i < MAX_LOOPS; i++) {
+ // Check uint64_t pointers.
+ filler[i] = malloc(1);
+ ASSERT_TRUE(filler[i] != nullptr);
+
+ values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
+ ASSERT_TRUE(values_64[i] != nullptr);
+ *values_64[i] = 0x1000 + i;
+ ASSERT_EQ(*values_64[i], 0x1000 + i);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
+
+ free(filler[i]);
+ }
+
+ for (size_t i = 0; i < MAX_LOOPS; i++) {
+ // Check long double pointers.
+ filler[i] = malloc(1);
+ ASSERT_TRUE(filler[i] != nullptr);
+
+ values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
+ ASSERT_TRUE(values_ldouble[i] != nullptr);
+ *values_ldouble[i] = 5.5 + i;
+ ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
+ // 32 bit glibc has a long double size of 12 bytes, so hardcode the
+ // required alignment to 0x7.
+#if !defined(__BIONIC__) && !defined(__LP64__)
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
+#else
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
+#endif
+
+ free(filler[i]);
+ }
+
+ for (size_t i = 0; i < MAX_LOOPS; i++) {
+ free(values_32[i]);
+ free(values_64[i]);
+ free(values_ldouble[i]);
+ }
+
+ delete[] filler;
+ delete[] values_32;
+ delete[] values_64;
+ delete[] values_ldouble;
+}