* lib/posix_memalign.c: Include stdckdint.h.
(posix_memalign): Test for overflow more straightforwardly,
and more portably to unlikely platforms where SIZE_MAX <= INT_MAX.
Treat a zero size as if it were alignment.
* m4/posix_memalign.m4 (gl_FUNC_POSIX_MEMALIGN):
* tests/test-posix_memalign.c (main):
Test zero size too. Use volatile to avoid compiler optimizations.
* modules/posix_memalign (Depends-on): Add stdckdint.
2024-10-30 Paul Eggert <eggert@cs.ucla.edu>
+ posix_memalign: check for GNU behavior with size 0
+ * lib/posix_memalign.c: Include stdckdint.h.
+ (posix_memalign): Test for overflow more straightforwardly,
+ and more portably to unlikely platforms where SIZE_MAX <= INT_MAX.
+ Treat a zero size as if it were alignment.
+ * m4/posix_memalign.m4 (gl_FUNC_POSIX_MEMALIGN):
+ * tests/test-posix_memalign.c (main):
+ Test zero size too. Use volatile to avoid compiler optimizations.
+ * modules/posix_memalign (Depends-on): Add stdckdint.
+
aligned_alloc: check for GNU behavior with size 0
If someone ever needs to distinguish between GNU and merely POSIX
behavior we can split this into two modules, but for now just
Portability problems fixed by Gnulib:
@itemize
@item
+This function returns a null pointer if the size argument is zero:
+AIX 7.3.
+@item
This function produces misaligned results on some platforms:
OpenBSD 6.1.
@end itemize
#include <stdlib.h>
#include <errno.h>
+#include <stdckdint.h>
int
posix_memalign (void **memptr, size_t alignment, size_t size)
#undef posix_memalign
{
- /* Round up SIZE to the next multiple of ALIGNMENT, namely
- (SIZE + ALIGNMENT - 1) & ~(ALIGNMENT - 1). */
- size += alignment - 1;
- if (size >= alignment - 1) /* no overflow? */
- return posix_memalign (memptr, alignment, size & ~(size_t)(alignment - 1));
- else
+ /* Round SIZE up to the next multiple of ALIGNMENT.
+ However, treat a zero size as if it were ALIGNMENT. */
+ size_t aligned_size;
+ if (ckd_add (&aligned_size, size, alignment - !!size))
return ENOMEM;
+ aligned_size &= -alignment;
+ return posix_memalign (memptr, alignment, aligned_size);
}
# posix_memalign.m4
-# serial 4
+# serial 5
dnl Copyright (C) 2020-2024 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
if test $ac_cv_func_posix_memalign = yes; then
dnl On OpenBSD 6.1, posix_memalign (&p, 32, 2406) stores a pointer
dnl that is not a multiple of 32.
- AC_CACHE_CHECK([whether posix_memalign works for large alignments],
+ dnl On AIX 7.3, aligned_alloc with a zero size returns NULL.
+ AC_CACHE_CHECK(
+ [whether posix_memalign works for large alignment or zero size],
[gl_cv_func_posix_memalign_works],
[AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdlib.h>
- ]],
+ /* Use pposix_memalign to test; 'volatile' prevents the compiler
+ from optimizing the malloc call away. */
+ int (*volatile pposix_memalign) (void **, size_t, size_t)
+ = posix_memalign;]],
[[void *p;
+ if (pposix_memalign (&p, 0, sizeof (void *)) != 0)
+ return 1;
if (32 % sizeof (void *) == 0
- && posix_memalign (&p, 32, 2406) == 0
+ && pposix_memalign (&p, 32, 2406) == 0
&& (unsigned long) p % 32 != 0)
return 1;
return 0;
[gl_cv_func_posix_memalign_works=no],
[case "$host_os" in
changequote(,)dnl
+ # Guess no on AIX.
+ aix*) gl_cv_func_aligned_alloc_works="guessing no" ;;
# Guess no on OpenBSD through 6.1.
openbsd[1-5].* | openbsd6.[01] | openbsd6.[01].*)
gl_cv_func_posix_memalign_works="guessing no" ;;
Depends-on:
extensions
+stdckdint [test $REPLACE_POSIX_MEMALIGN = 1]
stdlib
configure.ac:
{
#if HAVE_POSIX_MEMALIGN
static size_t sizes[] =
- { 13, 8, 17, 450, 320, 1, 99, 4, 15, 16, 2, 76, 37, 127, 2406, 641, 5781 };
+ {
+ 13, 8, 17, 450, 320, 1, 99, 4, 15, 16,
+ 2, 76, 37, 127, 2406, 641, 5781, 0
+ };
void *aligned2_blocks[SIZEOF (sizes)];
void *aligned4_blocks[SIZEOF (sizes)];
void *aligned8_blocks[SIZEOF (sizes)];