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

Reply via email to