On Wed, Oct 30, 2024 at 3:51 PM Paul Eggert <egg...@cs.ucla.edu> wrote: > > * 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. > --- > ChangeLog | 10 ++++++++++ > doc/posix-functions/posix_memalign.texi | 3 +++ > lib/posix_memalign.c | 13 +++++++------ > m4/posix_memalign.m4 | 17 +++++++++++++---- > modules/posix_memalign | 1 + > tests/test-posix_memalign.c | 5 ++++- > 6 files changed, 38 insertions(+), 11 deletions(-) > > diff --git a/ChangeLog b/ChangeLog > index 61296ba779..6ce890f5cc 100644 > --- a/ChangeLog > +++ b/ChangeLog > @@ -1,5 +1,15 @@ > 2024-10-30 Paul Eggert <egg...@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 > diff --git a/doc/posix-functions/posix_memalign.texi > b/doc/posix-functions/posix_memalign.texi > index 6585513548..d802fd6ebe 100644 > --- a/doc/posix-functions/posix_memalign.texi > +++ b/doc/posix-functions/posix_memalign.texi > @@ -14,6 +14,9 @@ it is more portable to older systems that do not support > C11. > 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 > diff --git a/lib/posix_memalign.c b/lib/posix_memalign.c > index 6a13c56710..6dd713bdb5 100644 > --- a/lib/posix_memalign.c > +++ b/lib/posix_memalign.c > @@ -20,16 +20,17 @@ > #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;
I don't think ENOMEM is a good error for the condition. I guess you can't return EOVERFLOW or ERANGE? Maybe EINVAL would be better if that's the case. > + aligned_size &= -alignment; > + return posix_memalign (memptr, alignment, aligned_size); > } > diff --git a/m4/posix_memalign.m4 b/m4/posix_memalign.m4 > index e814ec1560..37c40a528d 100644 > --- a/m4/posix_memalign.m4 > +++ b/m4/posix_memalign.m4 > @@ -1,5 +1,5 @@ > # 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, > @@ -18,15 +18,22 @@ AC_DEFUN([gl_FUNC_POSIX_MEMALIGN], > 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; > @@ -36,6 +43,8 @@ AC_DEFUN([gl_FUNC_POSIX_MEMALIGN], > [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" ;; > diff --git a/modules/posix_memalign b/modules/posix_memalign > index 0bcdf18414..e50e44ef23 100644 > --- a/modules/posix_memalign > +++ b/modules/posix_memalign > @@ -7,6 +7,7 @@ m4/posix_memalign.m4 > > Depends-on: > extensions > +stdckdint [test $REPLACE_POSIX_MEMALIGN = 1] > stdlib > > configure.ac: > diff --git a/tests/test-posix_memalign.c b/tests/test-posix_memalign.c > index 160e55b177..b61ac4e2a0 100644 > --- a/tests/test-posix_memalign.c > +++ b/tests/test-posix_memalign.c > @@ -33,7 +33,10 @@ main (int argc, char *argv[]) > { > #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)]; > -- > 2.43.0 Jeff