Make aligned_alloc match the standard.
Jemalloc does not verify that the size parameter is a multiple of
alignment. Fix this since it only went into P.
Fix the unit tests, and fix malloc debug/malloc hooks to handle this
new restrictive behavior.
Bug: 126944692
Test: Ran bionic unit tests.
Test: Ran bionic unit tests with malloc hooks enabled (no new tests fail).
Test: Ran bionic unit tests with malloc debug enabled (no new tests fail).
Test: Ran malloc debug unit tests.
Change-Id: I4d50785928815679c781ca729f998454d76b9192
diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h
index 79a4f72..3fd36e4 100644
--- a/libc/bionic/jemalloc.h
+++ b/libc/bionic/jemalloc.h
@@ -22,14 +22,19 @@
// Need to wrap memalign since je_memalign fails on non-power of 2 alignments.
#define je_memalign je_memalign_round_up_boundary
+// Need to wrap aligned_alloc since je_aligned_alloc does not enforce
+// that size is a multiple of alignment.
+#define je_aligned_alloc je_aligned_alloc_wrapper
+
__BEGIN_DECLS
-struct mallinfo je_mallinfo();
-int je_mallopt(int, int);
+void* je_aligned_alloc_wrapper(size_t, size_t);
int je_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
+int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+struct mallinfo je_mallinfo();
void je_malloc_disable();
void je_malloc_enable();
-int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+int je_mallopt(int, int);
void* je_memalign_round_up_boundary(size_t, size_t);
void* je_pvalloc(size_t);
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index ef0d384..c513246 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <errno.h>
#include <malloc.h>
#include <sys/param.h>
#include <unistd.h>
@@ -48,6 +49,20 @@
return je_memalign(boundary, size);
}
+#ifdef je_aligned_alloc
+#undef je_aligned_alloc
+#endif
+
+// The aligned_alloc function requires that size is a multiple of alignment.
+// jemalloc doesn't enforce this, so add enforcement here.
+void* je_aligned_alloc_wrapper(size_t alignment, size_t size) {
+ if ((size % alignment) != 0) {
+ errno = EINVAL;
+ return nullptr;
+ }
+ return je_aligned_alloc(alignment, size);
+}
+
int je_mallopt(int param, int value) {
// The only parameter we currently understand is M_DECAY_TIME.
if (param == M_DECAY_TIME) {
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 2e6afff..f662957 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -729,7 +729,7 @@
if (DebugCallsDisabled()) {
return g_dispatch->aligned_alloc(alignment, size);
}
- if (!powerof2(alignment)) {
+ if (!powerof2(alignment) || (size % alignment) != 0) {
errno = EINVAL;
return nullptr;
}
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 6da95ca..a72db3b 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -318,7 +318,7 @@
ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
debug_free(pointer);
- pointer = debug_aligned_alloc(128, 15);
+ pointer = debug_aligned_alloc(16, 16);
ASSERT_TRUE(pointer != nullptr);
ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
debug_free(pointer);
@@ -2144,9 +2144,9 @@
debug_free(pointer);
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
- pointer = debug_aligned_alloc(32, 50);
+ pointer = debug_aligned_alloc(32, 64);
ASSERT_TRUE(pointer != nullptr);
- expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
+ expected += android::base::StringPrintf("%d: memalign %p 32 64\n", getpid(), pointer);
debug_free(pointer);
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
diff --git a/libc/malloc_hooks/malloc_hooks.cpp b/libc/malloc_hooks/malloc_hooks.cpp
index f7bdd56..715a629 100644
--- a/libc/malloc_hooks/malloc_hooks.cpp
+++ b/libc/malloc_hooks/malloc_hooks.cpp
@@ -176,7 +176,7 @@
void* hooks_aligned_alloc(size_t alignment, size_t size) {
if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
- if (!powerof2(alignment)) {
+ if (!powerof2(alignment) || (size % alignment) != 0) {
errno = EINVAL;
return nullptr;
}