1# strstr.m4 serial 22
2dnl Copyright (C) 2008-2020 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
7dnl Check that strstr works.
8AC_DEFUN([gl_FUNC_STRSTR_SIMPLE],
9[
10  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
11  AC_REQUIRE([gl_FUNC_MEMCHR])
12  if test $REPLACE_MEMCHR = 1; then
13    REPLACE_STRSTR=1
14  else
15    dnl Detect https://sourceware.org/bugzilla/show_bug.cgi?id=12092
16    dnl and https://sourceware.org/bugzilla/show_bug.cgi?id=23637.
17    AC_CACHE_CHECK([whether strstr works],
18      [gl_cv_func_strstr_works_always],
19      [AC_RUN_IFELSE(
20         [AC_LANG_PROGRAM([[
21#include <string.h> /* for strstr */
22#ifdef __GNU_LIBRARY__
23 #include <features.h>
24 #if __GLIBC__ == 2 && __GLIBC_MINOR__ == 28
25  Unlucky user
26 #endif
27#endif
28#define P "_EF_BF_BD"
29#define HAYSTACK "F_BD_CE_BD" P P P P "_C3_88_20" P P P "_C3_A7_20" P
30#define NEEDLE P P P P P
31]],
32            [[return !!strstr (HAYSTACK, NEEDLE);
33            ]])],
34         [gl_cv_func_strstr_works_always=yes],
35         [gl_cv_func_strstr_works_always=no],
36         [dnl glibc 2.12 and cygwin 1.7.7 have a known bug.  uClibc is not
37          dnl affected, since it uses different source code for strstr than
38          dnl glibc.
39          dnl Assume that it works on all other platforms, even if it is not
40          dnl linear.
41          AC_EGREP_CPP([Lucky user],
42            [
43#ifdef __GNU_LIBRARY__
44 #include <features.h>
45 #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ > 12) || (__GLIBC__ > 2)) \
46     || defined __UCLIBC__
47  Lucky user
48 #endif
49#elif defined __CYGWIN__
50 #include <cygwin/version.h>
51 #if CYGWIN_VERSION_DLL_COMBINED > CYGWIN_VERSION_DLL_MAKE_COMBINED (1007, 7)
52  Lucky user
53 #endif
54#else
55  Lucky user
56#endif
57            ],
58            [gl_cv_func_strstr_works_always="guessing yes"],
59            [gl_cv_func_strstr_works_always="$gl_cross_guess_normal"])
60         ])
61      ])
62    case "$gl_cv_func_strstr_works_always" in
63      *yes) ;;
64      *)
65        REPLACE_STRSTR=1
66        ;;
67    esac
68  fi
69]) # gl_FUNC_STRSTR_SIMPLE
70
71dnl Additionally, check that strstr is efficient.
72AC_DEFUN([gl_FUNC_STRSTR],
73[
74  AC_REQUIRE([gl_FUNC_STRSTR_SIMPLE])
75  if test $REPLACE_STRSTR = 0; then
76    AC_CACHE_CHECK([whether strstr works in linear time],
77      [gl_cv_func_strstr_linear],
78      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
79#ifdef __MVS__
80/* z/OS does not deliver signals while strstr() is running (thanks to
81   restrictions on its LE runtime), which prevents us from limiting the
82   running time of this test.  */
83# error "This test does not work properly on z/OS"
84#endif
85#include <signal.h> /* for signal */
86#include <string.h> /* for strstr */
87#include <stdlib.h> /* for malloc */
88#include <unistd.h> /* for alarm */
89static void quit (int sig) { _exit (sig + 128); }
90]], [[
91    int result = 0;
92    size_t m = 1000000;
93    char *haystack = (char *) malloc (2 * m + 2);
94    char *needle = (char *) malloc (m + 2);
95    /* Failure to compile this test due to missing alarm is okay,
96       since all such platforms (mingw) also have quadratic strstr.  */
97    signal (SIGALRM, quit);
98    alarm (5);
99    /* Check for quadratic performance.  */
100    if (haystack && needle)
101      {
102        memset (haystack, 'A', 2 * m);
103        haystack[2 * m] = 'B';
104        haystack[2 * m + 1] = 0;
105        memset (needle, 'A', m);
106        needle[m] = 'B';
107        needle[m + 1] = 0;
108        if (!strstr (haystack, needle))
109          result |= 1;
110      }
111    /* Free allocated memory, in case some sanitizer is watching.  */
112    free (haystack);
113    free (needle);
114    return result;
115    ]])],
116        [gl_cv_func_strstr_linear=yes], [gl_cv_func_strstr_linear=no],
117        [dnl Only glibc > 2.12 on processors without SSE 4.2 instructions and
118         dnl cygwin > 1.7.7 are known to have a bug-free strstr that works in
119         dnl linear time.
120         AC_EGREP_CPP([Lucky user],
121           [
122#include <features.h>
123#ifdef __GNU_LIBRARY__
124 #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ > 12) || (__GLIBC__ > 2)) \
125     && !(defined __i386__ || defined __x86_64__) \
126     && !defined __UCLIBC__
127  Lucky user
128 #endif
129#endif
130#ifdef __CYGWIN__
131 #include <cygwin/version.h>
132 #if CYGWIN_VERSION_DLL_COMBINED > CYGWIN_VERSION_DLL_MAKE_COMBINED (1007, 7)
133  Lucky user
134 #endif
135#endif
136           ],
137           [gl_cv_func_strstr_linear="guessing yes"],
138           [gl_cv_func_strstr_linear="$gl_cross_guess_normal"])
139        ])
140      ])
141    case "$gl_cv_func_strstr_linear" in
142      *yes) ;;
143      *)
144        REPLACE_STRSTR=1
145        ;;
146    esac
147  fi
148]) # gl_FUNC_STRSTR
149