Imported Upstream version 3.8
[platform/upstream/diffutils.git] / m4 / sigaltstack.m4
1 # sigaltstack.m4 serial 15
2 dnl Copyright (C) 2002-2021 Free Software Foundation, Inc.
3 dnl This file is free software, distributed under the terms of the GNU
4 dnl General Public License.  As a special exception to the GNU General
5 dnl Public License, this file may be distributed as part of a program
6 dnl that contains a configuration script generated by Autoconf, under
7 dnl the same distribution terms as the rest of that program.
8
9 dnl Written by Bruno Haible and Eric Blake.
10
11 AC_DEFUN([SV_SIGALTSTACK],
12 [
13   AC_REQUIRE([AC_PROG_CC])
14   AC_REQUIRE([AC_CANONICAL_HOST])
15
16   AC_CHECK_FUNCS_ONCE([sigaltstack setrlimit])
17
18   if test "$ac_cv_func_sigaltstack" = yes; then
19     AC_CHECK_TYPE([stack_t], ,
20       [AC_DEFINE(stack_t, [struct sigaltstack],
21          [Define to 'struct sigaltstack' if that's the type of the argument to sigaltstack])
22       ],
23       [
24 #include <signal.h>
25 #if HAVE_SYS_SIGNAL_H
26 # include <sys/signal.h>
27 #endif
28       ])
29   fi
30
31   AC_CACHE_CHECK([for working sigaltstack], [sv_cv_sigaltstack], [
32     if test "$ac_cv_func_sigaltstack" = yes; then
33       case "$host_os" in
34         macos* | darwin[[6-9]]* | darwin[[1-9]][[0-9]]*)
35           # On MacOS X 10.2 or newer, just assume that if it compiles, it will
36           # work. If we were to perform the real test, 1 Crash Report dialog
37           # window would pop up.
38           AC_LINK_IFELSE([
39             AC_LANG_PROGRAM([[#include <signal.h>]],
40               [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
41             [sv_cv_sigaltstack="guessing yes"],
42             [sv_cv_sigaltstack=no])
43           ;;
44         *)
45           AC_RUN_IFELSE([
46             AC_LANG_SOURCE([[
47 #include <stdlib.h>
48 #include <signal.h>
49 #if HAVE_SYS_SIGNAL_H
50 # include <sys/signal.h>
51 #endif
52 #if HAVE_SETRLIMIT
53 # include <sys/types.h>
54 # include <sys/time.h>
55 # include <sys/resource.h>
56 #endif
57 void stackoverflow_handler (int sig)
58 {
59   /* If we get here, the stack overflow was caught.  */
60   exit (0);
61 }
62 volatile int * recurse_1 (volatile int n, volatile int *p)
63 {
64   if (n >= 0)
65     *recurse_1 (n + 1, p) += n;
66   return p;
67 }
68 int recurse (volatile int n)
69 {
70   int sum = 0;
71   return *recurse_1 (n, &sum);
72 }
73 char mystack[2 * (1 << 24)];
74 int main ()
75 {
76   stack_t altstack;
77   struct sigaction action;
78 #if defined HAVE_SETRLIMIT && defined RLIMIT_STACK
79   /* Before starting the endless recursion, try to be friendly to the user's
80      machine.  On some Linux 2.2.x systems, there is no stack limit for user
81      processes at all.  We don't want to kill such systems.  */
82   struct rlimit rl;
83   rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
84   setrlimit (RLIMIT_STACK, &rl);
85 #endif
86   /* Install the alternate stack.  Use the midpoint of mystack, to guard
87      against a buggy interpretation of ss_sp on IRIX.  */
88 #ifdef SIGSTKSZ
89   if (sizeof mystack / 2 < SIGSTKSZ)
90     exit (3);
91 #endif
92   altstack.ss_sp = mystack + sizeof mystack / 2;
93   altstack.ss_size = sizeof mystack / 2;
94   altstack.ss_flags = 0; /* no SS_DISABLE */
95   if (sigaltstack (&altstack, NULL) < 0)
96     exit (1);
97   /* Install the SIGSEGV handler.  */
98   sigemptyset (&action.sa_mask);
99   action.sa_handler = &stackoverflow_handler;
100   action.sa_flags = SA_ONSTACK;
101   sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
102   sigaction (SIGBUS, &action, (struct sigaction *) NULL);
103   /* Provoke a stack overflow.  */
104   recurse (0);
105   exit (2);
106 }]])],
107             [sv_cv_sigaltstack=yes],
108             [sv_cv_sigaltstack=no],
109             [
110               dnl FIXME: Put in some more known values here.
111               case "$host_os" in
112                 *)
113                   AC_LINK_IFELSE([
114                     AC_LANG_PROGRAM([[#include <signal.h>]],
115                       [[int x = SA_ONSTACK; stack_t ss; sigaltstack ((stack_t*)0, &ss);]])],
116                     [sv_cv_sigaltstack="guessing yes"],
117                     [sv_cv_sigaltstack=no])
118                   ;;
119               esac
120             ])
121           ;;
122       esac
123     else
124       sv_cv_sigaltstack=no
125     fi
126   ])
127   if test "$sv_cv_sigaltstack" != no; then
128     AC_DEFINE([HAVE_WORKING_SIGALTSTACK], [1],
129       [Define if you have the sigaltstack() function and it works.])
130
131     dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
132     dnl of the memory block designated as an alternate stack. But IRIX 5.3
133     dnl interprets it as the highest address!
134     AC_CACHE_CHECK([for correct stack_t interpretation],
135       [sv_cv_sigaltstack_low_base], [
136       AC_RUN_IFELSE([
137         AC_LANG_SOURCE([[
138 #include <stdlib.h>
139 #include <signal.h>
140 #if HAVE_SYS_SIGNAL_H
141 # include <sys/signal.h>
142 #endif
143 volatile char *stack_lower_bound;
144 volatile char *stack_upper_bound;
145 static void check_stack_location (volatile char *addr)
146 {
147   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
148     exit (0);
149   else
150     exit (1);
151 }
152 static void stackoverflow_handler (int sig)
153 {
154   char dummy;
155   check_stack_location (&dummy);
156 }
157 char mystack[2 * (1 << 24)];
158 int main ()
159 {
160   stack_t altstack;
161   struct sigaction action;
162   /* Install the alternate stack.  */
163   altstack.ss_sp = mystack + sizeof mystack / 2;
164   altstack.ss_size = sizeof mystack / 2;
165   stack_lower_bound = (char *) altstack.ss_sp;
166   stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
167   altstack.ss_flags = 0; /* no SS_DISABLE */
168   if (sigaltstack (&altstack, NULL) < 0)
169     exit (2);
170   /* Install the SIGSEGV handler.  */
171   sigemptyset (&action.sa_mask);
172   action.sa_handler = &stackoverflow_handler;
173   action.sa_flags = SA_ONSTACK;
174   if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
175     exit(3);
176   /* Provoke a SIGSEGV.  */
177   raise (SIGSEGV);
178   exit (3);
179 }]])],
180       [sv_cv_sigaltstack_low_base=yes],
181       [sv_cv_sigaltstack_low_base=no],
182       [
183         dnl FIXME: Put in some more known values here.
184         case "$host_os" in
185           irix5*) sv_cv_sigaltstack_low_base="no" ;;
186           *)      sv_cv_sigaltstack_low_base="guessing yes" ;;
187         esac
188       ])
189     ])
190     if test "$sv_cv_sigaltstack_low_base" = no; then
191       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
192         [Define if sigaltstack() interprets the stack_t.ss_sp field incorrectly,
193          as the highest address of the alternate stack range rather than as the
194          lowest address.])
195     fi
196   fi
197 ])