1# strstr.m4 serial 24
2dnl Copyright (C) 2008-2022 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_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 __GNU_LIBRARY__, 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#include <string.h> /* for __GNU_LIBRARY__ */
44#ifdef __GNU_LIBRARY__
45 #include <features.h>
46 #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ > 12) || (__GLIBC__ > 2)) \
47     || defined __UCLIBC__
48  Lucky user
49 #endif
50#elif defined __CYGWIN__
51 #include <cygwin/version.h>
52 #if CYGWIN_VERSION_DLL_COMBINED > CYGWIN_VERSION_DLL_MAKE_COMBINED (1007, 7)
53  Lucky user
54 #endif
55#else
56  Lucky user
57#endif
58            ],
59            [gl_cv_func_strstr_works_always="guessing yes"],
60            [gl_cv_func_strstr_works_always="$gl_cross_guess_normal"])
61         ])
62      ])
63    case "$gl_cv_func_strstr_works_always" in
64      *yes) ;;
65      *)
66        REPLACE_STRSTR=1
67        ;;
68    esac
69  fi
70]) # gl_FUNC_STRSTR_SIMPLE
71
72dnl Additionally, check that strstr is efficient.
73AC_DEFUN([gl_FUNC_STRSTR],
74[
75  AC_REQUIRE([gl_FUNC_STRSTR_SIMPLE])
76  if test $REPLACE_STRSTR = 0; then
77    AC_CACHE_CHECK([whether strstr works in linear time],
78      [gl_cv_func_strstr_linear],
79      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
80#ifdef __MVS__
81/* z/OS does not deliver signals while strstr() is running (thanks to
82   restrictions on its LE runtime), which prevents us from limiting the
83   running time of this test.  */
84# error "This test does not work properly on z/OS"
85#endif
86#include <signal.h> /* for signal */
87#include <string.h> /* for strstr */
88#include <stdlib.h> /* for malloc */
89#include <unistd.h> /* for alarm */
90static void quit (int sig) { _exit (sig + 128); }
91]], [[
92    int result = 0;
93    size_t m = 1000000;
94    char *haystack = (char *) malloc (2 * m + 2);
95    char *needle = (char *) malloc (m + 2);
96    /* Failure to compile this test due to missing alarm is okay,
97       since all such platforms (mingw) also have quadratic strstr.  */
98    signal (SIGALRM, quit);
99    alarm (5);
100    /* Check for quadratic performance.  */
101    if (haystack && needle)
102      {
103        memset (haystack, 'A', 2 * m);
104        haystack[2 * m] = 'B';
105        haystack[2 * m + 1] = 0;
106        memset (needle, 'A', m);
107        needle[m] = 'B';
108        needle[m + 1] = 0;
109        if (!strstr (haystack, needle))
110          result |= 1;
111      }
112    /* Free allocated memory, in case some sanitizer is watching.  */
113    free (haystack);
114    free (needle);
115    return result;
116    ]])],
117        [gl_cv_func_strstr_linear=yes], [gl_cv_func_strstr_linear=no],
118        [dnl Only glibc > 2.12 on processors without SSE 4.2 instructions and
119         dnl cygwin > 1.7.7 are known to have a bug-free strstr that works in
120         dnl linear time.
121         AC_EGREP_CPP([Lucky user],
122           [
123#include <features.h>
124#ifdef __GNU_LIBRARY__
125 #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ > 12) || (__GLIBC__ > 2)) \
126     && !(defined __i386__ || defined __x86_64__) \
127     && !defined __UCLIBC__
128  Lucky user
129 #endif
130#endif
131#ifdef __CYGWIN__
132 #include <cygwin/version.h>
133 #if CYGWIN_VERSION_DLL_COMBINED > CYGWIN_VERSION_DLL_MAKE_COMBINED (1007, 7)
134  Lucky user
135 #endif
136#endif
137           ],
138           [gl_cv_func_strstr_linear="guessing yes"],
139           [gl_cv_func_strstr_linear="$gl_cross_guess_normal"])
140        ])
141      ])
142    case "$gl_cv_func_strstr_linear" in
143      *yes) ;;
144      *)
145        REPLACE_STRSTR=1
146        ;;
147    esac
148  fi
149]) # gl_FUNC_STRSTR
150