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/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 61267f0..400e282 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -44,7 +44,7 @@
BacktraceData::BacktraceData(const Config& config, size_t* offset) {
size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames;
alloc_offset_ = *offset;
- *offset += BIONIC_ALIGN(hdr_len, sizeof(uintptr_t));
+ *offset += BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
}
static BacktraceData* g_backtrace_data = nullptr;
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 032c1fc..ce83aa4 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -347,10 +347,10 @@
valid = valid && parser.Done();
if (valid) {
- // It's necessary to align the front guard to sizeof(uintptr_t) to
+ // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
// make sure that the header is aligned properly.
if (options & FRONT_GUARD) {
- front_guard_bytes = BIONIC_ALIGN(front_guard_bytes, sizeof(uintptr_t));
+ front_guard_bytes = BIONIC_ALIGN(front_guard_bytes, MINIMUM_ALIGNMENT_BYTES);
}
// This situation can occur if the free_track option is specified and
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index d2cc56d..cb1de5a 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -41,6 +41,14 @@
constexpr uint64_t TRACK_ALLOCS = 0x80;
constexpr uint64_t LEAK_TRACK = 0x100;
+// In order to guarantee posix compliance, set the minimum alignment
+// to 8 bytes for 32 bit systems and 16 bytes for 64 bit systems.
+#if defined(__LP64__)
+constexpr size_t MINIMUM_ALIGNMENT_BYTES = 16;
+#else
+constexpr size_t MINIMUM_ALIGNMENT_BYTES = 8;
+#endif
+
// If only one or more of these options is set, then no special header is needed.
constexpr uint64_t NO_HEADER_OPTIONS = FILL_ON_ALLOC | FILL_ON_FREE | EXPAND_ALLOC;
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index bf2a0f5..92b866d 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -47,7 +47,7 @@
need_header_ = true;
// Initialize all of the static header offsets.
- pointer_offset_ = BIONIC_ALIGN(sizeof(Header), sizeof(uintptr_t));
+ pointer_offset_ = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
if (config_.options & BACKTRACE) {
backtrace.reset(new BacktraceData(config_, &pointer_offset_));
diff --git a/libc/malloc_debug/GuardData.cpp b/libc/malloc_debug/GuardData.cpp
index 4ba5253..c70e8f1 100644
--- a/libc/malloc_debug/GuardData.cpp
+++ b/libc/malloc_debug/GuardData.cpp
@@ -75,7 +75,7 @@
// Create a buffer for fast comparisons of the front guard.
cmp_mem_.resize(config.front_guard_bytes);
memset(cmp_mem_.data(), config.front_guard_value, cmp_mem_.size());
- // Assumes that front_bytes is a multiple of sizeof(uintptr_t).
+ // Assumes that front_bytes is a multiple of MINIMUM_ALIGNMENT_BYTES.
offset_ = *offset;
*offset += config.front_guard_bytes;
}
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 4f86579..0c0907d 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -39,6 +39,7 @@
#include <private/bionic_malloc_dispatch.h>
#include "backtrace.h"
+#include "Config.h"
#include "DebugData.h"
#include "debug_disable.h"
#include "debug_log.h"
@@ -264,7 +265,8 @@
return nullptr;
}
- Header* header = reinterpret_cast<Header*>(g_dispatch->memalign(sizeof(uintptr_t), real_size));
+ Header* header = reinterpret_cast<Header*>(
+ g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
if (header == nullptr) {
return nullptr;
}
@@ -355,10 +357,10 @@
if (!powerof2(alignment)) {
alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
- // Force the alignment to at least sizeof(uintptr_t) to guarantee
+ // Force the alignment to at least MINIMUM_ALIGNMENT_BYTES to guarantee
// that the header is aligned properly.
- if (alignment < sizeof(uintptr_t)) {
- alignment = sizeof(uintptr_t);
+ if (alignment < MINIMUM_ALIGNMENT_BYTES) {
+ alignment = MINIMUM_ALIGNMENT_BYTES;
}
// We don't have any idea what the natural alignment of
@@ -512,7 +514,8 @@
}
// Need to guarantee the alignment of the header.
- Header* header = reinterpret_cast<Header*>(g_dispatch->memalign(sizeof(uintptr_t), real_size));
+ Header* header = reinterpret_cast<Header*>(
+ g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
if (header == nullptr) {
return nullptr;
}
diff --git a/libc/malloc_debug/malloc_debug.h b/libc/malloc_debug/malloc_debug.h
index 6f9f90f..347fae2 100644
--- a/libc/malloc_debug/malloc_debug.h
+++ b/libc/malloc_debug/malloc_debug.h
@@ -39,7 +39,7 @@
// will still be in this order.
// Header (Required)
// BacktraceHeader (Optional: For the allocation backtrace)
-// uint8_t data (Optional: Front guard, will be a multiple of sizeof(uintptr_t))
+// uint8_t data (Optional: Front guard, will be a multiple of MINIMUM_ALIGNMENT_BYTES)
// allocation data
// uint8_t data (Optional: End guard)
//
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 551e498..1c800db 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -230,6 +230,10 @@
ASSERT_EQ(FRONT_GUARD, config->options);
ASSERT_EQ(40U, config->front_guard_bytes);
+ ASSERT_TRUE(InitConfig("front_guard=41"));
+ ASSERT_EQ(FRONT_GUARD, config->options);
+ ASSERT_EQ(48U, config->front_guard_bytes);
+
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
}
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 9fc8a57..b316e8a 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -34,6 +34,7 @@
#include <private/bionic_macros.h>
#include <private/bionic_malloc_dispatch.h>
+#include "Config.h"
#include "malloc_debug.h"
#include "log_fake.h"
@@ -70,9 +71,9 @@
constexpr uint32_t BACKTRACE_HEADER = 0x1;
static size_t get_tag_offset(uint32_t flags = 0, size_t backtrace_frames = 0) {
- size_t offset = BIONIC_ALIGN(sizeof(Header), sizeof(uintptr_t));
+ size_t offset = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
if (flags & BACKTRACE_HEADER) {
- offset += BIONIC_ALIGN(sizeof(BacktraceHeader) + sizeof(uintptr_t) * backtrace_frames, sizeof(uintptr_t));
+ offset += BIONIC_ALIGN(sizeof(BacktraceHeader) + sizeof(uintptr_t) * backtrace_frames, MINIMUM_ALIGNMENT_BYTES);
}
return offset;
}