1 # Check prerequisites for compiling lib/c-stack.c.
3 # Copyright (C) 2002-2004, 2008-2020 Free Software Foundation, Inc.
4 # This file is free software; the Free Software Foundation
5 # gives unlimited permission to copy and/or distribute it,
6 # with or without modifications, as long as this notice is preserved.
8 # Written by Paul Eggert.
12 AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC],
14 AC_REQUIRE([AC_CANONICAL_HOST])
15 AC_CHECK_FUNCS_ONCE([setrlimit])
16 AC_CHECK_HEADERS_ONCE([ucontext.h])
18 dnl List of signals that are sent when an invalid virtual memory address
19 dnl is accessed, or when the stack overflows.
20 dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }.
22 sunos4* | freebsd* | dragonfly* | openbsd* | mirbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems
23 FAULT_YIELDS_SIGBUS=1 ;;
25 FAULT_YIELDS_SIGBUS=1 ;;
26 macos* | darwin*) # Mac OS X
27 FAULT_YIELDS_SIGBUS=1 ;;
29 FAULT_YIELDS_SIGBUS=1 ;;
31 FAULT_YIELDS_SIGBUS=0 ;;
33 AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS],
34 [Define to 1 if an invalid memory address access may yield a SIGBUS.])
36 AC_CACHE_CHECK([for working C stack overflow detection],
37 [gl_cv_sys_stack_overflow_works],
38 [AC_RUN_IFELSE([AC_LANG_SOURCE(
43 # include <sys/types.h>
44 # include <sys/time.h>
45 # include <sys/resource.h>
48 # define SIGSTKSZ 16384
53 char buffer[2 * SIGSTKSZ];
57 } alternate_signal_stack;
60 segv_handler (int signo)
73 /* Use the midpoint to avoid Irix sigaltstack bug. */
74 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
75 st.ss_size = SIGSTKSZ;
76 r = sigaltstack (&st, 0);
80 sigemptyset (&act.sa_mask);
81 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
82 act.sa_handler = segv_handler;
83 #if FAULT_YIELDS_SIGBUS
84 if (sigaction (SIGBUS, &act, 0) < 0)
87 if (sigaction (SIGSEGV, &act, 0) < 0)
92 recurse_1 (volatile int n, volatile int *p)
95 *recurse_1 (n + 1, p) += n;
99 recurse (volatile int n)
102 return *recurse_1 (n, &sum);
108 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
109 /* Before starting the endless recursion, try to be friendly
110 to the user's machine. On some Linux 2.2.x systems, there
111 is no stack limit for user processes at all. We don't want
112 to kill such systems. */
114 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
115 setrlimit (RLIMIT_STACK, &rl);
118 result = c_stack_action ();
124 [gl_cv_sys_stack_overflow_works=yes],
125 [gl_cv_sys_stack_overflow_works=no],
127 # Guess no on native Windows.
128 mingw*) gl_cv_sys_stack_overflow_works="guessing no" ;;
129 *) gl_cv_sys_stack_overflow_works=cross-compiling ;;
134 if test "$gl_cv_sys_stack_overflow_works" = yes; then
135 AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1],
136 [Define to 1 if extending the stack slightly past the limit causes
137 a SIGSEGV which can be handled on an alternate stack established
140 dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address
141 dnl of the memory block designated as an alternate stack. But IRIX 5.3
142 dnl interprets it as the highest address!
143 AC_CACHE_CHECK([for correct stack_t interpretation],
144 [gl_cv_sigaltstack_low_base], [
149 #if HAVE_SYS_SIGNAL_H
150 # include <sys/signal.h>
153 # define SIGSTKSZ 16384
155 volatile char *stack_lower_bound;
156 volatile char *stack_upper_bound;
157 static void check_stack_location (volatile char *addr)
159 if (addr >= stack_lower_bound && addr <= stack_upper_bound)
164 static void stackoverflow_handler (int sig)
167 check_stack_location (&dummy);
171 char mystack[2 * SIGSTKSZ];
173 struct sigaction action;
174 /* Install the alternate stack. */
175 altstack.ss_sp = mystack + SIGSTKSZ;
176 altstack.ss_size = SIGSTKSZ;
177 stack_lower_bound = (char *) altstack.ss_sp;
178 stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1;
179 altstack.ss_flags = 0; /* no SS_DISABLE */
180 if (sigaltstack (&altstack, NULL) < 0)
182 /* Install the SIGSEGV handler. */
183 sigemptyset (&action.sa_mask);
184 action.sa_handler = &stackoverflow_handler;
185 action.sa_flags = SA_ONSTACK;
186 if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0)
188 /* Provoke a SIGSEGV. */
192 [gl_cv_sigaltstack_low_base=yes],
193 [gl_cv_sigaltstack_low_base=no],
194 [gl_cv_sigaltstack_low_base=cross-compiling])])
195 if test "$gl_cv_sigaltstack_low_base" = no; then
196 AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1],
197 [Define if sigaltstack() interprets the stack_t.ss_sp field
198 incorrectly, as the highest address of the alternate stack range
199 rather than as the lowest address.])
202 AC_CACHE_CHECK([for precise C stack overflow detection],
203 [gl_cv_sys_xsi_stack_overflow_heuristic],
204 [dnl On Linux/sparc64 (both in 32-bit and 64-bit mode), it would be wrong
205 dnl to set HAVE_XSI_STACK_OVERFLOW_HEURISTIC to 1, because the third
206 dnl argument passed to the segv_handler is a 'struct sigcontext *', not
207 dnl an 'ucontext_t *'. It would lead to a failure of test-c-stack2.sh.
208 case "${host_os}--${host_cpu}" in
210 gl_cv_sys_xsi_stack_overflow_heuristic=no
219 # include <ucontext.h>
222 # include <sys/types.h>
223 # include <sys/time.h>
224 # include <sys/resource.h>
227 # define SIGSTKSZ 16384
232 char buffer[2 * SIGSTKSZ];
236 } alternate_signal_stack;
239 # define find_stack_direction(ptr) STACK_DIRECTION
242 find_stack_direction (char const *addr)
245 return (! addr ? find_stack_direction (&dummy)
246 : addr < &dummy ? 1 : -1);
251 segv_handler (int signo, siginfo_t *info, void *context)
253 if (0 < info->si_code)
255 /* For XSI heuristics to work, we need uc_stack to
256 describe the interrupted stack (as on Solaris), and
257 not the currently executing stack (as on Linux). */
258 ucontext_t const *user_context = context;
259 char const *stack_min = user_context->uc_stack.ss_sp;
260 size_t stack_size = user_context->uc_stack.ss_size;
261 char const *faulting_address = info->si_addr;
262 size_t s = faulting_address - stack_min;
263 size_t page_size = sysconf (_SC_PAGESIZE);
264 if (find_stack_direction (0) < 0)
266 if (s < stack_size + page_size)
277 struct sigaction act;
281 /* Use the midpoint to avoid Irix sigaltstack bug. */
282 st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ;
283 st.ss_size = SIGSTKSZ;
284 r = sigaltstack (&st, 0);
288 sigemptyset (&act.sa_mask);
289 act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
290 act.sa_sigaction = segv_handler;
291 #if FAULT_YIELDS_SIGBUS
292 if (sigaction (SIGBUS, &act, 0) < 0)
295 if (sigaction (SIGSEGV, &act, 0) < 0)
299 static volatile int *
300 recurse_1 (volatile int n, volatile int *p)
303 *recurse_1 (n + 1, p) += n;
307 recurse (volatile int n)
310 return *recurse_1 (n, &sum);
316 #if HAVE_SETRLIMIT && defined RLIMIT_STACK
317 /* Before starting the endless recursion, try to be friendly
318 to the user's machine. On some Linux 2.2.x systems, there
319 is no stack limit for user processes at all. We don't want
320 to kill such systems. */
322 rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
323 setrlimit (RLIMIT_STACK, &rl);
326 result = c_stack_action ();
332 [gl_cv_sys_xsi_stack_overflow_heuristic=yes],
333 [gl_cv_sys_xsi_stack_overflow_heuristic=no],
334 [gl_cv_sys_xsi_stack_overflow_heuristic=cross-compiling])
339 if test "$gl_cv_sys_xsi_stack_overflow_heuristic" = yes; then
340 AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1],
341 [Define to 1 if extending the stack slightly past the limit causes
342 a SIGSEGV, and an alternate stack can be established with sigaltstack,
343 and the signal handler is passed a context that specifies the
344 run time stack. This behavior is defined by POSIX 1003.1-2001
345 with the X/Open System Interface (XSI) option
346 and is a standardized way to implement a SEGV-based stack
347 overflow detection heuristic.])
352 AC_DEFUN([gl_PREREQ_C_STACK],
353 [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC])
355 AC_CHECK_FUNCS_ONCE([sigaltstack])
356 AC_CHECK_DECLS([sigaltstack], , , [[#include <signal.h>]])
358 AC_CHECK_HEADERS_ONCE([ucontext.h])
360 AC_CHECK_TYPES([stack_t], , , [[#include <signal.h>]])
362 dnl c-stack does not need -lsigsegv if the system has XSI heuristics.
363 if test "$gl_cv_sys_xsi_stack_overflow_heuristic" != yes; then
365 if test "$gl_cv_lib_sigsegv" = yes; then
366 AC_SUBST([LIBCSTACK], [$LIBSIGSEGV])
367 AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV])
372 AC_DEFUN([gl_C_STACK],
374 dnl Prerequisites of lib/c-stack.c.