| 1 | # malloc.m4 serial 28
 | 
|---|
| 2 | dnl Copyright (C) 2007, 2009-2022 Free Software Foundation, Inc.
 | 
|---|
| 3 | dnl This file is free software; the Free Software Foundation
 | 
|---|
| 4 | dnl gives unlimited permission to copy and/or distribute it,
 | 
|---|
| 5 | dnl with or without modifications, as long as this notice is preserved.
 | 
|---|
| 6 | 
 | 
|---|
| 7 | # This is adapted with modifications from upstream Autoconf here:
 | 
|---|
| 8 | # https://git.savannah.gnu.org/cgit/autoconf.git/tree/lib/autoconf/functions.m4?id=v2.70#n949
 | 
|---|
| 9 | AC_DEFUN([_AC_FUNC_MALLOC_IF],
 | 
|---|
| 10 | [
 | 
|---|
| 11 |   AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
 | 
|---|
| 12 |   AC_CACHE_CHECK([whether malloc (0) returns nonnull],
 | 
|---|
| 13 |     [ac_cv_func_malloc_0_nonnull],
 | 
|---|
| 14 |     [AC_RUN_IFELSE(
 | 
|---|
| 15 |        [AC_LANG_PROGRAM(
 | 
|---|
| 16 |           [[#include <stdlib.h>
 | 
|---|
| 17 |           ]],
 | 
|---|
| 18 |           [[void *p = malloc (0);
 | 
|---|
| 19 |             int result = !p;
 | 
|---|
| 20 |             free (p);
 | 
|---|
| 21 |             return result;]])
 | 
|---|
| 22 |        ],
 | 
|---|
| 23 |        [ac_cv_func_malloc_0_nonnull=yes],
 | 
|---|
| 24 |        [ac_cv_func_malloc_0_nonnull=no],
 | 
|---|
| 25 |        [case "$host_os" in
 | 
|---|
| 26 |           # Guess yes on platforms where we know the result.
 | 
|---|
| 27 |           *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \
 | 
|---|
| 28 |           | gnu* | *-musl* | midnightbsd* \
 | 
|---|
| 29 |           | hpux* | solaris* | cygwin* | mingw* | msys* )
 | 
|---|
| 30 |             ac_cv_func_malloc_0_nonnull="guessing yes" ;;
 | 
|---|
| 31 |           # If we don't know, obey --enable-cross-guesses.
 | 
|---|
| 32 |           *) ac_cv_func_malloc_0_nonnull="$gl_cross_guess_normal" ;;
 | 
|---|
| 33 |         esac
 | 
|---|
| 34 |        ])
 | 
|---|
| 35 |     ])
 | 
|---|
| 36 |   AS_CASE([$ac_cv_func_malloc_0_nonnull], [*yes], [$1], [$2])
 | 
|---|
| 37 | ])# _AC_FUNC_MALLOC_IF
 | 
|---|
| 38 | 
 | 
|---|
| 39 | # gl_FUNC_MALLOC_GNU
 | 
|---|
| 40 | # ------------------
 | 
|---|
| 41 | # Replace malloc if it is not compatible with GNU libc.
 | 
|---|
| 42 | AC_DEFUN([gl_FUNC_MALLOC_GNU],
 | 
|---|
| 43 | [
 | 
|---|
| 44 |   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
 | 
|---|
| 45 |   AC_REQUIRE([gl_FUNC_MALLOC_POSIX])
 | 
|---|
| 46 |   REPLACE_MALLOC_FOR_MALLOC_GNU="$REPLACE_MALLOC_FOR_MALLOC_POSIX"
 | 
|---|
| 47 |   if test $REPLACE_MALLOC_FOR_MALLOC_GNU = 0; then
 | 
|---|
| 48 |     _AC_FUNC_MALLOC_IF([], [REPLACE_MALLOC_FOR_MALLOC_GNU=1])
 | 
|---|
| 49 |   fi
 | 
|---|
| 50 | ])
 | 
|---|
| 51 | 
 | 
|---|
| 52 | # gl_FUNC_MALLOC_PTRDIFF
 | 
|---|
| 53 | # ----------------------
 | 
|---|
| 54 | # Test whether malloc (N) reliably fails when N exceeds PTRDIFF_MAX,
 | 
|---|
| 55 | # and replace malloc otherwise.
 | 
