1# strncat.m4 serial 4
2dnl Copyright (C) 2002-2004, 2009-2018 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN_ONCE([gl_FUNC_STRNCAT],
8[
9  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
10  AC_REQUIRE([AC_PROG_CC])
11  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
12
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])
17
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]], [[
35  char *fence = NULL;
36#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
37# if HAVE_MAP_ANONYMOUS
38  const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
39  const int fd = -1;
40# else /* !HAVE_MAP_ANONYMOUS */
41  const int flags = MAP_FILE | MAP_PRIVATE;
42  int fd = open ("/dev/zero", O_RDONLY, 0666);
43  if (fd >= 0)
44# endif
45    {
46      int pagesize = getpagesize ();
47      char *two_pages =
48        (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
49                       flags, fd, 0);
50      if (two_pages != (char *)(-1)
51          && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
52        fence = two_pages + pagesize;
53    }
54#endif
55  if (fence)
56    {
57      char dest[8];
58
59      dest[0] = '*';
60      dest[1] = 'a';
61      dest[2] = '\0';
62      dest[3] = 'w';
63      dest[4] = 'x';
64      dest[5] = 'y';
65      dest[6] = 'z';
66
67      *(fence - 3) = '7';
68      *(fence - 2) = '2';
69      *(fence - 1) = '9';
70
71      if (strncat (dest + 1, fence - 3, 3) != dest + 1)
72        return 1;
73      if (dest[0] != '*')
74        return 2;
75      if (dest[1] != 'a'
76          || dest[2] != '7' || dest[3] != '2' || dest[4] != '9'
77          || dest[5] != '\0')
78        return 3;
79      if (dest[6] != 'z')
80        return 4;
81    }
82  return 0;
83]])], [gl_cv_func_strncat_works=yes], [gl_cv_func_strncat_works=no],
84       [
85        case "$host_os" in
86                    # Guess no on Solaris.
87          solaris*) gl_cv_func_strncat_works="guessing no" ;;
88                    # Guess yes on native Windows.
89          mingw*)   gl_cv_func_strncat_works="guessing yes" ;;
90                    # Guess yes otherwise.
91          *)        gl_cv_func_strncat_works="guessing yes" ;;
92        esac
93       ])
94    ])
95  case "$gl_cv_func_strncat_works" in
96    *yes) ;;
97    *) REPLACE_STRNCAT=1 ;;
98  esac
99])
100
101# Prerequisites of lib/strncat.c.
102AC_DEFUN([gl_PREREQ_STRNCAT], [
103  :
104])
105