update nearly all FSF copyright year lists to include 2010
[gnulib.git] / m4 / c-stack.m4
1 # Check prerequisites for compiling lib/c-stack.c.
2
3 # Copyright (C) 2002, 2003, 2004, 2008, 2009, 2010 Free Software Foundation,
4 # Inc.
5 # This file is free software; the Free Software Foundation
6 # gives unlimited permission to copy and/or distribute it,
7 # with or without modifications, as long as this notice is preserved.
8
9 # Written by Paul Eggert.
10
11 # serial 10
12
13 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
14   [# for STACK_DIRECTION
15    AC_REQUIRE([AC_FUNC_ALLOCA])
16    AC_REQUIRE([AC_CANONICAL_HOST])
17    AC_CHECK_FUNCS_ONCE([setrlimit])
18    AC_CHECK_HEADERS_ONCE([ucontext.h])
19
20    dnl List of signals that are sent when an invalid virtual memory address
21    dnl is accessed, or when the stack overflows.
22    dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }.
23    case "$host_os" in
24      sunos4* | freebsd* | dragonfly* | openbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
25        FAULT_YIELDS_SIGBUS=1 ;;
26      hpux*) # HP-UX
27        FAULT_YIELDS_SIGBUS=1 ;;
28      macos* | darwin*) # MacOS X
29        FAULT_YIELDS_SIGBUS=1 ;;
30      gnu*) # Hurd
31        FAULT_YIELDS_SIGBUS=1 ;;
32      *)
33        FAULT_YIELDS_SIGBUS=0 ;;
34    esac
35    AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS],
36      [Define to 1 if an invalid memory address access may yield a SIGBUS.])
37
38    AC_CACHE_CHECK([for working C stack overflow detection],
39      [ac_cv_sys_stack_overflow_works],
40      [AC_RUN_IFELSE([AC_LANG_SOURCE(
41            [[
42             #include <unistd.h>
43             #include <signal.h>
44             #if HAVE_SETRLIMIT
45             # include <sys/types.h>
46             # include <sys/time.h>
47             # include <sys/resource.h>
48             #endif
49             #ifndef SIGSTKSZ
50             # define SIGSTKSZ 16384
51             #endif
52
53             static union
54             {
55               char buffer[2 * SIGSTKSZ];
56               long double ld;
57               long u;
58               void *p;
59             } alternate_signal_stack;
60
61             static void
62             segv_handler (int signo)
63             {
64               _exit (0);
65             }
66
67             static int
68             c_stack_action ()
69             {
70               stack_t st;
71               struct sigaction act;
72               int r;
73
74               st.ss_flags = 0;
75               /* Use the midpoint to avoid Irix sigaltstack bug.  */
76               st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
77               st.ss_size = SIGSTKSZ;
78               r = sigaltstack (&st, 0);
79               if (r != 0)
80                 return r;
81
82               sigemptyset (&act.sa_mask);
83               act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
84               act.sa_handler = segv_handler;
85               #if FAULT_YIELDS_SIGBUS
86               if (sigaction (SIGBUS, &act, 0) < 0)
87                 return -1;
88               #endif
89               return sigaction (SIGSEGV, &act, 0);
90             }
91             static volatile int *
92             recurse_1 (volatile int n, volatile int *p)
93             {
94               if (n >= 0)
95                 *recurse_1 (n + 1, p) += n;
96               return p;
97             }
98             static int
99             recurse (volatile int n)
100             {
101               int sum = 0;
102               return *recurse_1 (n, &sum);
103             }
104             int
105             main ()
106             {
107               #if HAVE_SETRLIMIT && defined RLIMIT_STACK
108               /* Before starting the endless recursion, try to be friendly
109                  to the user's machine.  On some Linux 2.2.x systems, there
110                  is no stack limit for user processes at all.  We don't want
111                  to kill such systems.  */
112               struct rlimit rl;
113               rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
114               setrlimit (RLIMIT_STACK, &rl);
115               #endif
116
117               return c_stack_action () || recurse (0);
118             }
119            ]])],
120         [ac_cv_sys_stack_overflow_works=yes],
121         [ac_cv_sys_stack_overflow_works=no],
122         [ac_cv_sys_stack_overflow_works=cross-compiling])])
123
124   if test $ac_cv_sys_stack_overflow_works = yes; then
125    AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
126      [Define to 1 if extending the stack slightly past the limit causes
127       a SIGSEGV which can be handled on an alternate stack established
128       with sigaltstack.])
129
130     dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
131     dnl of the memory block designated as an alternate stack. But IRIX 5.3
132     dnl interprets it as the highest address!
133     AC_CACHE_CHECK([for correct stack_t interpretation],
134       [gl_cv_sigaltstack_low_base], [
135       AC_RUN_IFELSE([
136         AC_LANG_SOURCE([[
137 #include <stdlib.h>
138 #include <signal.h>
139 #if HAVE_SYS_SIGNAL_H
140 # include <sys/signal.h>
141 #endif
142 #ifndef SIGSTKSZ
143 # define SIGSTKSZ 16384
144 #endif
145 volatile char *stack_lower_bound;
146 volatile char *stack_upper_bound;
147 static void check_stack_location (volatile char *addr)
148 {
149   if (addr >= stack_lower_bound && addr <= stack_upper_bound)
150     exit (0);
151   else
152     exit (1);
153 }
154 static void stackoverflow_handler (int sig)
155 {
156   char dummy;
157   check_stack_location (&dummy);
158 }
159 int main ()
160 {
161   char mystack[2 * SIGSTKSZ];
162   stack_t altstack;
163   struct sigaction action;
164   /* Install the alternate stack.  */
165   altstack.ss_sp = mystack + SIGSTKSZ;
166   altstack.ss_size = SIGSTKSZ;
167   stack_lower_bound = (char *) altstack.ss_sp;
168   stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
169   altstack.ss_flags = 0; /* no SS_DISABLE */
170   if (sigaltstack (&altstack, NULL) < 0)
171     exit (2);
172   /* Install the SIGSEGV handler.  */
173   sigemptyset (&action.sa_mask);
174   action.sa_handler = &stackoverflow_handler;
175   action.sa_flags = SA_ONSTACK;
176   if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
177     exit(3);
178   /* Provoke a SIGSEGV.  */
179   raise (SIGSEGV);
180   exit (3);
181 }]])],
182       [gl_cv_sigaltstack_low_base=yes],
183       [gl_cv_sigaltstack_low_base=no],
184       [gl_cv_sigaltstack_low_base=cross-compiling])])
185    if test "$gl_cv_sigaltstack_low_base" = no; then
186       AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
187         [Define if sigaltstack() interprets the stack_t.ss_sp field
188          incorrectly, as the highest address of the alternate stack range
189          rather than as the lowest address.])
190     fi
191
192    AC_CACHE_CHECK([for precise C stack overflow detection],
193      ac_cv_sys_xsi_stack_overflow_heuristic,
194      [AC_RUN_IFELSE([AC_LANG_SOURCE(
195            [[
196             #include <unistd.h>
197             #include <signal.h>
198             #if HAVE_UCONTEXT_H
199             # include <ucontext.h>
200             #endif
201             #if HAVE_SETRLIMIT
202             # include <sys/types.h>
203             # include <sys/time.h>
204             # include <sys/resource.h>
205             #endif
206             #ifndef SIGSTKSZ
207             # define SIGSTKSZ 16384
208             #endif
209
210             static union
211             {
212               char buffer[2 * SIGSTKSZ];
213               long double ld;
214               long u;
215               void *p;
216             } alternate_signal_stack;
217
218             #if STACK_DIRECTION
219             # define find_stack_direction(ptr) STACK_DIRECTION
220             #else
221             static int
222             find_stack_direction (char const *addr)
223             {
224               char dummy;
225               return (! addr ? find_stack_direction (&dummy)
226                       : addr < &dummy ? 1 : -1);
227             }
228             #endif
229
230             static void
231             segv_handler (int signo, siginfo_t *info, void *context)
232             {
233               if (0 < info->si_code)
234                 {
235                   /* For XSI heuristics to work, we need uc_stack to describe
236                      the interrupted stack (as on Solaris), and not the
237                      currently executing stack (as on Linux).  */
238                   ucontext_t const *user_context = context;
239                   char const *stack_min = user_context->uc_stack.ss_sp;
240                   size_t stack_size = user_context->uc_stack.ss_size;
241                   char const *faulting_address = info->si_addr;
242                   size_t s = faulting_address - stack_min;
243                   size_t page_size = sysconf (_SC_PAGESIZE);
244                   if (find_stack_direction (0) < 0)
245                     s += page_size;
246                   if (s < stack_size + page_size)
247                     _exit (0);
248                 }
249
250               _exit (1);
251             }
252
253             static int
254             c_stack_action ()
255             {
256               stack_t st;
257               struct sigaction act;
258               int r;
259
260               st.ss_flags = 0;
261               /* Use the midpoint to avoid Irix sigaltstack bug.  */
262               st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
263               st.ss_size = SIGSTKSZ;
264               r = sigaltstack (&st, 0);
265               if (r != 0)
266                 return r;
267
268               sigemptyset (&act.sa_mask);
269               act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
270               act.sa_sigaction = segv_handler;
271               #if FAULT_YIELDS_SIGBUS
272               if (sigaction (SIGBUS, &act, 0) < 0)
273                 return -1;
274               #endif
275               return sigaction (SIGSEGV, &act, 0);
276             }
277             static volatile int *
278             recurse_1 (volatile int n, volatile int *p)
279             {
280               if (n >= 0)
281                 *recurse_1 (n + 1, p) += n;
282               return p;
283             }
284             static int
285             recurse (volatile int n)
286             {
287               int sum = 0;
288               return *recurse_1 (n, &sum);
289             }
290             int
291             main ()
292             {
293               #if HAVE_SETRLIMIT && defined RLIMIT_STACK
294               /* Before starting the endless recursion, try to be friendly
295                  to the user's machine.  On some Linux 2.2.x systems, there
296                  is no stack limit for user processes at all.  We don't want
297                  to kill such systems.  */
298               struct rlimit rl;
299               rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
300               setrlimit (RLIMIT_STACK, &rl);
301               #endif
302
303               return c_stack_action () || recurse (0);
304             }
305            ]])],
306         [ac_cv_sys_xsi_stack_overflow_heuristic=yes],
307         [ac_cv_sys_xsi_stack_overflow_heuristic=no],
308         [ac_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])])
309
310    if test $ac_cv_sys_xsi_stack_overflow_heuristic = yes; then
311      AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
312        [Define to 1 if extending the stack slightly past the limit causes
313         a SIGSEGV, and an alternate stack can be established with sigaltstack,
314         and the signal handler is passed a context that specifies the
315         run time stack.  This behavior is defined by POSIX 1003.1-2001
316         with the X/Open System Interface (XSI) option
317         and is a standardized way to implement a SEGV-based stack
318         overflow detection heuristic.])
319    fi
320   fi])
321
322
323 AC_DEFUN([gl_PREREQ_C_STACK],
324   [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
325    AC_REQUIRE([gl_LIBSIGSEGV])
326
327    # for STACK_DIRECTION
328    AC_REQUIRE([AC_FUNC_ALLOCA])
329
330    AC_CHECK_FUNCS_ONCE([sigaltstack])
331    AC_CHECK_DECLS([sigaltstack], , , [#include <signal.h>])
332
333    AC_CHECK_HEADERS_ONCE([unistd.h ucontext.h])
334
335    AC_CHECK_TYPES([stack_t], , , [#include <signal.h>])
336
337    dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
338    if test "$gl_cv_lib_sigsegv" = yes \
339        && test $"ac_cv_sys_xsi_stack_overflow_heuristic" != yes ; then
340      AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
341      AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
342    fi
343 ])
344
345 AC_DEFUN([gl_C_STACK],
346 [
347   dnl Prerequisites of lib/c-stack.c.
348   gl_PREREQ_C_STACK
349 ])