Also, port better to non-glibc, and in documentation update the list of platforms needing a fix. This includes 32-bit platforms using AddressSanitizer, unfortunately. * m4/malloc.m4 (gl_CHECK_MALLOC_PTRDIFF): Invoke gl_MUSL_LIBC. musl is safe, as is FreeBSD 11+, NetBSD 8+, OpenBSD 5.6+, AIX, Microsoft Windows. However, the AddressSanitizer is unsafe. --- ChangeLog | 10 +++++++++ doc/posix-functions/calloc.texi | 8 +++++-- doc/posix-functions/malloc.texi | 8 +++++-- doc/posix-functions/realloc.texi | 8 +++++-- doc/posix-functions/reallocarray.texi | 9 ++++++-- m4/malloc.m4 | 31 ++++++++++++++++++++++----- 6 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 757e1b7fe9..b384d22d81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2026-07-27 Paul Eggert <[email protected]> + + malloc: port to current -m32 AddressSanitizer + Also, port better to non-glibc, and in documentation update the + list of platforms needing a fix. This includes 32-bit platforms + using AddressSanitizer, unfortunately. + * m4/malloc.m4 (gl_CHECK_MALLOC_PTRDIFF): Invoke gl_MUSL_LIBC. + musl is safe, as is FreeBSD 11+, NetBSD 8+, OpenBSD 5.6+, AIX, + Microsoft Windows. However, the AddressSanitizer is unsafe. + 2026-07-26 Bruno Haible <[email protected]> [v]szprintf: Improve port to Fil-C. diff --git a/doc/posix-functions/calloc.texi b/doc/posix-functions/calloc.texi index 37e6e008b5..4df0d9da7b 100644 --- a/doc/posix-functions/calloc.texi +++ b/doc/posix-functions/calloc.texi @@ -21,9 +21,13 @@ calloc Solaris 11.4. @item -On some platforms, @code{calloc (n, s)} can succeed even if +On some 32-bit platforms, @code{calloc (n, s)} can succeed even if multiplying @code{n} by @code{s} would exceed @code{PTRDIFF_MAX} or -@code{SIZE_MAX}. Although failing to check for exceeding +@code{SIZE_MAX}, which can lead to undefined behavior later: +AddressSanitizer of gcc 16.1 or clang 22.1, glibc 2.29, FreeBSD 10.4, +NetBSD 7.2, OpenBSD 5.5, macOS 10.14, AIX 7.3, Solaris 11.4. + +Although failing to check for exceeding @code{PTRDIFF_MAX} is arguably allowed by POSIX it can lead to undefined behavior later, so @code{calloc-posix} does not allow going over the limit. diff --git a/doc/posix-functions/malloc.texi b/doc/posix-functions/malloc.texi index 0b552bdf67..e4df390b37 100644 --- a/doc/posix-functions/malloc.texi +++ b/doc/posix-functions/malloc.texi @@ -21,8 +21,12 @@ malloc Solaris 11.4. @item -On some platforms, @code{malloc (n)} can succeed even if @code{n} -exceeds @code{PTRDIFF_MAX}. Although this behavior is arguably +On some 32-bit platforms, @code{malloc (n)} can succeed even if @code{n} +exceeds @code{PTRDIFF_MAX}, which can lead to undefined behavior later: +AddressSanitizer of gcc 16.1 or clang 22.1, glibc 2.29, FreeBSD 10.4, +NetBSD 7.2, OpenBSD 5.5, macOS 10.14, AIX 7.3, Solaris 11.4. + +Although this behavior is arguably allowed by POSIX it can lead to behavior not defined by POSIX later, so @code{malloc-posix} does not allow going over the limit. @end itemize diff --git a/doc/posix-functions/realloc.texi b/doc/posix-functions/realloc.texi index 94dad44a59..1309efa93c 100644 --- a/doc/posix-functions/realloc.texi +++ b/doc/posix-functions/realloc.texi @@ -23,8 +23,12 @@ realloc Solaris 11.4. @item -On some platforms, @code{realloc (p, n)} can succeed even if @code{n} -exceeds @code{PTRDIFF_MAX}. Although this behavior is arguably +On some 32-bit platforms, @code{realloc (p, n)} can succeed even if @code{n} +exceeds @code{PTRDIFF_MAX}, which can lead to undefined behavior later: +AddressSanitizer of gcc 16.1 or clang 22.1, glibc 2.29, FreeBSD 10.4, +NetBSD 7.2, OpenBSD 5.5, macOS 10.14, AIX 7.3, Solaris 11.4. + +Although this behavior is arguably allowed by POSIX it is not compatible with GNU and can lead to behavior not defined by POSIX later, so @code{realloc-posix} does not allow going over the limit. diff --git a/doc/posix-functions/reallocarray.texi b/doc/posix-functions/reallocarray.texi index 39408e42c9..db0ec936c0 100644 --- a/doc/posix-functions/reallocarray.texi +++ b/doc/posix-functions/reallocarray.texi @@ -34,10 +34,15 @@ reallocarray Solaris 11.4. @item -On some platforms, @code{reallocarray (p, n, s)} can succeed even if +On some 32-bit platforms, @code{reallocarray (p, n, s)} can succeed even if multiplying @code{n} by @code{s} would exceed @code{PTRDIFF_MAX}, which can lead to undefined behavior later: -FreeBSD 13, NetBSD 9, OpenBSD 6, musl 1.2. +AddressSanitizer of gcc 16.1 or clang 22.1, glibc 2.29, Solaris 11.4. + +Although this behavior is arguably +allowed by POSIX it is not compatible with GNU and +can lead to behavior not defined by POSIX later, +so @code{realloc-posix} does not allow going over the limit. @item It is not portable to call diff --git a/m4/malloc.m4 b/m4/malloc.m4 index a95e33db86..567b0e89d6 100644 --- a/m4/malloc.m4 +++ b/m4/malloc.m4 @@ -1,5 +1,5 @@ # malloc.m4 -# serial 46 +# serial 47 dnl Copyright (C) 2007, 2009-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -104,6 +104,7 @@ AC_DEFUN([gl_FUNC_MALLOC_PTRDIFF] # Set gl_cv_func_malloc_gnu. AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF], [ + gl_MUSL_LIBC AC_CACHE_CHECK([whether malloc is ptrdiff_t safe], [gl_cv_malloc_ptrdiff], [AC_COMPILE_IFELSE( @@ -118,10 +119,30 @@ AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF] is no problem. */ #define NARROW_SIZE (SIZE_MAX <= PTRDIFF_MAX) - /* glibc 2.30 and later malloc refuses to exceed ptrdiff_t - bounds even on 32-bit platforms. We don't know which - non-glibc systems are safe. */ - #define KNOWN_SAFE (2 < __GLIBC__ + (30 <= __GLIBC_MINOR__)) + /* Whether address sanitization is in use. + clang 4 through 21 signal this only with __has_feature. */ + #if !defined __SANITIZE_ADDRESS__ && defined __has_feature + # if __has_feature (address_sanitizer) + # define __SANITIZE_ADDRESS__ 1 + # endif + #endif + + #if __OpenBSD__ || __NetBSD__ + #include <sys/param.h> + #endif + + /* Many platforms are safe: malloc stays in ptrdiff_t bounds. + However, with address sanitization, gcc (up to at least + gcc 16.1) and clang (up to at least clang 22) interpose + a malloc that can go over a 32-bit ptrdiff_t limit. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126436 + https://github.com/llvm/llvm-project/issues/212288 + If we don't know a platform is safe, assume it's unsafe. */ + #define KNOWN_SAFE \ + (((2 < __GLIBC__ + (30 <= __GLIBC_MINOR__)) || MUSL_LIBC \ + || 11 <= __FreeBSD__ || 800000000 <= __NetBSD_Version__ \ + || 201411 <= OpenBSD || defined _WIN32) \ + && !__SANITIZE_ADDRESS__) #if WIDE_PTRDIFF || NARROW_SIZE || KNOWN_SAFE return 0; -- 2.55.0
