[PATCH] malloc: Improve memalign alignment handling

Wilco Dijkstra Wilco.Dijkstra@arm.com
Wed Jan 28 17:44:41 GMT 2026


Use generic stdc_count_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.

Passes regress, OK for commit?

---

diff --git a/malloc/malloc.c b/malloc/malloc.c
index a49e211925ae6303d064b7e590fd015e85affe38..8fd8ec43960f7e0d95c0fca32f03439a3530c977 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3004,8 +3004,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_count_zeros ((size_t) MAX_TCACHE_SMALL_SIZE)
+	       - stdc_count_zeros (nb);
   return idx;
 }
 
@@ -3522,6 +3522,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_count_zeros ((size_t) 1)
+				 - stdc_count_zeros (alignment));
+      if (alignment == 0)
+	{
+	  __set_errno (EINVAL);
+	  return NULL;
+	}
+    }
+
   return _mid_memalign (alignment, bytes);
 }
 libc_hidden_def (__libc_memalign)
@@ -3534,8 +3547,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;
@@ -3581,28 +3594,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)
@@ -5386,9 +5377,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;
 
 


More information about the Libc-alpha mailing list