immutable: Add tests.
[gnulib.git] / m4 / strncat.m4
blobeaf456cb15baa363ddb0dc87e5f81f88bc61384c
1 # strncat.m4 serial 5
2 dnl Copyright (C) 2002-2004, 2009-2021 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.
7 AC_DEFUN_ONCE([gl_FUNC_STRNCAT],
9   AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
10   AC_REQUIRE([AC_PROG_CC])
11   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
13   dnl Check for prerequisites for memory fence checks.
14   gl_FUNC_MMAP_ANON
15   AC_CHECK_HEADERS_ONCE([sys/mman.h])
16   AC_CHECK_FUNCS_ONCE([mprotect])
18   dnl Detect bug in Solaris 8..10 on SPARC and Solaris 11.0 on x86:
19   dnl strncat should not dereference more than n bytes, but always dereferences
20   dnl n+1 bytes if the first n bytes don't contain a NUL byte.
21   dnl Assume that strncat works on platforms that lack mprotect.
22   AC_CACHE_CHECK([whether strncat works], [gl_cv_func_strncat_works],
23     [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
24 #include <string.h>
25 #if HAVE_SYS_MMAN_H
26 # include <fcntl.h>
27 # include <unistd.h>
28 # include <sys/types.h>
29 # include <sys/mman.h>
30 # ifndef MAP_FILE
31 #  define MAP_FILE 0
32 # endif
33 #endif
34 ]GL_MDA_DEFINES],
36   char *fence = NULL;
37 #if HAVE_SYS_MMAN_H && HAVE_MPROTECT
38 # if HAVE_MAP_ANONYMOUS
39   const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
40   const int fd = -1;
41 # else /* !HAVE_MAP_ANONYMOUS */
42   const int flags = MAP_FILE | MAP_PRIVATE;
43   int fd = open ("/dev/zero", O_RDONLY, 0666);
44   if (fd >= 0)
45 # endif
46     {
47       int pagesize = getpagesize ();
48       char *two_pages =
49         (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
50                        flags, fd, 0);
51       if (two_pages != (char *)(-1)
52           && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
53         fence = two_pages + pagesize;
54     }
55 #endif
56   if (fence)
57     {
58       char dest[8];
60       dest[0] = '*';
61       dest[1] = 'a';
62       dest[2] = '\0';
63       dest[3] = 'w';
64       dest[4] = 'x';
65       dest[5] = 'y';
66       dest[6] = 'z';
68       *(fence - 3) = '7';
69       *(fence - 2) = '2';
70       *(fence - 1) = '9';
72       if (strncat (dest + 1, fence - 3, 3) != dest + 1)
73         return 1;
74       if (dest[0] != '*')
75         return 2;
76       if (dest[1] != 'a'
77           || dest[2] != '7' || dest[3] != '2' || dest[4] != '9'
78           || dest[5] != '\0')
79         return 3;
80       if (dest[6] != 'z')
81         return 4;
82     }
83   return 0;
84 ]])], [gl_cv_func_strncat_works=yes], [gl_cv_func_strncat_works=no],
85        [
86         case "$host_os" in
87                     # Guess no on Solaris.
88           solaris*) gl_cv_func_strncat_works="guessing no" ;;
89                     # Guess yes on native Windows.
90           mingw*)   gl_cv_func_strncat_works="guessing yes" ;;
91                     # Guess yes otherwise.
92           *)        gl_cv_func_strncat_works="guessing yes" ;;
93         esac
94        ])
95     ])
96   case "$gl_cv_func_strncat_works" in
97     *yes) ;;
98     *) REPLACE_STRNCAT=1 ;;
99   esac
102 # Prerequisites of lib/strncat.c.
103 AC_DEFUN([gl_PREREQ_STRNCAT], [
104   :