Collin Funk wrote:
> FreeBSD 15.0 was released today.
In a testdir, I see a test failure:
FAIL: test-realloc-posix
========================
../../gltests/test-realloc-posix.c:66: assertion 'errno == ENOMEM' failed
FAIL test-realloc-posix (exit status: 134)
The reason is that realloc (p, size) sets errno when failing only when
size <= 0x700000000000000; it leaves errno untouched if
size > 0x700000000000000.
This patch provides a workaround.
Collin, if you want to send a bug report to the FreeBSD people, here's
my test program:
=========================== foo.c ===========================
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
size_t b = (argc > 1 ? atol (argv[1]) : PTRDIFF_MAX + 1);
errno = 1729;
void *p = malloc (1);
printf ("p = 0x%lx, errno = %d\n", (unsigned long) p, errno);
p = realloc (p, b);
printf ("p = 0x%lx, errno = %d\n", (unsigned long) p, errno);
}
===============================================================
2025-12-02 Bruno Haible <[email protected]>
realloc-posix: Add workaround for FreeBSD 15.0.
* m4/realloc.m4 (gl_FUNC_REALLOC_POSIX): Test whether realloc sets
errno on failure. Define HAVE_REALLOC_POSIX if yes. Use the
gl_FUNC_MALLOC_POSIX result only on non-BSD platforms.
* m4/malloc.m4 (gl_FUNC_MALLOC_POSIX, gl_CHECK_MALLOC_POSIX): Don't
mention realloc here. Update comments.
* lib/realloc.c (rpl_realloc): Test HAVE_REALLOC_POSIX instead of
HAVE_MALLOC_POSIX.
* doc/posix-functions/realloc.texi: Mention FreeBSD 15 bug.
diff --git a/doc/posix-functions/realloc.texi b/doc/posix-functions/realloc.texi
index a70c33d665..5a0feb8521 100644
--- a/doc/posix-functions/realloc.texi
+++ b/doc/posix-functions/realloc.texi
@@ -12,7 +12,7 @@
@itemize
@item
On some platforms, when the function fails it does not set @code{errno}:
-mingw, MSVC 14.
+FreeBSD 15 (for a size > 0x7000000000000000), mingw, MSVC 14.
@item
On some platforms, when the function fails it might set @code{errno}
diff --git a/lib/realloc.c b/lib/realloc.c
index 62efd5a39f..cf0bf6e9f7 100644
--- a/lib/realloc.c
+++ b/lib/realloc.c
@@ -94,7 +94,7 @@ rpl_realloc (void *p, size_t n)
void *result = realloc (p, n1);
-# if !HAVE_MALLOC_POSIX
+# if !HAVE_REALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
# endif
diff --git a/m4/malloc.m4 b/m4/malloc.m4
index 688594fe66..e4bf33a789 100644
--- a/m4/malloc.m4
+++ b/m4/malloc.m4
@@ -1,5 +1,5 @@
# malloc.m4
-# serial 44
+# serial 45
dnl Copyright (C) 2007, 2009-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -99,7 +99,7 @@ AC_DEFUN([gl_FUNC_MALLOC_PTRDIFF]
[REPLACE_MALLOC_FOR_MALLOC_POSIX=1])
])
-# Test whether malloc, realloc, calloc refuse to create objects
+# Test whether malloc, calloc refuse to create objects
# larger than what can be expressed in ptrdiff_t.
# Set gl_cv_func_malloc_gnu.
AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF],
@@ -148,7 +148,7 @@ AC_DEFUN([gl_FUNC_MALLOC_POSIX]
case "$gl_cv_func_malloc_posix" in
*yes)
AC_DEFINE([HAVE_MALLOC_POSIX], [1],
- [Define if malloc, realloc, and calloc set errno on allocation
failure.])
+ [Define if malloc and calloc set errno on allocation failure.])
;;
*)
REPLACE_MALLOC_FOR_MALLOC_POSIX=1
@@ -156,19 +156,20 @@ AC_DEFUN([gl_FUNC_MALLOC_POSIX]
esac
])
-# Test whether malloc, realloc, calloc set errno to ENOMEM on failure.
+# Test whether malloc, calloc set errno to ENOMEM on failure.
# Set gl_cv_func_malloc_posix to *yes or *no accordingly.
AC_DEFUN([gl_CHECK_MALLOC_POSIX],
[
AC_REQUIRE([AC_CANONICAL_HOST])
- AC_CACHE_CHECK([whether malloc, realloc, calloc set errno on failure],
+ AC_CACHE_CHECK([whether malloc, calloc set errno on failure],
[gl_cv_func_malloc_posix],
[
dnl It is too dangerous to try to allocate a large amount of memory:
dnl some systems go to their knees when you do that. So assume that
dnl all Unix implementations of the function set errno on failure,
dnl except on those platforms where we have seen 'test-malloc-gnu',
- dnl 'test-realloc-posix', 'test-calloc-gnu' fail.
+ dnl 'test-realloc-posix', 'test-calloc-gnu' fail. For platforms
+ dnl where only 'test-realloc-posix', see realloc.m4.
case "$host_os" in
mingw* | windows*)
dnl Old MSVCRT from 2001 did not set errno=ENOMEM when malloc failed.
diff --git a/m4/realloc.m4 b/m4/realloc.m4
index 0242abdc8c..a6c2ec4c33 100644
--- a/m4/realloc.m4
+++ b/m4/realloc.m4
@@ -1,5 +1,5 @@
# realloc.m4
-# serial 39
+# serial 40
dnl Copyright (C) 2007, 2009-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -27,13 +27,54 @@ AC_DEFUN([gl_FUNC_REALLOC_POSIX]
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_REQUIRE([gl_FUNC_MALLOC_POSIX])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_CACHE_CHECK([whether realloc sets errno on failure],
+ [gl_cv_func_realloc_posix],
+ [
+ dnl FreeBSD 15.0 realloc() does not set errno when asked for more than
+ dnl 0x7000000000000000 bytes.
+ case "$host_os" in
+ darwin* | freebsd* | dragonfly* | midnightbsd* | netbsd* | openbsd*)
+ AC_RUN_IFELSE(
+ [AC_LANG_SOURCE(
+ [[#include <errno.h>
+ #include <stdlib.h>
+ int main (int argc, char **argv)
+ {
+ void *p;
+ errno = 1729;
+ p = realloc (malloc (1), (size_t)(-1) / 100 * 49);
+ return (!p && errno == 1729);
+ }
+ ]])
+ ],
+ [gl_cv_func_realloc_posix=yes],
+ [gl_cv_func_realloc_posix=no],
+ [case "$host_os" in
+ freebsd*) gl_cv_func_realloc_posix="guessing no" ;;
+ *) gl_cv_func_realloc_posix="guessing yes" ;;
+ esac
+ ])
+ ;;
+ *)
+ gl_cv_func_realloc_posix="$gl_cv_func_malloc_posix"
+ ;;
+ esac
+ ])
+ case "$gl_cv_func_realloc_posix" in
+ *yes)
+ AC_DEFINE([HAVE_REALLOC_POSIX], [1],
+ [Define if realloc sets errno on allocation failure.])
+ ;;
+ *)
+ REPLACE_REALLOC_FOR_REALLOC_POSIX=1
+ ;;
+ esac
AC_REQUIRE([gl_FUNC_REALLOC_SANITIZED])
if test "$gl_cv_func_realloc_sanitize" != no; then
REPLACE_REALLOC_FOR_REALLOC_POSIX=1
AC_DEFINE([NEED_SANITIZED_REALLOC], [1],
[Define to 1 if realloc should abort upon undefined behaviour.])
- else
- REPLACE_REALLOC_FOR_REALLOC_POSIX=$REPLACE_MALLOC_FOR_MALLOC_POSIX
fi
])