|---|
| 56 | AC_DEFUN([gl_FUNC_MALLOC_PTRDIFF],
 | 
|---|
| 57 | [
 | 
|---|
| 58 |   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
 | 
|---|
| 59 |   AC_REQUIRE([gl_CHECK_MALLOC_PTRDIFF])
 | 
|---|
| 60 |   test "$gl_cv_malloc_ptrdiff" = yes || REPLACE_MALLOC_FOR_MALLOC_POSIX=1
 | 
|---|
| 61 | ])
 | 
|---|
| 62 | 
 | 
|---|
| 63 | # Test whether malloc, realloc, calloc refuse to create objects
 | 
|---|
| 64 | # larger than what can be expressed in ptrdiff_t.
 | 
|---|
| 65 | # Set gl_cv_func_malloc_gnu to yes or no accordingly.
 | 
|---|
| 66 | AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF],
 | 
|---|
| 67 | [
 | 
|---|
| 68 |   AC_CACHE_CHECK([whether malloc is ptrdiff_t safe],
 | 
|---|
| 69 |     [gl_cv_malloc_ptrdiff],
 | 
|---|
| 70 |     [AC_COMPILE_IFELSE(
 | 
|---|
| 71 |        [AC_LANG_PROGRAM(
 | 
|---|
| 72 |           [[#include <stdint.h>
 | 
|---|
| 73 |           ]],
 | 
|---|
| 74 |           [[/* 64-bit ptrdiff_t is so wide that no practical platform
 | 
|---|
| 75 |                can exceed it.  */
 | 
|---|
| 76 |             #define WIDE_PTRDIFF (PTRDIFF_MAX >> 31 >> 31 != 0)
 | 
|---|
| 77 | 
 | 
|---|
| 78 |             /* On rare machines where size_t fits in ptrdiff_t there
 | 
|---|
| 79 |                is no problem.  */
 | 
|---|
| 80 |             #define NARROW_SIZE (SIZE_MAX <= PTRDIFF_MAX)
 | 
|---|
| 81 | 
 | 
|---|
| 82 |             /* glibc 2.30 and later malloc refuses to exceed ptrdiff_t
 | 
|---|
| 83 |                bounds even on 32-bit platforms.  We don't know which
 | 
|---|
| 84 |                non-glibc systems are safe.  */
 | 
|---|
| 85 |             #define KNOWN_SAFE (2 < __GLIBC__ + (30 <= __GLIBC_MINOR__))
 | 
|---|
| 86 | 
 | 
|---|
| 87 |             #if WIDE_PTRDIFF || NARROW_SIZE || KNOWN_SAFE
 | 
|---|
| 88 |               return 0;
 | 
|---|
| 89 |             #else
 | 
|---|
| 90 |               #error "malloc might not be ptrdiff_t safe"
 | 
|---|
| 91 |               syntax error
 | 
|---|
| 92 |             #endif
 | 
|---|
| 93 |           ]])],
 | 
|---|
| 94 |        [gl_cv_malloc_ptrdiff=yes],
 | 
|---|
| 95 |        [gl_cv_malloc_ptrdiff=no])
 | 
|---|
| 96 |     ])
 | 
|---|
| 97 | ])
 | 
|---|
| 98 | 
 | 
|---|
| 99 | # gl_FUNC_MALLOC_POSIX
 | 
|---|
| 100 | # --------------------
 | 
|---|
| 101 | # Test whether 'malloc' is POSIX compliant (sets errno to ENOMEM when it
 | 
|---|
| 102 | # fails, and doesn't mess up with ptrdiff_t overflow), and replace
 | 
|---|
| 103 | # malloc if it is not.
 | 
|---|
| 104 | AC_DEFUN([gl_FUNC_MALLOC_POSIX],
 | 
|---|
| 105 | [
 | 
|---|
| 106 |   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
 | 
|---|
| 107 |   AC_REQUIRE([gl_FUNC_MALLOC_PTRDIFF])
 | 
|---|
| 108 |   AC_REQUIRE([gl_CHECK_MALLOC_POSIX])
 | 
|---|
| 109 |   if test "$gl_cv_func_malloc_posix" = yes; then
 | 
|---|
| 110 |     AC_DEFINE([HAVE_MALLOC_POSIX], [1],
 | 
|---|
| 111 |       [Define if malloc, realloc, and calloc set errno on allocation failure.])
 | 
|---|
| 112 |   else
 | 
|---|
| 113 |     REPLACE_MALLOC_FOR_MALLOC_POSIX=1
 | 
|---|
| 114 |   fi
 | 
|---|
| 115 | ])
 | 
