[PATCH v2] malloc: Improve memalign alignment
Wilco Dijkstra
Wilco.Dijkstra@arm.com
Tue Feb 24 17:17:12 GMT 2026
v2: use stdc_leading_zeros, improve testing of memalign
Use generic stdc_leading_zeros to safely adapt to input types. Move rounding up of
alignments that are not powers of 2 to __libc_memalign. Simplify alignment handling
of aligned_alloc and __posix_memalign. Add a testcase for non-power of 2 memalign
and fix malloc-debug.
Passes regress, OK for commit?
---
diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
index 269003b4eff28cf74be54e62a433a06fd6a280b5..46e1860dcf32bdb682737d1f42c6296bcef5ff8e 100644
--- a/malloc/malloc-debug.c
+++ b/malloc/malloc-debug.c
@@ -269,6 +269,12 @@ _debug_mid_memalign (size_t alignment, size_t bytes, const void *address)
static void *
__debug_memalign (size_t alignment, size_t bytes)
{
+ alignment = stdc_bit_ceil (alignment);
+ if (alignment == 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
return _debug_mid_memalign (alignment, bytes, RETURN_ADDRESS (0));
}
strong_alias (__debug_memalign, memalign)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 0ff016e549694f457c3fe090f3265d35f1d60e28..d3bf2b9b7687b721cd157e5688ad83944c780e92 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3000,8 +3000,8 @@ static __always_inline size_t
large_csize2tidx(size_t nb)
{
size_t idx = TCACHE_SMALL_BINS
- + __builtin_clz (MAX_TCACHE_SMALL_SIZE)
- - __builtin_clz (nb);
+ + stdc_leading_zeros ((size_t) MAX_TCACHE_SMALL_SIZE)
+ - stdc_leading_zeros (nb);
return idx;
}
@@ -3518,6 +3518,19 @@ libc_hidden_def (__libc_realloc)
void *
__libc_memalign (size_t alignment, size_t bytes)
{
+ /* Round the alignment up to a power of 2, and report an error on overflow.
+ Zero alignment is handled by _mid_memalign. */
+ if (__glibc_unlikely (!powerof2 (alignment)))
+ {
+ alignment = (size_t) 2 << (stdc_bit_width (alignment) - 1);
+
+ if (alignment == 0)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+ }
+
return _mid_memalign (alignment, bytes);
}
libc_hidden_def (__libc_memalign)
@@ -3530,8 +3543,8 @@ aligned_alloc (size_t alignment, size_t bytes)
/* Similar to memalign, but starting with ISO C17 the standard
requires an error for alignments that are not supported by the
implementation. Valid alignments for the current implementation
- are non-negative powers of two. */
- if (!powerof2 (alignment) || alignment == 0)
+ are powers of two. */
+ if (!stdc_has_single_bit (alignment))
{
__set_errno (EINVAL);
return NULL;
@@ -3577,28 +3590,6 @@ _mid_memalign (size_t alignment, size_t bytes)
if (alignment <= MALLOC_ALIGNMENT)
return __libc_malloc (bytes);
- /* Otherwise, ensure that it is at least a minimum chunk size */
- if (alignment < MINSIZE)
- alignment = MINSIZE;
-
- /* If the alignment is greater than SIZE_MAX / 2 + 1 it cannot be a
- power of 2 and will cause overflow in the check below. */
- if (alignment > SIZE_MAX / 2 + 1)
- {
- __set_errno (EINVAL);
- return NULL;
- }
-
-
- /* Make sure alignment is power of 2. */
- if (!powerof2 (alignment))
- {
- size_t a = MALLOC_ALIGNMENT * 2;
- while (a < alignment)
- a <<= 1;
- alignment = a;
- }
-
#if USE_TCACHE
void *victim = tcache_get_align (checked_request2size (bytes), alignment);
if (victim != NULL)
@@ -5317,9 +5308,7 @@ __posix_memalign (void **memptr, size_t alignment, size_t size)
/* Test whether the SIZE argument is valid. It must be a power of
two multiple of sizeof (void *). */
- if (alignment % sizeof (void *) != 0
- || !powerof2 (alignment / sizeof (void *))
- || alignment == 0)
+ if (alignment < sizeof (void *) || !powerof2 (alignment))
return EINVAL;
diff --git a/malloc/tst-memalign.c b/malloc/tst-memalign.c
index 771dd9c62eb708a8f3bd5c508794abbf9aa2a54d..ade37091b8223bad5c223f8b73271d7aed90c8f1 100644
--- a/malloc/tst-memalign.c
+++ b/malloc/tst-memalign.c
@@ -107,10 +107,10 @@ do_test (void)
free (p);
/* Check the alignment of the returned pointer is correct. */
- p = memalign (0x100, 10);
+ p = memalign (129, 10);
if (p == NULL)
- merror ("memalign (0x100, 10) failed.");
+ merror ("memalign (129, 10) failed.");
ptrval = (unsigned long) p;
More information about the Libc-alpha
mailing list