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


Reply via email to