|---|
| 116 | 
 | 
|---|
| 117 | # Test whether malloc, realloc, calloc set errno to ENOMEM on failure.
 | 
|---|
| 118 | # Set gl_cv_func_malloc_posix to yes or no accordingly.
 | 
|---|
| 119 | AC_DEFUN([gl_CHECK_MALLOC_POSIX],
 | 
|---|
| 120 | [
 | 
|---|
| 121 |   AC_REQUIRE([AC_CANONICAL_HOST])
 | 
|---|
| 122 |   AC_CACHE_CHECK([whether malloc, realloc, calloc set errno on failure],
 | 
|---|
| 123 |     [gl_cv_func_malloc_posix],
 | 
|---|
| 124 |     [
 | 
|---|
| 125 |       dnl It is too dangerous to try to allocate a large amount of memory:
 | 
|---|
| 126 |       dnl some systems go to their knees when you do that. So assume that
 | 
|---|
| 127 |       dnl all Unix implementations of the function set errno on failure,
 | 
|---|
| 128 |       dnl except on those platforms where we have seen 'test-malloc-gnu',
 | 
|---|
| 129 |       dnl 'test-realloc-gnu', 'test-calloc-gnu' fail.
 | 
|---|
| 130 |       case "$host_os" in
 | 
|---|
| 131 |         mingw*)
 | 
|---|
| 132 |           gl_cv_func_malloc_posix=no ;;
 | 
|---|
| 133 |         irix* | solaris*)
 | 
|---|
| 134 |           dnl On IRIX 6.5, the three functions return NULL with errno unset
 | 
|---|
| 135 |           dnl when the argument is larger than PTRDIFF_MAX.
 | 
|---|
| 136 |           dnl On Solaris 11.3, the three functions return NULL with errno set
 | 
|---|
| 137 |           dnl to EAGAIN, not ENOMEM, when the argument is larger than
 | 
|---|
| 138 |           dnl PTRDIFF_MAX.
 | 
|---|
| 139 |           dnl Here is a test program:
 | 
|---|
| 140 | m4_divert_push([KILL])
 | 
|---|
| 141 | #include <errno.h>
 | 
|---|
| 142 | #include <stdio.h>
 | 
|---|
| 143 | #include <stdlib.h>
 | 
|---|
| 144 | #define ptrdiff_t long
 | 
|---|
| 145 | #ifndef PTRDIFF_MAX
 | 
|---|
| 146 | # define PTRDIFF_MAX ((ptrdiff_t) ((1UL << (8 * sizeof (ptrdiff_t) - 1)) - 1))
 | 
|---|
| 147 | #endif
 | 
|---|
| 148 | 
 | 
|---|
| 149 | int main ()
 | 
|---|
| 150 | {
 | 
|---|
| 151 |   void *p;
 | 
|---|
| 152 | 
 | 
|---|
| 153 |   fprintf (stderr, "PTRDIFF_MAX = %lu\n", (unsigned long) PTRDIFF_MAX);
 | 
|---|
| 154 | 
 | 
|---|
| 155 |   errno = 0;
 | 
|---|
| 156 |   p = malloc ((unsigned long) PTRDIFF_MAX + 1);
 | 
|---|
| 157 |   fprintf (stderr, "p=%p errno=%d\n", p, errno);
 | 
|---|
| 158 | 
 | 
|---|
| 159 |   errno = 0;
 | 
|---|
| 160 |   p = calloc (PTRDIFF_MAX / 2 + 1, 2);
 | 
|---|
| 161 |   fprintf (stderr, "p=%p errno=%d\n", p, errno);
 | 
|---|
| 162 | 
 | 
|---|
| 163 |   errno = 0;
 | 
|---|
| 164 |   p = realloc (NULL, (unsigned long) PTRDIFF_MAX + 1);
 | 
|---|
| 165 |   fprintf (stderr, "p=%p errno=%d\n", p, errno);
 | 
|---|
| 166 | 
 | 
|---|
| 167 |   return 0;
 | 
|---|
| 168 | }
 | 
|---|
| 169 | m4_divert_pop([KILL])
 | 
|---|
| 170 |           gl_cv_func_malloc_posix=no ;;
 | 
|---|
| 171 |         *)
 | 
|---|
| 172 |           gl_cv_func_malloc_posix=yes ;;
 | 
|---|
| 173 |       esac
 | 
|---|
| 174 |     ])
 | 
|---|
| 175 | ])
 | 
|---|